> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zerodash.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Debit (place bet)

> Subtracts the stake from the player's wallet when a bet is placed.

Every debit is eventually settled by exactly one [Credit](/api-reference/callbacks/credit) **or** one [Rollback](/api-reference/callbacks/rollback) carrying the same `gameRoundId` — never both.

**Free rounds:** when `reason` is `freeround` the stake is `0`. Deduct nothing, but still create the transaction and return a valid response.

The status code you choose here is a contract, not a formality — see the response list below. `422` tells Zero-Dash the transaction definitively does not exist on your side; `500` tells us it might, and we will send a rollback.



## OpenAPI

````yaml api-reference/callbacks.json POST /debit
openapi: 3.1.0
info:
  title: Zero-Dash Wallet Callbacks
  version: 1.0.0
  summary: >-
    The wallet API that you implement and Zero-Dash calls to authorize players
    and move money.
  description: >-
    **You implement these five endpoints. Zero-Dash calls them.**


    This is the inverse direction of the [Customer
    API](/api-reference/customer/list-games): here Zero-Dash is the client and
    your platform is the server. Mount them under any base path you like — the
    full path you register is what gets signed.


    All endpoints must be RESTful, accept and return JSON, and be served over
    HTTPS with a valid TLS certificate.


    Before you write a line of code, read [Wallet
    integration](/wallet/overview), [Amounts and currencies](/wallet/amounts)
    and [Idempotency](/wallet/idempotency).


    **Tip —** Use the playground on these pages to fire signed requests at
    **your own** implementation: set the `host` server variable to your callback
    host.
  contact:
    name: Zero-Dash Integrations
    email: info@zerodash.studio
servers:
  - url: https://{host}
    description: >-
      Your wallet host. Point this at your own environment to test your
      implementation. If you mount the endpoints under a path prefix (for
      example /zerodash/v1), include it in the host value — the full registered
      path is what gets signed.
    variables:
      host:
        default: wallet.example-operator.com
        description: The host you register with Zero-Dash, including any path prefix.
security:
  - signature: []
    timestamp: []
tags:
  - name: Wallet
    description: Player authorization and the money movements of a game round.
  - name: Troubleshooting
    description: Endpoints Zero-Dash uses to reconcile state after a failure.
paths:
  /debit:
    post:
      tags:
        - Wallet
      summary: Debit (place bet)
      description: >-
        Subtracts the stake from the player's wallet when a bet is placed.


        Every debit is eventually settled by exactly one
        [Credit](/api-reference/callbacks/credit) **or** one
        [Rollback](/api-reference/callbacks/rollback) carrying the same
        `gameRoundId` — never both.


        **Free rounds:** when `reason` is `freeround` the stake is `0`. Deduct
        nothing, but still create the transaction and return a valid response.


        The status code you choose here is a contract, not a formality — see the
        response list below. `422` tells Zero-Dash the transaction definitively
        does not exist on your side; `500` tells us it might, and we will send a
        rollback.
      operationId: debit
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DebitRequest'
            examples:
              realMoney:
                summary: Real money bet
                value:
                  playerId: acct_8f2c19
                  token: eyJhbGciOiJIUzI1NiIs...
                  transactionId: test-transaction-1112
                  gameId: lucky-duck
                  gameRoundId: round-1234
                  stake:
                    amount: 1
                    currency: USD
                  reason: paid
              freeRound:
                summary: Free round bet (stake is 0)
                value:
                  playerId: acct_8f2c19
                  token: eyJhbGciOiJIUzI1NiIs...
                  transactionId: test-transaction-2001
                  gameId: lucky-duck
                  gameRoundId: round-9001
                  stake:
                    amount: 0
                    currency: USD
                  reason: freeround
                  freeRoundData:
                    campaign: freeround-campaign-1
                    value:
                      amount: 1
                      currency: USD
      responses:
        '200':
          description: Bet accepted and the stake was subtracted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionResponse'
              example:
                operatorTransactionId: op-tx-55901
                balance:
                  amount: 95
                  currency: USD
                  updatedAt: '2026-01-29T14:05:29.678Z'
                createdAt: '2026-01-29T14:05:29.678Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: >-
            Insufficient balance. The player does not have enough funds for this
            bet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: insufficient balance
        '422':
          description: >-
            The transaction was **certainly not** created because of an internal
            error on your side. Zero-Dash will not send a rollback, because
            there is nothing to roll back.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: wallet unavailable, transaction not created
        '500':
          description: >-
            An internal error occurred **after** the transaction was created.
            Zero-Dash will attempt to cancel it, with retries on failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: internal error
