Price Predictions
Price Prediction is the largest automation surface in the v2 API. You can read rounds and results anonymously, submit for the wallet your API key is pinned to, or let an end user submit from a partner site by signing a short-lived delegated intent with their verified wallet. For the product rules — how rounds are scheduled, how prizes are funded, and how winners are ranked — see Price Prediction.Operations
Base URL is
https://api.blank.build/api/v2. See Scopes for granting predictions:read, predictions:write, and predictions:delegate, and Conventions for pagination, caching, rate limits, retries, and idempotency.
Client setup
API keys are server-side only. Every example on this page is Node.js server code.{ data, metadata, response }. All prices are canonical decimal strings and all lamport amounts are unsigned integer strings — parse them with BigInt or a decimal library, never Number.
Rounds
listPredictionRounds returns rounds newest-first with cursor + limit (1–100, default 50).
You can only submit while a round is
open. locksAt is the scheduled boundary — treat the server’s status as authoritative rather than comparing clocks yourself, since the lock is a durable state transition, not a timestamp comparison.
listPredictionRounds returns 404 prediction_token_not_enabled.
Privacy model
This is the part most integrations get wrong. Exact predicted values are withheld until the round durably locks, so nobody can copy or front-run other entries.listRoundPredictions returns a discriminated union on visibility:
data holds at most 100 PublicPredictionEntry items: id, walletAddress, username, predictedPriceInSol, rank (nullable), distancePpm (nullable), and submittedAt.
Standings
listPredictionStandings returns { data: [...] } with at most 100 ranked entries. It returns 409 prediction_exact_values_locked until the round has durably locked.
PublicPredictionEntry fields plus a non-null rank and payoutLamports (unsigned integer string, nullable — null when no payout applies).
Your own prediction
getOwnedPrediction returns your full immutable prediction at any time, including before the round locks. The privacy rules apply to other people’s entries, not to yours.
Predictions created through this API always carry
submissionSource: "api_v2", which is how you tell your own automated entries apart from ones made in the Blank app.
Eligibility
getPredictionEligibility evaluates your API key’s pinned wallet against finalized chain state and returns the evidence behind the verdict.
This route can return
503 prediction_balance_unavailable when finalized balance data cannot be read. That is retryable — back off and try again.
Eligibility is advisory evidence, not a reservation. The server re-verifies
every condition when you submit, so an
eligible: true response can still be
followed by a 409 if the round locks or your balance drops in between. Check
eligibility to give users a clear reason up front, then handle the submit
errors anyway.round_not_open and insufficient_balance. Submission errors keep one primary code for normal branching and include any additional failures discovered during the same evaluation in problem.causes.
Submitting a prediction
createPrediction takes a strict body — extra properties are rejected.
Canonical means no leading zeros on the integer part and no trailing zeros in the fraction: send
"0.00001234", not "0.000012340".
201 with the immutable Prediction.
Idempotency
createPrediction requires a durable Idempotency-Key header: 8–128 printable ASCII characters. If you do not pass idempotencyKey in the mutation options, the SDK generates one and exposes it as result.metadata.idempotencyKey.
Persist the key before you send the request, and reuse it on every retry. A generated key that only exists in memory is useless if the process dies mid-flight, which is exactly the case idempotency exists for.
- Retention is 24 hours.
- A replayed response carries
Idempotent-Replayed: true; the SDK surfaces it asresult.metadata.idempotentReplayed. - Reusing a key with a different body returns
409 idempotency_key_reused. - Retrying while the first attempt is still in flight returns
409 idempotency_request_in_progresswithRetry-After: 1.
Raw HTTP
Run this from a server shell, never a browser:Submission errors
Read routes surface
404 prediction_round_not_found for unknown rounds, 404 prediction_not_found when getOwnedPrediction is called with an ID your key does not own, and 409 prediction_exact_values_locked when exact values are still withheld. The shared 401 invalid_api_key and 403 insufficient_scope apply to every authenticated route. See Error Model for the problem-details body and Troubleshooting for diagnosis.
Delegated submissions
Use delegation when users should enter a prediction on your site under their own Blank account. Create a dedicated server-side API key with onlypredictions:delegate. Never send that key or construct BlankClient in the browser.
The flow is server → browser wallet → server:
- Your server prepares an intent for the exact round, wallet, and price.
- Your browser gives
intent.messageto the connected wallet’ssignMessagemethod as UTF-8 bytes. - Your browser base58-encodes the 64-byte Ed25519 signature and sends the intent ID and signature to your server.
- Your server submits them to Blank with a second durable idempotency key.
bs58; the Blank SDK remains server-only.
Prediction in the submission response, while owner-scoped reads and prediction webhooks remain private to the signing user’s Blank account.
All normal prediction eligibility errors can also be returned at submission time. A valid signature proves consent; it does not reserve eligibility or bypass the round, username, balance, or uniqueness rules.
When several requirements fail, inspect
problem.causes as well as the primary problem.code. Each cause has a canonical code, title, detail, and optional context. Balance failures include balanceRaw, minimumBalanceRaw, and evaluationSlot; closed-round failures include roundStatus and locksAt.
End to end
Find the open round, check eligibility, submit with a caller-owned durable key, then read the prediction back.prediction.submissionSource is "api_v2", and prediction.status starts as active. settlementEligible, distancePpm, and rank stay null until the round settles.
Reacting to rounds with webhooks
Polling works, but webhooks are how you drive a bot without a timer. Three event types cover the prediction lifecycle:
A typical loop: subscribe to
round.locked to fetch standings the moment they open up, and to round.settled to record results and payouts. Subscribe to prediction.submitted if you want a confirmation signal independent of your submit call’s HTTP response.
See Webhooks for endpoint registration, signature verification, replay, and delivery retries.