Skip to content

Developers · API v1

A versioned REST API, signed webhooks and a sandbox with generated data. This page covers the conventions that apply to every endpoint.

bash
# The sandbox base URL and key are issued together
export POOCRAFT_API="https://<your-sandbox-host>"
export POOCRAFT_KEY="pk_sandbox_••••••••"

curl "$POOCRAFT_API/api/v1/sportsbook/events?state=live" \
  --header "Authorization: Bearer $POOCRAFT_KEY"
Sandbox

The samples on this page are illustrative. They show conventions and shapes, not a contract. Final endpoints and payloads are confirmed, and production access is arranged, during onboarding.

Overview

The Poocraft API is a REST API served over HTTPS under /api/v1. Requests and responses are JSON. Every response carries an X-Request-Id header that you can quote when you contact us about a specific call.

The operator console is built on this API, so anything your team does in the interface can be automated. Access is scoped: a key only sees the tenant it belongs to and only does what its scopes allow.

Conventions

Base path
/api/v1
Transport
HTTPS only
Format
JSON, UTF-8
Amounts
Integers in minor units: 2500 is 25.00
Time
ISO 8601, UTC
Tracing
X-Request-Id on every response

Authentication

Authenticate every request with an API key sent as a bearer token: Authorization: Bearer <key>. Keys are created per environment and per integration, and the full value is shown once, at creation.

Each key carries scopes that limit what it can do. Give an integration only the scopes it needs: a reporting job should not hold a key that can move funds.

http
GET /api/v1/wallet/balances?player_id=pl_9041
Authorization: Bearer pk_sandbox_••••••••

Example scopes

Example scopes
ScopeAllows
wallet:readRead balances and transactions
wallet:writeDebit, credit and roll back
games:readRead the game catalog
launch:writeCreate launch sessions
sportsbook:readRead events, markets and prices
compliance:writeRequest compliance checks
webhooks:manageCreate and manage webhook endpoints
reports:readQuery events and exports

Scope names are examples. The scopes available to you are listed with your key.

A missing, malformed or revoked key returns 401 with the code unauthorized. A valid key without the required scope returns 403 with the code forbidden.

Keep keys on your servers. Never ship them in a browser or a mobile app. To rotate a key, create a new one, deploy it, then revoke the old one.

Idempotency

Networks fail, and a client cannot always tell whether a request was processed. Idempotency keys make retries safe: send an Idempotency-Key header with any request that changes state. For wallet operations the header is required.

How keys behave

  1. Use one unique value per logical operation, for example a UUID.
  2. The same key with the same body returns the original response. Nothing is posted twice, and the response contains "idempotent_replay": true.
  3. The same key with a different body is rejected with 422 and the code idempotency_mismatch.
  4. After a timeout or a 5xx response, retry with the same key. Do not generate a new key for a retry.
http
POST /api/v1/wallet/debit
Authorization: Bearer pk_sandbox_••••••••
Idempotency-Key: 7c1e9a52-0b7e-4f0e-9a51-2f6f3b1c8d10
Content-Type: application/json

{
  "player_id": "pl_9041",
  "amount": 2500,
  "currency": "EUR",
  "reference": "round_58210"
}

Response to a retried request

http
HTTP/1.1 200 OK
X-Request-Id: req_01HZX4W2

{
  "transaction_id": "txn_8f2a41",
  "status": "posted",
  "balance": { "amount": 147500, "currency": "EUR" },
  "idempotent_replay": true
}

Errors

Errors use conventional HTTP status codes and one JSON envelope. code is stable and safe to branch on. message is written for people and may change. request_id matches the X-Request-Id header.

http
HTTP/1.1 409 Conflict
X-Request-Id: req_01HZX7B3

