> For the complete documentation index, see [llms.txt](https://docs.solanavibestation.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.solanavibestation.com/api-reference/rewind.md).

# Rewind

Rewind is Solana Vibe Station's historical account state and simulation service. It answers questions the standard Solana RPC can't — what an account looked like at any past slot, every write to an account across a slot range, and what a transaction would have done if it had run earlier against the exact state it ran on.

### What you can do with Rewind

* **Look up historical account state.** `getHistoricalAccountInfo` and `getMultipleHistoricalAccounts` return account data at any position — end-of-slot, exact `(slot, writeVersion)`, or anchored immediately before / after a known transaction so you don't have to know the slot in advance. Both are wire-compatible supersets of Solana's `getAccountInfo` / `getMultipleAccounts` — standard SDKs deserialize the response unchanged and ignore the extra `rewind*` fields.
* **Walk an account's change history.** `getAccountChanges` returns paginated, newest-first per-write history for one pubkey across a slot range. Each row carries a `dataHash`, `txnSignature`, `dataChanged`, and (opt-in) the raw data blob.
* **Compare two points.** `getAccountDiff` returns full AccountInfo for two independently positioned points plus a structural summary (`lamportsDelta`, `ownerChanged`, `dataChanged`, …). The idiom `anchorA: before / anchorB: after` gives you exactly one transaction's per-account state transition in a single round-trip.
* **Replay transactions.** `simulateHistoricalTransaction` runs a fully-signed transaction through the SVM against the archive's exact state at a chosen position — same feature set, sysvars, address-lookup tables, and program bytecode the network had at that moment. Post-mortems, "what did this see?" debugging, and what-if analysis with `accountOverrides`.
* **Read the runtime that was.** `getHistoricalFeatureSet` returns the feature gates active at a slot — the same information you'd derive from `Feature111…` accounts, but tracked over time. Anyone replaying old transactions needs this.
* **Inspect coverage.** `getRewindCoverage` reports the current `earliestSlot` / `latestSlot`, gap ranges, and the days of history your key is entitled to (`windowDays`). Critical for audit and trust.
* **Liveness.** `getHealth` is Solana-compatible; existing client libraries and load-balancer health checks work unmodified.

### Endpoint

Rewind lives on its own subdomain:

```
https://rewind.solanavibestation.com
```

POST JSON-RPC 2.0 to the root path. Authentication is the standard SVS scheme — `Authorization: <api-key>` header or `?api_key=<api-key>` query parameter. Your key's plan controls both the rate limit and the number of days of history you can reach.

### Methods

<table data-search="false"><thead><tr><th>Method</th><th>Purpose</th></tr></thead><tbody><tr><td><code>getHistoricalAccountInfo</code></td><td>One account at a chosen point in history.</td></tr><tr><td><code>getMultipleHistoricalAccounts</code></td><td>Up to 100 accounts at one shared point in history.</td></tr><tr><td><code>getAccountChanges</code></td><td>Every write to one account in a slot range, newest first.</td></tr><tr><td><code>getAccountDiff</code></td><td>One account at two points, with a structural summary.</td></tr><tr><td><code>getHistoricalFeatureSet</code></td><td>Runtime feature gates active at a slot.</td></tr><tr><td><code>simulateHistoricalTransaction</code></td><td>Replay a transaction against archive state at a chosen position.</td></tr><tr><td><code>getRewindCoverage</code></td><td>Archive coverage, gaps, and your key's window.</td></tr><tr><td><code>getHealth</code></td><td>Solana-compatible liveness probe.</td></tr></tbody></table>

Anything else returns `-32601 Method not found`.

### Positioning a query

Every read method and the simulator share one positioning vocabulary. Every endpoint that needs a historical position accepts one of:

* **End-of-slot** — `slot: N` positions at the newest version of the account at or before the end of slot N.
* **Inside a slot** — `slot: N, writeVersion: W` positions at the newest version at or before `(N, W)`. `writeVersion` values come from `getAccountChanges` rows and are stable — they identify one specific write.
* **Per-transaction anchored** — `anchor: { signature, position }` positions immediately before (default) or after a known transaction. The slot is resolved from the signature index, so you don't have to know it. Useful for "what state did this tx see?" / "what did it leave behind?" workflows. When the transaction was the first writer in its slot, `before` resolves to the end of the previous slot.

One of `slot` or `anchor` is always required.

The actual position of the version served is echoed back in `value.rewindSlot` / `value.rewindWriteVersion`. When either differs from what you asked for, the state was carried forward from an earlier write. That pair is a stable cache key and, importantly, a valid `before` cursor for `getAccountChanges`.

`getAccountDiff` accepts positioning independently per side via `slotA` / `writeVersionA` / `anchorA` and their `B` counterparts. `getAccountChanges` uses `[fromSlot, toSlot]` for the range and either a `{ slot, writeVersion }` `before` cursor from the previous page's `next`, or an `anchor` cursor to start pagination at a known transaction.

### Archive coverage and your window

Rewind keeps a rolling window of recent history. Your API key's plan sets how much of that window your calls can reach — see Tiers below. `getRewindCoverage` reports the effective `earliestSlot`, `latestSlot`, and your key's `windowDays` in one call.

The coverage response also lists any **gaps** — slot ranges where ingest is incomplete. There are two kinds:

* **Real gaps** (`partial`, `missing`, `unknown`). Point reads and simulations that resolve into these refuse with `-32018` rather than silently serving stale at-or-before data. Pass `tolerateGaps: true` to explicitly accept the older answer. `getAccountChanges` doesn't refuse — it surfaces intersecting gaps inline via `value.gaps[]` so walkers can see discontinuities in their stream.
* **Skipped slots.** Leader-skipped slots that produced no block on chain. These are not archive failures, they don't appear as gaps, and they don't trigger refusal — the at-or-before answer is genuinely correct.

### Filtered accounts

To keep the archive efficient, Rewind does not archive **Vote-owned accounts** (they are rewritten every slot). Their existence and owner are recorded, so:

* A read that touches a Vote account is refused with `-32017` (`data` names the pubkey and owner) — rather than silently answered with `null`.
* A Vote account the archive has never observed at all still reads as `null`.
* A simulation whose transaction invokes the Vote program or loads a Vote-owned account (directly or through CPI) also refuses with `-32017`.

Typical workloads — DeFi swaps, arbitrage analysis, liquidations, NFT marketplace flows — never touch the filtered class.

### Error codes

All Rewind errors come back via the standard JSON-RPC `error` envelope.

<table data-search="false"><thead><tr><th>Code</th><th>Meaning</th></tr></thead><tbody><tr><td><code>-32600</code></td><td>Invalid request — <code>jsonrpc</code> is not <code>"2.0"</code>.</td></tr><tr><td><code>-32601</code></td><td>Method not found.</td></tr><tr><td><code>-32602</code></td><td>Invalid params — malformed or conflicting parameters; the message says which.</td></tr><tr><td><code>-32603</code></td><td>Internal error — transient; safe to retry.</td></tr><tr><td><code>-32005</code></td><td>Node is unhealthy — <code>getHealth</code> only.</td></tr><tr><td><code>-32014</code></td><td>Slot not available — position is above <code>latestSlot</code>. Query a live RPC for it.</td></tr><tr><td><code>-32015</code></td><td>Slot before earliest — position is below <code>earliestSlot</code>, or (rare) an account's history at it has aged out (<code>data.lastWriteSlot</code> present).</td></tr><tr><td><code>-32016</code></td><td>Signature not found — the anchor transaction is not indexed.</td></tr><tr><td><code>-32017</code></td><td>Filtered account — the account (or one the simulated transaction needs) belongs to a class the archive does not track: Vote.</td></tr><tr><td><code>-32018</code></td><td>Slot in archive gap — position falls in a <code>partial</code>, <code>missing</code>, or <code>unknown</code> slot. <code>data</code> carries the gap bounds.</td></tr></tbody></table>

The `-32014` / `-32015` split lets you route "too new — go to live RPC" and "too old — outside the archive window" to different UX. `-32016` is distinct so callers can tell "signature not indexed" apart from "out of range".

### Tiers

Access is metered per API key. Two plans are available today; Enterprise is coming soon.

| **Starter** (trials)         | 1 day        | 5 req/s, burst 5     | 1 req/s, burst 1   |
| ---------------------------- | ------------ | -------------------- | ------------------ |
| **Pro**                      | 30 days      | 50 req/s, burst 50   | 10 req/s, burst 10 |
| **Enterprise** (coming soon) | Full archive | 250 req/s, burst 250 | 50 req/s, burst 50 |

Your key's window is reflected in `getRewindCoverage`'s `windowDays` and in the effective `earliestSlot` the response returns. Positions below your floor are refused with `-32015`, the same code you'd see for anything below the archive floor. Anchor signatures, `preStateSlot`, and `accountOverrides.loadAt` positions inside a simulation are all checked the same way.

Contact the SVS team for Enterprise access or higher limits.

### Client SDKs

Typed clients ship for every method above, with the same error codes and helper utilities:

<table><thead><tr><th>Package</th><th>Registry</th><th>Language</th><th data-hidden>Notes</th></tr></thead><tbody><tr><td><a href="https://crates.io/crates/svs-rewind"><code>svs-rewind</code></a></td><td>crates.io</td><td>Rust</td><td><code>zstd</code> cargo feature for <code>base64+zstd</code> decoding.</td></tr><tr><td><a href="https://www.npmjs.com/package/@solanavibestation/rewind"><code>@solanavibestation/rewind</code></a></td><td>npm</td><td>TypeScript</td><td>Zero runtime dependencies, <code>fetch</code>-based.</td></tr></tbody></table>

Both add the same helpers on top of the raw calls: a change walker that pages `getAccountChanges` and surfaces `gaps`; a transaction view (`before`/`after` in one call, one or many accounts); a coverage guard that classifies a slot as offline before you spend a call on it; a chunked batch reader with truncation-resubmit; data decoding; and an opt-in retry policy that never retries `-32602`, `-32014`, `-32015`, `-32016`, or `-32017`.

### Compatibility notes

* `getHistoricalAccountInfo` and `getMultipleHistoricalAccounts` responses are strict supersets of Solana's; SDKs such as `@solana/web3.js` and `solana-py` deserialize them as ordinary `AccountInfo` objects and ignore the `rewind*` fields.
* `context.apiVersion` is `rewind-<version>` rather than a Solana version string.
* `commitment` is accepted everywhere and ignored — only rooted data is archived.
* `simulateHistoricalTransaction` mirrors Solana's `simulateTransaction` shape (`err`, `logs`, `accounts`, `unitsConsumed`, `returnData`, `innerInstructions`) plus `rewind*` extensions; `sigVerify` and `replaceRecentBlockhash` are accepted and ignored.
* `getAccountChanges`, `getAccountDiff`, `getRewindCoverage`, `getHistoricalFeatureSet` have no Solana RPC analogue.

### Need help?

For questions about Rewind, feature requests, wider archive windows, or Enterprise access, contact the SVS team via Discord or your customer portal account.