components:
  schemas:
    DebitRequest:
      type: object
      required:
        - playerId
        - transactionId
        - gameId
        - gameRoundId
        - stake
      properties:
        playerId:
          type: string
          description: Player account ID.
        token:
          type: string
          description: The session token from game launch.
        transactionId:
          type: string
          description: >-
            Zero-Dash ID of this bet transaction. Use it as your idempotency
            key.
        gameId:
          type: string
          description: Slug of the game the round belongs to.
          examples:
            - lucky-duck
        gameRoundId:
          type: string
          description: >-
            Groups the bet with its settlement. The credit or rollback that
            settles this bet carries the same value.
          examples:
            - round-1234
        stake:
          $ref: '#/components/schemas/Amount'
          description: Decimal amount to subtract from the balance. `0` for free rounds.
        reason:
          $ref: '#/components/schemas/Reason'
        freeRoundData:
          $ref: '#/components/schemas/FreeRoundData'
    TransactionResponse:
      type: object
      required:
        - operatorTransactionId
        - balance
      properties:
        operatorTransactionId:
          type: string
          description: >-
            Your internal transaction ID. Stored by Zero-Dash for
            troubleshooting only.
        balance:
          $ref: '#/components/schemas/Balance'
        createdAt:
          type: string
          format: date-time
          description: >-
            Transaction creation date (ISO-8601 UTC). Defaults to the time of
            processing when omitted.
    Error:
      type: object
      description: Error body. Use this shape wherever possible so failures are actionable.
      properties:
        message:
          type: string
          description: Human-readable explanation of the failure.
    Amount:
      type: object
      required:
        - amount
        - currency
      description: >-
        A monetary value as a **decimal**, never in minor units. Crypto is
        capped at 8 decimal places.
      properties:
        amount:
          oneOf:
            - type: number
            - type: string
          description: Decimal value, for example `12.45` USD or `0.00000123` BTC.
          examples:
            - 1
        currency:
          type: string
          description: ISO-4217 currency code.
          examples:
            - USD
    Reason:
      type: string
      description: >-
        Type of the bet. `paid` is real money; `freeround` is a free round —
        each free spin is a separate bet with its own debit call.
      enum:
        - paid
        - freeround
    FreeRoundData:
      type: object
      required:
        - campaign
        - value
      description: Present only when `reason` is `freeround`.
      properties:
        campaign:
          type: string
          description: Campaign code the free round belongs to.
          examples:
            - freeround-campaign-1
        value:
          $ref: '#/components/schemas/Amount'
          description: Nominal value of one free round, as configured on the campaign.
    Balance:
      type: object
      required:
        - amount
        - currency
      description: The player's balance **after** the operation was applied.
      properties:
        amount:
          oneOf:
            - type: number
            - type: string
          description: >-
            Most recent decimal balance, for example `12.45` USD or `0.00000123`
            BTC.
          examples:
            - 95
        currency:
          type: string
          description: ISO-4217 currency code.
          examples:
            - USD
        updatedAt:
          type: string
          format: date-time
          description: When the balance was last updated (ISO-8601 UTC).
  responses:
    BadRequest:
      description: Invalid request payload format. Include an explanation in the body.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: missing field gameRoundId
    Unauthorized:
      description: >-
        Signature mismatch, stale timestamp, or source IP outside the Zero-Dash
        allowlist.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: invalid signature
  securitySchemes:
    signature:
      type: apiKey
      in: header
      name: X-Zd-Signature
      description: >-
        Hex-encoded `HMAC-SHA512(apiPath|timestamp|data, secretKey)` computed by
        Zero-Dash. **Recompute it and compare before doing anything else.** See
        [Request signature](/security/signature).
    timestamp:
      type: apiKey
      in: header
      name: X-Zd-Timestamp
      description: >-
        Unix time in **milliseconds**, and the exact value that was signed.
        Reject requests older than 5 minutes.

````