> 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/quickstart.md).

# Quickstart

You need an API key with Rewind enabled (Starter for trials, Pro for production — see Tiers). Every example below hits `https://rewind.solanavibestation.com` with the key in the `Authorization` header.

### 1. Check what you can reach

Before anything else, ask the archive what window your key sees. This is also the call to make when you're not sure why a query was refused.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://rewind.solanavibestation.com \
  -H "Content-Type: application/json" \
  -H "Authorization: $SVS_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"getRewindCoverage","params":[{"includeGaps":false}]}'
```

{% endtab %}

{% tab title="TypeScript" %}

```ts
import { RewindClient } from "@solanavibestation/rewind";

const rewind = new RewindClient("https://rewind.solanavibestation.com", {
  apiKey: process.env.SVS_API_KEY,
});

const cov = await rewind.getRewindCoverage({ includeGaps: false });
console.log(`slots ${cov.earliestSlot}..${cov.latestSlot}, window ${cov.windowDays ?? "full"} days`);
```

{% endtab %}

{% tab title="Rust" %}

```rust
use svs_rewind::{Client, CoverageConfig};

let client = Client::new("https://rewind.solanavibestation.com")?
    .with_api_key(std::env::var("SVS_API_KEY")?);

let cov = client.get_rewind_coverage(&CoverageConfig { include_gaps: Some(false), ..Default::default() }).await?;
println!("slots {:?}..{}, window {:?} days", cov.earliest_slot, cov.latest_slot, cov.window_days);
```

{% endtab %}
{% endtabs %}

You'll get back something like:

```json
{
  "earliestSlot": 446259052,
  "latestSlot": 446843325,
  "slotRange": 584274,
  "missingSlotCount": 7,
  "skippedSlotCount": 467,
  "gapPercent": 0.0012,
  "gaps": null,
  "truncated": false,
  "windowDays": 30
}
```

Any position you ask for must sit between `earliestSlot` and `latestSlot`. Below the floor you get `-32015`; above the tip, `-32014` — go to a live RPC for that.

### 2. Read an account at a past slot

Pick a slot inside the window and a pubkey. The response is a normal Solana `AccountInfo` plus two extra fields telling you exactly which archived version you were served.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://rewind.solanavibestation.com \
  -H "Content-Type: application/json" \
  -H "Authorization: $SVS_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getHistoricalAccountInfo",
    "params": [
      "SysvarC1ock11111111111111111111111111111111",
      { "slot": 446800000, "encoding": "jsonParsed" }
    ]
  }'
```

{% endtab %}

{% tab title="TypeScript" %}

```ts
const { value } = await rewind.getHistoricalAccountInfo(
  "SysvarC1ock11111111111111111111111111111111",
  { slot: 446_800_000, encoding: "jsonParsed" },
);
console.log(value?.data, value?.rewindSlot, value?.rewindWriteVersion);
```

{% endtab %}

{% tab title="Rust" %}

```rust
use svs_rewind::{Encoding, Position, ReadConfig};

let cfg = ReadConfig::at(Position::Slot(446_800_000)).encoding(Encoding::JsonParsed);
let r = client.get_historical_account_info("SysvarC1ock11111111111111111111111111111111", &cfg).await?;
if let Some(a) = r.value { println!("{:?} {} {}", a.data, a.rewind_slot, a.rewind_write_version); }
```

{% endtab %}
{% endtabs %}

`rewindSlot` is the slot the returned version was actually written in. If it's lower than the slot you asked for, the account simply wasn't touched in between — the state carried forward. `value` is `null` if the account didn't exist yet at that position.

### 3. The three questions Rewind is built for

#### "What did this transaction do?"

Anchor both sides of a diff to one signature. You don't need to know the slot — Rewind resolves it from the signature.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://rewind.solanavibestation.com \
  -H "Content-Type: application/json" \
  -H "Authorization: $SVS_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getAccountDiff",
    "params": [
      "<pubkey>",
      {
        "anchorA": { "signature": "<sig>", "position": "before" },
        "anchorB": { "signature": "<sig>", "position": "after" }
      }
    ]
  }'
```

{% endtab %}

{% tab title="TypeScript" %}

```ts
import { transactionView } from "@solanavibestation/rewind";

const { value } = await transactionView(rewind, sig, pubkey);
console.log(value.diff?.lamportsDelta, value.diff?.dataChanged);
// value.a and value.b are the full before/after AccountInfo
```

{% endtab %}

{% tab title="Rust" %}

```rust
let v = client.transaction_view(sig, pubkey, None).await?;
if let Some(d) = v.value.diff { println!("{} {}", d.lamports_delta, d.data_changed); }
```

{% endtab %}
{% endtabs %}

#### "Show me everything that happened to this account"

`getAccountChanges` returns one row per write, newest first, with a cursor for the next page. The SDK walkers handle the cursor loop and surface archive gaps as they go.

{% tabs %}
{% tab title="cURL" %}

```bash
# First page; pass value.next back as "before" to fetch the next one
curl -X POST https://rewind.solanavibestation.com \
  -H "Content-Type: application/json" \
  -H "Authorization: $SVS_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getAccountChanges",
    "params": [
      "<pubkey>",
      { "fromSlot": 446700000, "toSlot": 446800000, "limit": 100 }
    ]
  }'
```

{% endtab %}

{% tab title="TypeScript" %}

```ts
import { iterAccountChanges } from "@solanavibestation/rewind";

for await (const row of iterAccountChanges(rewind, pubkey, { fromSlot: 446_700_000, toSlot: 446_800_000 })) {
  if (row.dataChanged) console.log(row.slot, row.writeVersion, row.txnSignature);
}
```

{% endtab %}

{% tab title="Rust" %}

```rust
use svs_rewind::ChangesConfig;

let mut w = client.walk_account_changes(pubkey, ChangesConfig::range(446_700_000, 446_800_000));
while let Some(page) = w.next_page().await? {
    for row in page.changes.iter().filter(|r| r.data_changed) {
        println!("{} {} {:?}", row.slot, row.write_version, row.txn_signature);
    }
}
```

{% endtab %}
{% endtabs %}

Filter on `dataChanged` to skip writes that only moved lamports. Pass `includeData: true` with an `encoding` if you want the bytes on each row (page size drops to 50).

#### "Why did this transaction fail?"

Re-run it against the exact state it saw. Anchor the simulation to the transaction's own signature with `position: "before"` and you get the same logs, error and compute units the network produced.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://rewind.solanavibestation.com \
  -H "Content-Type: application/json" \
  -H "Authorization: $SVS_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "simulateHistoricalTransaction",
    "params": [
      "<base64 transaction>",
      {
        "anchor": { "signature": "<sig>", "position": "before" },
        "innerInstructions": true
      }
    ]
  }'
```

{% endtab %}

{% tab title="TypeScript" %}

```ts
const { value } = await rewind.simulateHistoricalTransaction(txBase64, {
  anchor: { signature: sig, position: "before" },
  innerInstructions: true,
});
console.log(value.err, value.unitsConsumed);
for (const line of value.logs) console.log(line);
```

{% endtab %}

{% tab title="Rust" %}

```rust
use svs_rewind::SimulateConfig;

let mut cfg = SimulateConfig::around_transaction(sig, false);
cfg.inner_instructions = Some(true);
let r = client.simulate_historical_transaction(tx_b64, &cfg).await?;
println!("{:?} {}", r.value.err, r.value.units_consumed);
for line in &r.value.logs { println!("{line}"); }
```

{% endtab %}
{% endtabs %}

To ask "would it have succeeded if…", add `accountOverrides` — see the `simulateHistoricalTransaction` reference.
