# programSubscribe

> Streams an update for every account owned by a program, one notification per changed account.

Source: https://docs.constant-k.com/rpc/websocket/programsubscribe/

`programSubscribe` replaces opening one `accountSubscribe` per account when a whole program's account set is being watched: each notification names the `pubkey` that changed alongside its new state, equivalent to a single row of `getProgramAccounts` pushed as it happens.

`filters` (`dataSize` and/or `memcmp`) apply server-side, limiting notifications from a busy program to relevant accounts; `encoding`, `dataSlice` and `commitment` behave exactly as they do for `accountSubscribe`. Pubsub notifications always carry `context`, so `withContext` has no effect here; it exists only for shape-compatibility with the HTTP `getProgramAccounts` config.

- Transport: WebSocket, JSON-RPC 2.0 over `wss://ws-newyork.constant-k.com:1337/ws?api-key=YOUR_API_KEY`
- Category: Subscriptions
- Availability: Operator and above

## Parameters

`params` is a positional JSON array, in this order:

- `programId` (string, required): Base58-encoded public key of the program whose owned accounts to watch.
- `config` (object, optional): Optional subscription settings.
  - `encoding` (string, optional, one of `base58`, `base64`, `base64+zstd`, `jsonParsed`, default `"base58"`): Format for the returned account `data`. `base58` is the legacy default (also accepted under its old name `binary`) and is slow for large accounts; `jsonParsed` asks the node to run a program-specific parser and silently falls back to `base64` when no parser exists for the account's owner.
  - `commitment` (string, optional, one of `processed`, `confirmed`, `finalized`, default `"finalized"`): How settled the account/transaction state must be before the node acts on it. `processed` is fastest and can roll back; `finalized` is slowest and never rolls back.
  - `filters` (object[], optional): Up to 4 server-side filters; an account must match all of them to be included.
  - `dataSlice` (object | null, optional): Returns only a byte range of `data` instead of the whole payload. Not compatible with `jsonParsed` encoding.
    - `offset` (integer, required, min 0): Byte offset to start the slice at.
    - `length` (integer, required, min 0): Number of bytes to return.
  - `withContext` (boolean, optional, default `false`): Pubsub notifications always carry `context`, so `withContext` has no effect here; it is accepted only for shape-compatibility with the HTTP `getProgramAccounts` config.

## Result

- `result` (integer, optional): The subscription id, returned once in the initial RPC response. Passed to `programUnsubscribe`, it cancels the stream.

## Notifications

Updates arrive as `programNotification` messages. `result.value.pubkey` is the account that changed; `result.value.account` is its new state, shaped like a single entry of `getProgramAccounts` (`lamports`, `data`, `owner`, `executable`, `rentEpoch`, `space`).

- `params.result` (object, optional)
  - `context` (object, optional): Response context, including the slot the data was read at.
    - `slot` (integer, optional): Slot number this applies to.
  - `value` (object, optional): The requested data; see the fields below.
    - `pubkey` (string, optional): Base58 public key of the account.
    - `account` (object, optional): The account's on-chain state.
      - `lamports` (integer, optional): Account balance, in lamports.
      - `data` (any, optional): Account data, shaped by the requested `encoding`.
      - `owner` (string, optional): Base58 address of the program (or, for a token account, the wallet) that owns this account.
      - `executable` (boolean, optional): Whether this account is a program.
      - `rentEpoch` (integer, optional): Legacy rent-exemption epoch; not meaningful for accounts created after rent-exempt minimums became mandatory.
      - `space` (integer, optional): Size of the account's data, in bytes.

## Unsubscribe

`programUnsubscribe`, called with the subscription id, returns `true` once the subscription is removed.

## Example: Subscribe to pump.fun bonding-curve account updates

Request (send after connecting):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "programSubscribe",
  "params": [
    "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
    {
      "encoding": "base64",
      "commitment": "confirmed"
    }
  ]
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "result": 26917954,
  "id": 1
}
```

Notification:

```json
{
  "jsonrpc": "2.0",
  "method": "programNotification",
  "params": {
    "result": {
      "context": {
        "slot": 447946428
      },
      "value": {
        "pubkey": "GG6GEDwxnP9cCcrjQJcpZK3QvQmMBgDC62LCSTDfw2eY",
        "account": {
          "lamports": 26827350,
          "data": [
            "F7f4N2DYrGDINy9L2uoCAH6pEwQAAAAAyJ8c/0jsAQDuuYMBAAAAAACAxqR+jQMAACb981GmPrsjUR7APLL4hdUzGl56okzTzseyFQPdSgAlAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
            "base64"
          ],
          "owner": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
          "executable": false,
          "rentEpoch": 18446744073709552000,
          "space": 151
        }
      }
    },
    "subscription": 26917954
  }
}
```

## Notes

- WebSocket access is included on the Operator plan and above; it is not available on Free.
- Concurrent connections are capped per API key: 10 on Operator, 50 on Blade Runner, 100 on Nexus.
- Subscribe and unsubscribe calls draw from the same global per-plan request-rate limit as HTTP calls: 50 req/s on Operator, 200 req/s on Blade Runner, 500 req/s on Nexus.
- Only subscription methods (the `*Subscribe` / `*Unsubscribe` family) are accepted on the WebSocket endpoint; standard request/response RPC methods must go over HTTPS instead.
- A `getHealth` request sent over the open socket on a regular interval serves as a keepalive; connections that go quiet can be dropped by intermediate load balancers.
- Each region has its own WebSocket hostname, for example `wss://ws-newyork.constant-k.com:1337/ws?api-key=YOUR_API_KEY`; every region is listed on the Endpoints page.
- The example follows the shape of a bonding-curve account update from the pump.fun program, which changes often enough to produce a notification within seconds of subscribing. Addresses in it are synthetic.
- A program with a very large or very active account set (the SPL Token program, for example) can produce far more notifications than a single connection can usefully process; `filters` narrow the set for a program that busy.

