Documentation Index
Fetch the complete documentation index at: https://docs.hubra.app/llms.txt
Use this file to discover all available pages before exploring further.
POST /api/v1/broadcast requires a hubra_token on every call. This page explains why it exists and how to use it.
What it is
A HMAC token issued by/stake, /unstake, and /withdraw. The token is computed over the message bytes of the unsigned transaction the endpoint just built.
/broadcast alongside the signed transaction.
Why it exists
Without a gate,/broadcast would be a free Solana RPC for arbitrary signed transactions. The server has cost (RPC quota, MEV protection budget, Sanctum execute slots) on every broadcast; allowing arbitrary transactions opens a denial-of-service vector.
The HMAC token binds a specific broadcast to a specific Hubra-built transaction:
/broadcastrecomputes the HMAC over the signed transaction’s message bytes.- If it matches, the broadcast proceeds.
- If it does not,
/broadcastreturns403 forbidden.
Lifetime
Tokens are valid for ~2 minutes after issue. This matches Solana’s blockhash window: a transaction with an expired blockhash cannot be broadcast successfully anyway, so a longer-lived token would not help. If your token expires, rebuild via/stake, /unstake, or /withdraw to get a fresh one. The build is cheap.
Sanctum-specific fields
For Sanctum-routed flows, the broadcast also needssanctumKind and sanctum_order. These are returned alongside hubra_token in the build response:
hubra_token, route, sanctumKind, sanctum_order) to /broadcast. Sanctum’s execute endpoint independently validates the signed transaction against the original sanctum_order; without it, Sanctum rejects the broadcast.
For non-Sanctum flows, only hubra_token is needed.
What to save
When you call/stake or /unstake, save:
| Always | Sanctum-routed only | |
|---|---|---|
| Required | transaction, hubra_token | sanctumKind, sanctum_order |
sol-native-stake, also save stakeAccount (the new pubkey) — you need it for future deactivate / withdraw / instant unstake.
What you do not need
You do not need to:- Decode or parse the token.
- Refresh it manually (just rebuild if expired).
- Sign or transform it in any way.
- Persist it beyond the broadcast.
Error: token mismatch
If/broadcast returns 403 forbidden:
- The token has expired (>2 minutes since issue). Rebuild.
- The signed transaction’s message bytes do not match the unsigned bytes (you re-serialized differently). Make sure
tx.serialize()after signing produces the same message slice as the original. - The token belongs to a different transaction (you mixed up two parallel build responses).
/stake or /unstake, sign that new transaction, and broadcast with the new token.
See also
POST /broadcast
The endpoint that uses the token.
Errors
403 forbidden and other error slugs.