Get started
Errors
Errors use conventional HTTP status codes and a small JSON body you can branch on.
400 Bad Request
{
"error": "bad_request",
"message": "Invalid request body.",
"issues": [
{
"path": "ticketPriceUSDCents",
"message": "Expected number, received string"
}
]
}| Field | Meaning |
|---|---|
error | A stable, machine-readable code. Branch on this. |
message | A human explanation. Log it or show it to an operator; its wording may change. |
issues | On invalid bodies: each problem, with the field path it concerns. |
required | On insufficient_scope: the scope the key needs. |
retryAfter | On rate_limited: seconds until you may retry. |
Status codes
| Status | error | What to do |
|---|---|---|
| 400 | bad_request | The request is invalid, or the action is not allowed in the current state (for example, entries are closed). Fix the request; retrying the same one will not help. |
| 401 | missing_api_key, invalid_api_key | Check the Authorization header and the key. |
| 401 | missing_proof, no_agent_key, invalid_proof | Draws only: sign a fresh BitRaffle-Proof. See Signed requests. |
| 402 | payment_required | Draws only: your prepaid balance cannot cover the draw. The body says where to deposit. |
| 403 | insufficient_scope, forbidden | The key lacks a scope, or the action is switched off for this competition. |
| 404 | not_found | Not found, or not your organisation's. |
| 409 | conflict, already_registered, invalid_proof | The resource is in a state that conflicts with the request, or a draw proof was reused. |
| 412 | precondition_failed | Your organisation is not set up for this yet, for example card payments are not configured. |
| 429 | rate_limited | Wait Retry-After seconds. See Rate limits. |
| 500, 502, 503 | internal_error, bad_gateway, unavailable | Our side, or a payment provider or the blockchain. Retry with backoff. |
Retrying safely
- Retry
429afterRetry-After, and5xxwith exponential backoff (for example 1s, 2s, 4s, capped at a minute). - Do not retry other
4xxresponses unchanged. They describe the request, not a passing condition. - Reads are always safe to retry. For checkout, poll the session you already have rather than starting a second one.
- Revealing a draw again with identical inputs returns the same result without charging twice.