{"openapi":"3.1.0","info":{"title":"Axiom Gaming Platform API","version":"0.1.0","summary":"Sandbox gaming infrastructure for developers.","description":"Axiom is a B2B gaming engine API. This contract describes the first four endpoints. GET /api/v1/games is live in sandbox and lists the published catalog. Player create, get, and list are live and tenant-scoped to the API key. Wallet is a sandbox virtual-credit ledger. Balance is derived from append-only transactions. POST /api/v1/sessions starts a synchronous Dice session: it debits stake, executes the engine, and credits payout when the result requires it. The catalog describes games. It does not execute them. POST /api/v1/webhooks registers an HTTPS endpoint for session.completed and session.cancelled. Webhook delivery is best-effort first delivery + durable delivery record + explicit retry. There is no automatic retry. GET /api/v1/audit lists a sanitized, cursor-paginated trail of business facts. Audit is not a source of truth for balances, sessions, or deliveries. GET /api/v1/organization and GET /api/v1/organization/entitlements expose the calling tenant and its resolved entitlements. The client does not send organizationId. The environment is sandbox-only and uses virtual credits. Axiom does not process real money, deposits, withdrawals, PIX, or cards."},"servers":[{"url":"/","description":"Current deployment"}],"tags":[{"name":"Games","description":"Sandbox game catalog."},{"name":"Players","description":"Players scoped to an organization."},{"name":"Wallet","description":"Virtual credit ledger for a player."},{"name":"Sessions","description":"Game session execution."},{"name":"Webhooks","description":"Signed HTTPS notifications for terminal sessions. Best-effort first delivery + durable delivery record + explicit retry."},{"name":"Audit","description":"Read-only sanitized business-fact trail. Tenant-scoped from the API key. Cursor-paginated. Does not replace Wallet, Session, or Webhook Delivery."},{"name":"Organization","description":"Read-only view of the calling organization and its resolved entitlements. Tenant is derived from the API key."}],"security":[{"sandboxApiKey":[]}],"paths":{"/api/v1/organization":{"get":{"tags":["Organization"],"operationId":"getOrganization","summary":"Get the calling organization","description":"Returns the organization derived from the API key. Query parameters cannot select another organization. There is no public create, update, or delete.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Calling organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/organization/entitlements":{"get":{"tags":["Organization"],"operationId":"getOrganizationEntitlements","summary":"Get resolved entitlements for the calling organization","description":"Resolves Subscription → Plan → plan entitlements for the API key tenant. Commercial plan names are not used for enforcement. Sandbox currently ships without limiting entitlements.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Resolved entitlements for the calling organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationEntitlements"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/games":{"get":{"tags":["Games"],"operationId":"listGames","summary":"List available sandbox games","description":"Returns games published for the sandbox catalog. The first game is Dice. Listing a game does not start a session or execute the game. Clients cannot choose an internal game version; the published version is returned.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Sandbox game catalog. Only active games in sandbox are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameListResponse"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/players":{"get":{"tags":["Players"],"operationId":"listPlayers","summary":"List players in the calling organization","description":"Returns players that belong to the organization derived from the API key. Query parameters cannot select another organization. Simple listing: every player for the tenant, newest first. No pagination cursor in this phase.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Players in the calling organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayerListResponse"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Players"],"operationId":"createPlayer","summary":"Create a sandbox player","description":"Creates a player in the organization derived from the API key. externalRef is required and unique per organization, not globally. organizationId in the body is rejected. Creating a player does not create a wallet or a game session.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlayerRequest"}}}},"responses":{"201":{"description":"Player created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Player"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/players/{playerId}":{"get":{"tags":["Players"],"operationId":"getPlayer","summary":"Get a player by id","description":"Looks up a player by id and the organization derived from the API key. A player that exists in another organization returns the same 404 as a missing player.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"playerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Player in the calling organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Player"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallets":{"post":{"tags":["Wallet"],"operationId":"createWallet","summary":"Create a virtual wallet for a player","description":"Creates an empty sandbox wallet for a player in the calling organization. One wallet per player. Does not credit any balance. organizationId in the body is rejected. Creating a player does not create a wallet.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWalletRequest"}}}},"responses":{"201":{"description":"Wallet created with balance 0.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallets/{walletId}":{"get":{"tags":["Wallet"],"operationId":"getWallet","summary":"Get a wallet by id","description":"Looks up a wallet by id and the organization derived from the API key. Balance is derived from the ledger. Cross-tenant lookups return 404.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"walletId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Virtual wallet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallets/{walletId}/transactions":{"get":{"tags":["Wallet"],"operationId":"listWalletTransactions","summary":"List wallet ledger entries","description":"Returns append-only ledger entries for the wallet, newest first. There is no public update or delete.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"walletId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Ledger entries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletTransactionListResponse"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallets/{walletId}/credit":{"post":{"tags":["Wallet"],"operationId":"creditWallet","summary":"Credit virtual credits","description":"Appends a credit entry. Amount is a positive integer. Idempotency-Key is required and replayed.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"walletId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditWalletRequest"}}}},"responses":{"200":{"description":"Credit applied or replayed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletOperationResponse"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallets/{walletId}/debit":{"post":{"tags":["Wallet"],"operationId":"debitWallet","summary":"Debit virtual credits","description":"Appends a debit entry if the derived balance is sufficient. Never allows a negative balance. Idempotency-Key is required and replayed.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"walletId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DebitWalletRequest"}}}},"responses":{"200":{"description":"Debit applied or replayed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletOperationResponse"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallets/{walletId}/refund":{"post":{"tags":["Wallet"],"operationId":"refundWallet","summary":"Refund virtual credits","description":"Appends a new refund entry. Never updates a previous transaction. reference identifies the operation being reversed and is unique per wallet among refunds.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"walletId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundWalletRequest"}}}},"responses":{"200":{"description":"Refund applied or replayed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletOperationResponse"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/players/{playerId}/wallet":{"get":{"tags":["Wallet"],"operationId":"getWalletByPlayer","summary":"Get a player's wallet","description":"Looks up the wallet for a player in the calling organization. A player or wallet in another organization returns 404.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"playerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Virtual wallet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/wallet":{"get":{"tags":["Wallet"],"operationId":"getWalletByPlayerQuery","summary":"Get a player's wallet by query","description":"Alias of GET /api/v1/players/{playerId}/wallet. playerId is a query parameter. Organization still comes from the API key.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"playerId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Virtual wallet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sessions":{"get":{"tags":["Sessions"],"operationId":"listGameSessions","summary":"List sessions in the calling organization","description":"Returns sessions of the organization derived from the API key, newest first. There is no pagination in the MVP.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Sessions of the calling organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameSessionListResponse"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Sessions"],"operationId":"createGameSession","summary":"Start a sandbox game session","description":"Starts a Dice session for a player in the calling organization. The server loads the published catalog game, validates config through the engine, debits stake, executes Dice, credits payout when the engine result requires it, and returns the completed session in the same request. After the session is persisted terminal, Axiom attempts at most one signed webhook POST. Webhook success or failure never changes the session or the ledger. organizationId in the body is rejected. Idempotency-Key is required and replayed.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}}},"responses":{"201":{"description":"Session created and settled, or replayed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameSession"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sessions/{sessionId}":{"get":{"tags":["Sessions"],"operationId":"getGameSession","summary":"Get a session by id","description":"Looks up a session by id and the organization derived from the API key. Cross-tenant lookups return 404.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Game session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameSession"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"operationId":"listWebhooks","summary":"List webhook endpoints in the calling organization","description":"Returns webhook endpoints of the organization derived from the API key. Cross-tenant endpoints are never included. Secrets are never returned.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Webhook endpoints of the calling organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListResponse"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"operationId":"createWebhook","summary":"Register an HTTPS webhook endpoint","description":"Registers an HTTPS URL for session.completed and/or session.cancelled. The signing secret is shown once on first create and never stored in plaintext. Replay of the same Idempotency-Key and payload omits the secret. organizationId in the body is rejected. Delivery guarantee: best-effort first delivery + durable delivery record + explicit retry. There is no worker or automatic retry.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}}},"responses":{"201":{"description":"Endpoint created. secret is present only on the first successful create, not on idempotent replay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{webhookId}":{"get":{"tags":["Webhooks"],"operationId":"getWebhook","summary":"Get a webhook endpoint by id","description":"Looks up a webhook by id and the organization derived from the API key. Cross-tenant lookups return 404. The signing secret is never returned.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Webhook endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Webhooks"],"operationId":"revokeWebhook","summary":"Revoke a webhook endpoint","description":"Revokes the endpoint. Revoked endpoints receive no further deliveries. Cross-tenant deletes return 404.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Webhook revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{webhookId}/deliveries":{"get":{"tags":["Webhooks"],"operationId":"listWebhookDeliveries","summary":"List deliveries for a webhook endpoint","description":"Returns delivery attempts for one endpoint in the calling organization. Newest first. The frozen payload is not listed here.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deliveries for the webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryListResponse"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/deliveries/{deliveryId}/retry":{"post":{"tags":["Webhooks"],"operationId":"retryWebhookDelivery","summary":"Retry a failed webhook delivery","description":"Re-sends the frozen payload of an existing delivery. Does not create a session, a ledger entry, or a second logical delivery. A delivery that already succeeded returns 409 and is not resent.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Retry result for the same delivery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/audit":{"get":{"tags":["Audit"],"operationId":"listAuditEvents","summary":"List sanitized audit events for the calling organization","description":"Returns business facts that already happened. Organization is derived from the API key. organizationId is never accepted as a trusted filter and is never returned. Results are cursor-paginated, newest first. Audit is not a financial ledger and does not include secrets, session seeds, or delivery lastError.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"type","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AuditEventType"}},{"name":"sessionId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"playerId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"walletId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"transactionId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"webhookId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"deliveryId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"apiKeyId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from pagination.nextCursor. Do not invent values."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Page of sanitized audit events.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditListResponse"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/audit/{eventId}":{"get":{"tags":["Audit"],"operationId":"getAuditEvent","summary":"Get one sanitized audit event","description":"Returns a single business fact belonging to the calling organization. A fact that exists for another tenant returns the same 404 as a missing row.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"name":"eventId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Sanitized audit event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditEvent"}}}},"400":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Standard error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"sandboxApiKey":{"type":"http","scheme":"bearer","bearerFormat":"aur_sk_sandbox","description":"Sandbox API key. Send as `Authorization: Bearer aur_sk_sandbox_...`. The organization is derived from the key. Games, players, wallet, sessions, webhooks, audit, and organization entitlements are available after a valid key."}},"parameters":{"RequestId":{"name":"X-Request-Id","in":"header","required":false,"description":"Optional client correlation id. Echoed when present.","schema":{"type":"string","format":"uuid"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Required for wallet credit, debit, and refund, player creation, session start, and webhook registration. The header is 16–64 characters. Wallet mutations, session create, and webhook create persist the key per organization and replay the original result. Reusing the same key for a different payload or operation returns 409 IDEMPOTENCY_CONFLICT. Player create still validates the header without replay.","schema":{"type":"string","minLength":16,"maxLength":64}}},"schemas":{"Error":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","requestId"],"properties":{"code":{"type":"string","enum":["NOT_IMPLEMENTED","UNAUTHORIZED","VALIDATION_ERROR","CONFLICT","GAME_NOT_FOUND","PLAYER_NOT_FOUND","WALLET_NOT_FOUND","WALLET_ALREADY_EXISTS","INSUFFICIENT_BALANCE","INSUFFICIENT_CREDITS","INVALID_AMOUNT","IDEMPOTENCY_CONFLICT","IDEMPOTENCY_REPLAY","SESSION_NOT_FOUND","WEBHOOK_NOT_FOUND","AUDIT_EVENT_NOT_FOUND","ORGANIZATION_NOT_FOUND","ENTITLEMENT_LIMIT_EXCEEDED","USAGE_LIMIT_EXCEEDED"]},"message":{"type":"string"},"requestId":{"type":"string","format":"uuid"}}}}},"GameType":{"type":"string","enum":["dice"]},"GameEnvironment":{"type":"string","enum":["sandbox"]},"GameStatus":{"type":"string","enum":["active"],"description":"Inactive games are omitted from this list."},"Game":{"type":"object","additionalProperties":false,"required":["id","slug","name","type","environment","status","version"],"properties":{"id":{"type":"string","example":"dice","description":"Stable public identifier. Same as slug. Not a database UUID."},"slug":{"type":"string","example":"dice"},"name":{"type":"string","example":"Dice"},"type":{"$ref":"#/components/schemas/GameType"},"environment":{"$ref":"#/components/schemas/GameEnvironment"},"status":{"$ref":"#/components/schemas/GameStatus"},"version":{"type":"string","example":"1.0.0","description":"Currently published game version. Clients cannot select another version."}}},"GameListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Game"}}}},"CreatePlayerRequest":{"type":"object","additionalProperties":false,"required":["externalRef"],"properties":{"externalRef":{"type":"string","minLength":1,"maxLength":128,"description":"Id from the customer system. Unique together with the organization derived from the API key. The same value may exist in another organization."},"displayName":{"type":"string","maxLength":80}}},"Player":{"type":"object","additionalProperties":false,"required":["id","organizationId","externalRef","displayName","status","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid","description":"Public player id. Not the customer externalRef."},"organizationId":{"type":"string","format":"uuid","description":"Organization derived from the API key. Never accepted from the client."},"externalRef":{"type":"string"},"displayName":{"type":["string","null"]},"status":{"type":"string","enum":["active","inactive"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"PlayerListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Player"}}}},"CreateWalletRequest":{"type":"object","additionalProperties":false,"required":["playerId"],"properties":{"playerId":{"type":"string","format":"uuid","description":"Player in the calling organization."}}},"CreditWalletRequest":{"type":"object","additionalProperties":false,"required":["amount"],"properties":{"amount":{"type":"integer","minimum":1,"maximum":1000000000,"description":"Positive integer virtual credits. Never a float."},"reference":{"type":"string","minLength":1,"maxLength":128,"description":"Optional client reference. Defaults to the idempotency key."}}},"DebitWalletRequest":{"type":"object","additionalProperties":false,"required":["amount"],"properties":{"amount":{"type":"integer","minimum":1,"maximum":1000000000},"reference":{"type":"string","minLength":1,"maxLength":128}}},"RefundWalletRequest":{"type":"object","additionalProperties":false,"required":["amount","reference"],"properties":{"amount":{"type":"integer","minimum":1,"maximum":1000000000},"reference":{"type":"string","minLength":1,"maxLength":128,"description":"Identifier of the operation being reversed. Unique per wallet among refunds."}}},"Wallet":{"type":"object","additionalProperties":false,"required":["id","playerId","currency","balance","environment","createdAt","updatedAt"],"properties":{"id":{"type":"string","format":"uuid"},"playerId":{"type":"string","format":"uuid"},"currency":{"type":"string","enum":["CREDITS"],"description":"Fictional unit. Not money."},"balance":{"type":"integer","minimum":0,"description":"Derived from the ledger. Integer virtual credits. Never a float."},"environment":{"type":"string","enum":["sandbox"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WalletTransaction":{"type":"object","additionalProperties":false,"required":["id","type","amount","reference","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["credit","debit","refund"]},"amount":{"type":"integer","minimum":1},"reference":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"WalletTransactionListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WalletTransaction"}}}},"WalletOperationResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["walletId","playerId","balance","currency","environment","transaction"],"properties":{"walletId":{"type":"string","format":"uuid"},"playerId":{"type":"string","format":"uuid"},"balance":{"type":"integer","minimum":0},"currency":{"type":"string","enum":["CREDITS"]},"environment":{"type":"string","enum":["sandbox"]},"transaction":{"$ref":"#/components/schemas/WalletTransaction"}}}}},"CreateSessionRequest":{"type":"object","additionalProperties":false,"required":["playerId","game","stake","config"],"properties":{"playerId":{"type":"string","format":"uuid"},"game":{"$ref":"#/components/schemas/GameType","description":"Catalog slug. The server resolves the published sandbox version."},"gameVersion":{"type":"string","example":"1.0.0","description":"Optional. When present, must match the published catalog version."},"stake":{"type":"integer","minimum":1,"maximum":1000000000,"description":"Virtual credits to debit for this session."},"config":{"type":"object","additionalProperties":false,"required":["target"],"properties":{"target":{"type":"integer","minimum":1,"maximum":6,"description":"Dice target face. Validated by the game handler."}}}}},"GameSession":{"type":"object","additionalProperties":false,"required":["id","playerId","game","gameVersion","status","stake","payout","result","createdAt","completedAt"],"properties":{"id":{"type":"string","format":"uuid"},"playerId":{"type":"string","format":"uuid"},"game":{"$ref":"#/components/schemas/GameType"},"gameVersion":{"type":"string","example":"1.0.0"},"status":{"type":"string","enum":["created","started","in_progress","completed","cancelled","expired"],"description":"MVP sessions normally settle to completed in the same request."},"stake":{"type":"integer","minimum":1},"payout":{"type":"integer","minimum":0,"description":"Virtual credits credited after settle. Zero on a loss."},"result":{"oneOf":[{"$ref":"#/components/schemas/DiceResult"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}}},"GameSessionListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GameSession"}}}},"DiceResult":{"type":"object","additionalProperties":false,"required":["kind","roll","target","outcome","payout"],"properties":{"kind":{"type":"string","enum":["dice"]},"roll":{"type":"integer","minimum":1,"maximum":6},"target":{"type":"integer","minimum":1,"maximum":6},"outcome":{"type":"string","enum":["win","lose"]},"payout":{"type":"integer","minimum":0,"description":"Copied from the engine result. Not a second source of financial truth."}}},"WebhookEvent":{"type":"string","enum":["session.completed","session.cancelled"],"description":"Only terminal session events are emitted. Wallet, player, and catalog events are out of scope."},"CreateWebhookRequest":{"type":"object","additionalProperties":false,"required":["url","events"],"properties":{"url":{"type":"string","format":"uri","description":"HTTPS URL. HTTP and URLs with userinfo are rejected."},"events":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/WebhookEvent"},"description":"At least one event. Duplicates are removed."}}},"Webhook":{"type":"object","additionalProperties":false,"required":["id","url","events","status","createdAt","revokedAt"],"properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEvent"}},"status":{"type":"string","enum":["active","revoked"]},"createdAt":{"type":"string","format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"}}},"WebhookCreated":{"type":"object","additionalProperties":false,"required":["id","url","events","status","createdAt","revokedAt","secret"],"description":"First-create response. Idempotent replay of POST /webhooks omits secret.","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEvent"}},"status":{"type":"string","enum":["active","revoked"]},"createdAt":{"type":"string","format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"secret":{"type":"string","description":"Shown once. Used to verify HMAC-SHA256 of the raw body in X-Aurora-Signature."}}},"WebhookListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}},"WebhookDelivery":{"type":"object","additionalProperties":false,"required":["id","webhookId","sessionId","type","status","attemptCount","lastHttpStatus","lastError","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"webhookId":{"type":"string","format":"uuid"},"sessionId":{"type":"string","format":"uuid"},"type":{"$ref":"#/components/schemas/WebhookEvent"},"status":{"type":"string","enum":["pending","succeeded","failed"]},"attemptCount":{"type":"integer","minimum":0},"lastHttpStatus":{"type":["integer","null"]},"lastError":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}},"WebhookDeliveryListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"AuditEventType":{"type":"string","enum":["organization.created","api_key.created","api_key.revoked","player.created","wallet.created","wallet.credited","wallet.debited","wallet.refunded","session.completed","session.cancelled","webhook.created","webhook.revoked","webhook.delivery.failed","webhook.delivery.succeeded"]},"AuditEvent":{"type":"object","additionalProperties":false,"required":["id","type","occurredAt","actor","resource","playerId","walletId","transactionId","sessionId","webhookId","deliveryId","apiKeyId","attemptCount","data"],"description":"Sanitized public audit fact. organizationId, secrets, session seeds, API key plaintext, and delivery lastError are never included.","properties":{"id":{"type":"string","format":"uuid"},"type":{"$ref":"#/components/schemas/AuditEventType"},"occurredAt":{"type":"string","format":"date-time"},"actor":{"type":"object","additionalProperties":false,"required":["kind","id"],"properties":{"kind":{"type":"string","enum":["api_key","user","system"]},"id":{"type":["string","null"]}}},"resource":{"type":"object","additionalProperties":false,"required":["type","id"],"properties":{"type":{"type":"string"},"id":{"type":"string","format":"uuid"}}},"playerId":{"type":["string","null"],"format":"uuid"},"walletId":{"type":["string","null"],"format":"uuid"},"transactionId":{"type":["string","null"],"format":"uuid"},"sessionId":{"type":["string","null"],"format":"uuid"},"webhookId":{"type":["string","null"],"format":"uuid"},"deliveryId":{"type":["string","null"],"format":"uuid"},"apiKeyId":{"type":["string","null"],"format":"uuid"},"attemptCount":{"type":["integer","null"]},"data":{"type":"object","additionalProperties":true,"description":"Sanitized fact payload. Never includes organizationId or secrets."}}},"AuditListResponse":{"type":"object","additionalProperties":false,"required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditEvent"}},"pagination":{"type":"object","additionalProperties":false,"required":["nextCursor","limit"],"properties":{"nextCursor":{"type":["string","null"]},"limit":{"type":"integer","minimum":1,"maximum":100}}}}},"Organization":{"type":"object","additionalProperties":false,"required":["id","name","slug","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"EntitlementItem":{"type":"object","additionalProperties":false,"required":["key","kind","booleanValue","numericValue"],"properties":{"key":{"type":"string","description":"Stable entitlement key such as players.max. Enforcement uses this key, never the plan name."},"kind":{"type":"string","enum":["boolean","numeric","quota"]},"booleanValue":{"type":["boolean","null"]},"numericValue":{"type":["integer","null"]}}},"OrganizationEntitlements":{"type":"object","additionalProperties":false,"required":["plan","subscription","entitlements"],"properties":{"plan":{"type":"object","additionalProperties":false,"required":["code","name","status"],"properties":{"code":{"type":"string","example":"sandbox"},"name":{"type":"string","example":"Sandbox"},"status":{"type":"string","enum":["assignable","retired"]}}},"subscription":{"type":"object","additionalProperties":false,"required":["status","startedAt"],"properties":{"status":{"type":"string","enum":["active"]},"startedAt":{"type":"string","format":"date-time"}}},"entitlements":{"type":"array","items":{"$ref":"#/components/schemas/EntitlementItem"},"description":"Resolved plan entitlements. Sandbox currently ships with an empty list. A missing key means the current create behavior continues."}}}}}}