{
  "error": {
    "code": "idempotency_mismatch",
    "message": "This Idempotency-Key was already used with a different request body.",
    "request_id": "req_01HZX7B3"
  }
}
HTTP status codes and error codes
StatusCodeMeaningWhat to do
400invalid_requestThe request is malformed or a field failed validation.Fix the request. Do not retry it unchanged.
401unauthorizedThe API key is missing, malformed or revoked.Check the Authorization header and the environment.
403forbiddenThe key is valid but lacks the required scope.Use a key that carries the scope.
404not_foundThe resource does not exist or is not visible to this key.Check the identifier and the environment.
409conflictThe request conflicts with the current state, such as rolling back a transaction twice.Read the current state before deciding what to do.
422idempotency_mismatchThe Idempotency-Key was already used with a different body.Use a new key for a new operation.
429rate_limitedThe key exceeded its rate limit.Wait for Retry-After, then retry.
500internal_errorSomething failed on our side.Retry with the same idempotency key. Quote request_id if it persists.

Pagination

List endpoints use cursor pagination. Each response contains a data array and a next_cursor. Pass that value as cursor to get the next page. When next_cursor is null, you have reached the end.

Cursors are opaque. Store them and send them back as they are; do not parse or construct them. A cursor stays valid for the query it came from, so keep filters unchanged while you page.

Pagination parameters
NameWhereMeaning
limitQueryPage size. Each endpoint documents its maximum.
cursorQueryThe next_cursor value from the previous response.
next_cursorResponseCursor for the next page, or null on the last page.
http
GET /api/v1/reports/events?type=wallet.transaction.posted&limit=50&cursor=c_eyJvIjo1MH0
Authorization: Bearer pk_sandbox_••••••••
http
HTTP/1.1 200 OK
X-Request-Id: req_01HZX6K8

{
  "data": [
    { "id": "evt_3c9d61", "type": "wallet.transaction.posted", "occurred_at": "2026-11-13T19:04:52Z" }
  ],
  "next_cursor": null
}

Rate limits

Rate limits apply per API key. The limits for your keys depend on the environment and on your agreement, so no figures are listed here. Every response reports the current limit and what is left of it in headers.

Rate limit headers
HeaderMeaning
RateLimit-LimitRequests allowed for this key in the current window.
RateLimit-RemainingRequests left in the current window.
RateLimit-ResetWhen the current window resets.
Retry-AfterSent with 429: the number of seconds to wait before retrying.

When a key exceeds its limit the API returns 429 with the code rate_limited. Wait for the time given in Retry-After, then retry with the same idempotency key. Read the headers rather than hard-coding a limit in your client.

http
HTTP/1.1 429 Too Many Requests
RateLimit-Limit: <requests allowed in the window>
RateLimit-Remaining: 0
RateLimit-Reset: <when the window resets>
Retry-After: <seconds to wait>
X-Request-Id: req_01HZX8QD

{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests for this API key.",
    "request_id": "req_01HZX8QD"
  }
}

Webhooks

Webhooks deliver events to an HTTPS endpoint that you register. Each endpoint subscribes to the event types it needs and has its own signing secret, shown once when the endpoint is created.

http
POST https://operator.example/webhooks/poocraft
X-Poocraft-Signature: t=1794600000,v1=5d41402abc4b2a76b9719d911017c592
Content-Type: application/json

{
  "id": "evt_3c9d10",
  "type": "wallet.transaction.posted",
  "data": { "transaction_id": "txn_8f2a41", "amount": 2500, "currency": "EUR" }
}

Signature

Every delivery carries an X-Poocraft-Signature header of the form t=<timestamp>,v1=<signature>. The signature is an HMAC-SHA256, hex encoded, computed with the endpoint secret over the string {t}.{payload}, where payload is the raw request body.

Verifying a delivery

  1. Read the raw request body before any JSON parsing.
  2. Split the header into t and v1.
  3. Compute HMAC-SHA256 over {t}.{payload} with your endpoint secret.
  4. Compare the result with v1 using a constant-time comparison.
  5. Reject deliveries whose t is older than the tolerance you choose.
  6. Deduplicate on the event id before acting.
