Quickstart
1
Get Access
Parsed Streams is in closed beta. The Helius team whitelists your project id and shares the connection endpoint with you. To join the closed beta, apply here.Authenticate with your project’s API key, passed as the
api-key query parameter (or the x-api-key header).2
Connect
wscat
3
Subscribe with a Filter
Send The response
parsedTransactionSubscribe with a filter and optional options:result is an integer subscription id:4
Read a Notification
Every matching transaction arrives as a
parsedTransactionNotification, already decoded, with matchedIndexes pointing at the instructions your filter hit. See Notifications for the full shape.5
Unsubscribe
Guides
Track Jupiter Swaps
Use
describeProgram to build a filter you can trust before you subscribe.Track Pump.fun Mints
A reconnect-safe listener that logs every new Pump.fun token deploy.
Handling Reconnects
Survive idle timeouts and deploys, then backfill exactly what you missed.
Protocol Reference
Parsed Streams uses JSON-RPC 2.0 over a single WebSocket connection. Each request receives a response with the sameid. A subscription then pushes parsedTransactionNotification messages until you unsubscribe or disconnect.
Subscribe
SendparsedTransactionSubscribe with a filter and optional options. The response result is an integer subscription id.
Request
Response
Filter fields
At least one ofprograms or accounts.include is required. The fields you set combine with AND: an instruction must satisfy all of them to match.
string[]
Program IDs to match (base58 addresses, not names). An instruction matches if its program is in this list. OR within the list.
string[]
Decoded instruction names, such as
route. Matched exactly first, then with a case and separator insensitive fallback, so sharedAccountsRoute also matches the wire name shared_accounts_route. OR within the list. Only instructions whose name the catalog could identify can match, so take names from describeProgram.string[]
Account addresses. An instruction matches if any of these appears in its account list. OR within the list. Works for every instruction, decoded or not. The program id itself does not count as an account here.
object
A map of decoded account role name to address, such as
{ "user_transfer_authority": "<pubkey>" }. Every entry must hold (AND across entries), and the instruction must be decoded for this to apply. Role names match exactly, with no case folding, so copy them from describeProgram rather than guessing.boolean
default:"false"
Include instructions from failed transactions.
boolean
default:"true"
Inner (CPI) instructions are eligible to match. Set
false to match top-level instructions only.-32602 rather than silently ignored, so typos fail loudly instead of matching nothing.
Options
The second param is optional.string
default:"confirmed"
Only
confirmed is supported.string
default:"full"
What each notification carries.
full: the whole transaction, every instruction, plus matchedIndexes pointing at the filter hits. matched: only the instructions that matched, no index list. raw: matched instructions only, each reduced to its position, programId, and base58 data blob, with no decoded fields and no accountKeys array. Use matched when bandwidth matters more than context (full payloads average roughly three times the size), and raw when you decode instruction data yourself and only need the bytes.Notifications
One notification per matching transaction per subscription. With the defaultdetails: "full":
transactionis the full context.feeis in lamports.accountKeysis the complete key list, including keys loaded from address lookup tables, in the same order the chain reports them.feePayeris alwaysaccountKeys[0].errorcarries the transaction error as structured JSON, for example{"InstructionError": [2, {"Custom": 6001}]}, whenstatusis"error".summaryhas one shape everywhere it appears: atype(such asswaportransfer), a human-readabledescription, and a structuredparsedDatapayload when the parser recognizes the action — for a swap: the protocol, amounts, and mints.transaction.summarylabels the transaction’s headline action; each recognized instruction carries its ownsummarywith the same shape. To collect every swap in a transaction, iterateinstructionsand readsummary.parsedDatawheresummary.typeis"swap".nativeTransfersandtokenTransferslist the SOL and token movements the parser extracted from the whole transaction, in the same shape the Parsed Events API returns, so stream and API consumers can share processing code. Both are always present, possibly empty.instructionsis every instruction of the transaction in execution order: each top-level instruction followed by its inner instructions. Each entry carries its own position:topIndexis which top-level instruction it belongs to (starting at 0),innerIndexis its position among that instruction’s inner calls (nullmeans it is the top-level instruction itself), andstackHeightis the call depth (1 for top level). Use these, not the array position.matchedIndexesare indices intoinstructionstelling you which ones your filter actually hit. The rest are there for context. Withdetails: "matched"the array contains only the hits andmatchedIndexesis absent.decodednames are snake_case (in_amount,user_transfer_authority), as published in the program’s IDL. Integer arguments are commonly strings ("1000000") because u64 values do not fit in JavaScript numbers.blockTimeis currently alwaysnull. Do not build on it.- Expect a mix of decoded and undecoded instructions inside one transaction: a fully decoded swap can sit next to an unrecognized memo. Branch on
decoded: when it isnull, the instruction carriesrawData(base58 bytes) andrawAccounts(plain pubkey list) instead, so you always have something to work with.
details: "raw" the value shrinks to transaction meta and blobs. accountKeys, nativeTransfers, tokenTransfers, matchedIndexes, and all decoded fields are gone (the transaction summary is still included); each matched instruction is its position, its program, and its data bytes in base58, exactly as they appear on chain (present even for instructions the catalog could have decoded):
Unsubscribe
true if the subscription existed and was yours. Notifications stop immediately. Closing the connection removes all its subscriptions.
Discovery
The most common failure with this kind of API is a filter that is valid but matches nothing, usually a guessed instruction or role name.describeProgram prevents that by returning the exact names the matcher compares against:
Request
Response
jupiter, and a name lookup can resolve to the older one). If you do look up by name, check that result.id is the program you intend to subscribe to.
Recommended flow: describeProgram to get the exact instruction and role names, build the filter with those names, then subscribe. The Track Jupiter Swaps guide walks through this end to end.
Limits
Errors
Errors follow JSON-RPC 2.0:{ "error": { "code": <int>, "message": "<text>" }, "id": <id> }. Messages say exactly what was wrong and where.
Connections can also close with a WebSocket close code — see Handling Reconnects for what each one means and how to recover.