> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# preconfSubscribe

> Use preconfSubscribe on any paid Helius plan to stream Solana transactions before shredding, with Helius execution status and BAM pre-execution signals.

Start a subscription to [Preconfirmations](https://www.helius.dev/docs/pre-confirmations/overview.md) — transactions delivered before they are collected into entries and converted into shreds. This is the lowest-latency transaction signal Helius offers. One subscription streams both Helius preconfirmations, emitted the instant the leader executes the transaction and carrying its execution status, and [BAM preconfirmations](https://www.helius.dev/docs/pre-confirmations/overview.md#bam-preconfirmations), emitted when the validator commits to executing it. Use `includeSource` to select either source.

## Endpoints

`preconfSubscribe` is served from the Helius [Gatekeeper](https://www.helius.dev/docs/gatekeeper/overview.md) endpoint:

* `wss://beta.helius-rpc.com/?api-key=<API_KEY>`

The `beta` hostname refers to the Gatekeeper rollout, not the maturity of Preconfirmations — it will become the standard endpoint as traffic migrates to Gatekeeper.

> [!NOTE]
>
> The stream is not continuous. Coverage scales with the share of network stake
> forwarding to Helius or running BAM, so expect slots with no messages — handle
> these gaps gracefully. See [Coverage](https://www.helius.dev/docs/pre-confirmations/overview.md#coverage).

## Authorizations

**api-key** `string` *required*

Your Helius API key, passed as the `api-key` query parameter. Preconfs are available on all paid plans.

## Body

**params** `array`

Optional. Omit `params` to receive every transaction from both Helius and BAM. To narrow the stream, pass a filter object as the first element — filtering happens server-side, so you only pay for and receive the transactions you care about.

**Filter**

Every field is optional — a missing field means "no constraint" for that predicate, so an empty filter matches every transaction from both sources. Set fields combine with **AND**, evaluated in the order `includeSource` → `failed` → `regionInclude` → `signatures` → `accountExclude` → `accountRequired` → `accountInclude` → `signerExclude` → `signerInclude` → `instructions`.

**includeSource** `string[]` (default: \[])

Sources to receive. Supported values are `helius` and `bam`. Omit the field or pass an empty array to receive both sources. Use `["helius"]` or `["bam"]` to receive one source. Unknown values and non-array values return `-32602` (invalid params).

> [!NOTE]
>
> The deprecated `includeBam` filter remains available for backward compatibility. `includeBam: false` equals `includeSource: ["helius"]`. `includeBam: true` or an omitted field selects both sources. Do not send `includeBam` and `includeSource` together.

**failed** `boolean`

`true` returns only failed (reverted) transactions; `false` returns only successful transactions. Either value excludes Helius transactions with unknown status. Omit the field to receive all statuses. Preconfirmations with unknown status are still delivered if they match the source, region, account, and signer filters.

**regionInclude** `string[]`

If non-empty, the transaction must originate from **one of** these [regions](#region-codes). Transactions without region information are dropped when this is set.

**accountInclude** `string[]`

If non-empty, the transaction must reference **at least one** of these accounts (base58 pubkeys). Capped at 10,000 entries.

**accountExclude** `string[]`

The transaction is dropped if it references **any** of these accounts. Takes precedence over `accountInclude`. Capped at 10,000 entries.

**accountRequired** `string[]`

The transaction must reference **all** of these accounts. Capped at 10,000 entries.

**signerInclude** `string[]`

If non-empty, the transaction must be signed by **at least one** of these accounts. Capped at 10,000 entries.

**signerExclude** `string[]`

The transaction is dropped if it is signed by **any** of these accounts. Takes precedence over `signerInclude`. Capped at 10,000 entries.

**signatures** `string[]`

If non-empty, the transaction's first signature must match **one** of these base58 signatures. Capped at 1,000 entries.

**instructions** `object[]`

If non-empty, at least one top-level instruction must match **one** of these instruction filters. Capped at 16 entries.

**Instruction filter**

**programId** `string` *required*

The base58 pubkey of the program invoked by the instruction.

**memcmp** `object[]`

Compares decoded bytes at an offset in the instruction data. All entries must match. Capped at four entries.

Each entry requires a non-negative `offset` and a `bytes` string. The optional `encoding` is `base58`, `base64`, or `hex`, and defaults to `base58`. Each value must decode to 1–128 bytes.

**dataSize** `number`

The exact instruction data length in bytes. The maximum is 4,096 bytes.

An invalid source, pubkey, signature, instruction filter, or region code returns JSON-RPC error `-32602` (invalid params). Combining `includeSource` with the deprecated `includeBam` field also returns `-32602`. Instruction filters inspect top-level instructions only. They do not match instructions invoked through cross-program invocation (CPI). A `memcmp` end offset and `dataSize` must not exceed 4,096 bytes.

Account filters match more than the transaction's static account keys — Helius resolves v0 [address lookup tables](https://www.helius.dev/docs/glossary.md#address-lookup-table-alt) server-side, so `accountInclude`, `accountExclude`, and `accountRequired` also match accounts a transaction loads through an ALT.

### Region codes

| Code | Location | Code | Location |
| - | - | - | - |
| `slc` | Salt Lake City | `tyo` | Tokyo |
| `fra` | Frankfurt | `ams` | Amsterdam |
| `lon` | London | `dal` | Dallas |
| `pit` | Pittsburgh | `dub` | Dublin |
| `sgp` | Singapore | `mia` | Miami |
| `ewr` | Newark | `lax` | Los Angeles |
| `iad` | Ashburn | `sea` | Seattle |
| `hkg` | Hong Kong | `sqq` | Šiauliai, Lithuania |

For Helius preconfirmations the region is where Helius ingested the transaction. For BAM preconfirmations it is the regional BAM endpoint that emitted the preconfirmation, not where Helius ingested it. BAM's Singapore and Dallas endpoints map to `sgp` and `dal`.

## Response

**result** `integer`

Subscription id (needed to unsubscribe)

```json Request theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe",
  "params": [
    {
      "failed": false,
      "regionInclude": ["ewr", "fra"],
      "accountInclude": ["9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"]
    }
  ]
}
```

```json Helius only theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe",
  "params": [{ "includeSource": ["helius"] }]
}
```

```json Instruction filter theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe",
  "params": [
    {
      "instructions": [
        {
          "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
          "memcmp": [
            {
              "offset": 0,
              "bytes": "66063d1201daebea",
              "encoding": "hex"
            }
          ]
        }
      ]
    }
  ]
}
```

```javascript JavaScript theme={"system"}
const WebSocket = require('ws');

const ws = new WebSocket('wss://beta.helius-rpc.com/?api-key=<API_KEY>');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'preconfSubscribe' // Helius and BAM preconfirmations by default
    // Optional filter:
    // params: [{ failed: false, accountInclude: ['9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM'] }]
    // Helius preconfirmations only:
    // params: [{ includeSource: ['helius'] }]
  }));

  setInterval(() => ws.ping(), 30_000);
});

ws.on('message', (data, isBinary) => {
  // The subscribe acknowledgement arrives as a JSON text frame
  if (!isBinary) {
    const msg = JSON.parse(data.toString());
    if (msg.id === 1) console.log('Subscribed, ID:', msg.result);
    return;
  }

  // Notifications arrive as binary frames:
  // version (u8) | slot (u64 LE) | tx_index (u64 LE) | status (u8) | transaction bytes
  const buf = Buffer.from(data);
  const version = buf.readUInt8(0);
  if (version !== 1) return; // unknown schema version; update your decoder
  const slot = buf.readBigUInt64LE(1);
  const txIndex = buf.readBigUInt64LE(9); // always 0 for BAM; may be 0 for other sources
  const status = buf.readUInt8(17); // 0 = failed, 1 = success, 2 = unknown
  const txBytes = buf.subarray(18); // transaction in Solana wire format (legacy, v0, or v1)

  console.log('Preconfirmation:', { slot, txIndex, status, bytes: txBytes.length });
});
```

```json Response theme={"system"}
{ "jsonrpc": "2.0", "id": 1, "result": 24040 }
```

```text Notification (binary frame) theme={"system"}
version   u8              payload schema version, currently 1
slot      u64 (LE)        slot the transaction is scheduled in
tx_index  u64 (LE)        transaction index when available (always 0 for BAM)
status    u8              0 = failed, 1 = success, 2 = unknown
tx        bytes           transaction in Solana wire format (legacy, v0, or v1)
```

## Notifications

After the JSON acknowledgement, notifications are delivered as **binary** WebSocket frames (not JSON). Helius and BAM preconfirmations share the same layout. Each frame is a packed byte layout carrying a single transaction:

| Bytes | Field | Type | Description |
| - | - | - | - |
| 0 | `version` | `u8` | Payload schema version. Currently `1`. |
| 1–8 | `slot` | `u64` (little-endian) | The slot the transaction is scheduled in. |
| 9–16 | `tx_index` | `u64` (little-endian) | Index of the transaction within the slot, when available. BAM preconfirmations always report `0`; other sources may also report `0` when no transaction index is available. |
| 17 | `status` | `u8` | Transaction status: `0` = failed, `1` = success, `2` = unknown. |
| 18+ | `transaction` | `bytes` | The transaction in Solana wire format. See [Decoding the transaction](#decoding-the-transaction). |

The payload has no source field. Don't infer a BAM origin from `tx_index = 0`, since other sources may also report `0`.

> [!WARNING]
>
> **Always read and check the `version` byte first.** It is currently `1`. If
> Helius needs to update the payload format, the version will increment — branch
> on it so your decoder keeps working across schema changes.

A preconfirmation is an early signal, not a guarantee. The transaction has not yet landed onchain and could still fail or be dropped. Confirm landing through standard commitment checks before treating it as final.

### Decoding the transaction

The transaction bytes are forwarded exactly as the validator serialized them, in the standard wire encoding for the transaction's version. Legacy and v0 transactions use the signatures-first layout that `bincode` produces. Transaction v1 ([SIMD-0385](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md)) uses a message-first layout with signatures at the end, so `bincode` fails on v1 payloads.

Use a decoder that handles every version. In Rust, [`agave-transaction-view`](https://docs.rs/agave-transaction-view) parses legacy, v0, and v1 transactions in place and is the recommended option; [`wincode`](https://docs.rs/wincode) with a current Solana SDK `VersionedTransaction` also works. In JavaScript, make sure your library version supports transaction v1. See the [guide](https://www.helius.dev/docs/pre-confirmations/preconf-subscribe.md#decoding-the-transaction) for a Rust example.

## Duplicate notifications

Helius and BAM preconfirmations are deduplicated per source, not across sources. A small share of transactions reach Helius through both, so you can receive the same signature twice, and the two copies may report different slots. Deduplicate by signature on the client and make transaction-triggered actions idempotent. See the [guide](https://www.helius.dev/docs/pre-confirmations/preconf-subscribe.md#duplicate-notifications).

## Pricing

Preconfirmations are available on **all paid plans: Developer, Business, Professional, and Enterprise**. Free plans are not eligible. See [Credits](https://www.helius.dev/docs/billing/credits.md) for details.

Slots with zero delivered messages cost zero credits, even when the slot has preconfirmation [coverage](https://www.helius.dev/docs/pre-confirmations/overview.md#coverage). When a slot delivers at least one message, each open `preconfSubscribe` subscription is billed the greater of 300 credits or 10 credits per delivered message. Uncovered slots cost zero. See [Pricing](https://www.helius.dev/docs/pre-confirmations/overview.md#pricing) for source and region billing eligibility.

| Messages delivered in a covered slot | Credits billed |
| - | - |
| 0 | 0 |
| 10 | 300 |
| 30 | 300 |
| 100 | 1,000 |

Each concurrent subscription is billed independently when it receives at least one message. Close subscriptions you no longer need with [`preconfUnsubscribe`](https://www.helius.dev/docs/api-reference/pre-confirmations/preconfunsubscribe). With `includeSource: ["helius"]`, BAM-only covered slots are excluded from billing. When `regionInclude` is set, covered slots outside the selected regions cost zero for that subscription; matching slots are billed only when the subscription receives at least one message.

Billing is per message, not per unique signature. A transaction delivered by both Helius and BAM counts twice. Set `includeSource: ["helius"]` if you only want Helius preconfirmations.

> [!TIP]
>
> To control costs, consolidate account filters into one subscription where practical, use `regionInclude` to limit billing to the regions you need, set `includeSource: ["helius"]` when you do not need BAM, and monitor credits in the [Helius Dashboard](https://dashboard.helius.dev).

## Related

> [card] [Preconfirmations Overview](https://www.helius.dev/docs/pre-confirmations/overview.md)
>
> What Preconfirmations are and where they sit in the validator pipeline.

> [card] [preconfUnsubscribe](https://www.helius.dev/docs/api-reference/pre-confirmations/preconfunsubscribe.md)
>
> Stop a subscription by its id.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.