ts
// Verify the signature before trusting a delivery
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(payload: string, header: string, secret: string) {
  const [t, v1] = header.split(",").map((part) => part.split("=")[1] ?? "");
  const expected = createHmac("sha256", secret).update(`${t}.${payload}`).digest("hex");
  return v1.length === expected.length && timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Retries

Respond with a 2xx status as soon as you have stored the event, and do the work asynchronously. Any other response, or a timeout, counts as a failure and the delivery is retried with increasing delays.

Deliveries can arrive more than once and out of order. Make handlers idempotent and use the event id to deduplicate.

Replay

Recorded events can be replayed to an endpoint, which is useful after an outage or when a new consumer comes online. A replayed delivery keeps the original event id and gets a new timestamp and signature, so the same verification and deduplication apply.

Sandbox

The sandbox mirrors the API surface with generated data. There are no real funds, no real players and no connection to live providers.

Sandbox keys are prefixed pk_sandbox_ and only work against the sandbox. Production keys are issued separately, during onboarding, and never share a prefix with sandbox keys.

What the sandbox includes

  • Generated players, balances, catalog entries and fixtures
  • A sandbox game adapter and feed adapter that simulate rounds and price changes
  • Webhook deliveries signed the same way as in production
  • Data you can reset when you want a clean start

Getting access

Sandbox access is set up by our team. Request a demo and tell us what you plan to integrate.

Request sandbox access

Versioning

The version is part of the path: /api/v1. Within a version we only make backwards-compatible changes: new endpoints, new optional parameters, new fields in responses and new event types.

Write clients that ignore fields and event types they do not recognise. Breaking changes ship under a new version path, and the timeline for moving between versions is agreed with integrated operators.

Endpoint reference

Six areas of the API, each with a sample request, a response and a related webhook.

Illustrative samples. Endpoints and payloads are finalised during onboarding, when production access is arranged.

Wallet API

Debit, credit and rollback operations against the ledger with idempotency on every write.

POST/api/v1/wallet/debit

http
POST /api/v1/wallet/debit
Authorization: Bearer pk_sandbox_••••••••
Idempotency-Key: 7c1e9a52-0b7e-4f0e-9a51-2f6f3b1c8d10
Content-Type: application/json

{
  "player_id": "pl_9041",
  "amount": 2500,
  "currency": "EUR",
  "reference": "round_58210"
}

Game Aggregation API

List games, create launch sessions and receive round results through one adapter contract.

POST/api/v1/launch/sessions

http
POST /api/v1/launch/sessions
Authorization: Bearer pk_sandbox_••••••••
Content-Type: application/json

{
  "game_id": "gm_ember_vault",
  "player_id": "pl_9041",
  "currency": "EUR",
  "locale": "en",
  "return_url": "https://operator.example/lobby"
}

Sportsbook Feed

Events, markets and price updates normalised from external sportsbook services.

GET/api/v1/sportsbook/events

http
GET /api/v1/sportsbook/events?sport=football&state=live
Authorization: Bearer pk_sandbox_••••••••

Player & Compliance Hooks

Integration points for KYC/AML providers, limits and responsible gaming actions.

POST/api/v1/compliance/checks

http
POST /api/v1/compliance/checks
Authorization: Bearer pk_sandbox_••••••••
Content-Type: application/json

{
  "player_id": "pl_9041",
  "action": "withdrawal",
  "amount": 25000,
  "currency": "EUR"
}

Webhooks

Signed event delivery with retries, replay and per-endpoint event selection.

POST/api/v1/webhooks/endpoints

http
POST /api/v1/webhooks/endpoints
Authorization: Bearer pk_sandbox_••••••••
Content-Type: application/json

{
  "url": "https://operator.example/webhooks/poocraft",
  "events": ["wallet.transaction.posted", "game.round.settled"]
}

Reporting API

Query operational events and export reports for finance, operations and compliance.

GET/api/v1/reports/events

http
GET /api/v1/reports/events?type=wallet.transaction.posted&from=2026-11-01&limit=50
Authorization: Bearer pk_sandbox_••••••••

Sandbox access

Tell us what you plan to integrate. We will set up sandbox access and walk your developers through the first calls.