Skip to documentation
GAME_ALLIGATOR
ProductsGamificationIntegrationDemos
Let’s talk
ProductsGamificationIntegrationDemos
Let’s talk
Integration
OverviewGuidesAPI referenceResources
Integration overview
Integration architectureFundamentalsGetting startedCertification
Products
Aggregation
Part I · Fundamentals
Core flowRequest & signingEnvelope, money and data formatsErrors: one modelIdempotency & retriesRate limits, pagination, networkMoney Path Rules
Part II · Operator API
Getting startedGames APIWallet APIFree rounds APIReports APIFeatures APIEvent stream
Part III · Certification
Run the checks from the Operator PortalThe command-line tool (for your CI)The checklistCertification checklist
Part IV · Changelog and status
ChangelogDocument ControlChangelog & migration guide: Operator API v2
Appendix
Numbers to rememberWhole guide on one page
API reference
Get player balanceAuthenticate player sessionDebit player balance (bet)Credit player balance (win/bonus)Atomic debit and creditRollback transactionClose game roundSettle free-round grantReconcile uncertain transactionNon-financial notificationgetCapabilitieslistGamesupdateGamelaunchGamelaunchDemocloseSessionlistSessionslistRoundsexportRoundsgetAggregatesissueGrantlistGrantscancelGrantsubscribeackgetOperatorCapabilitiesgetGameFeatureslistBonusBuyTypesissueBonusBuycancelBonusBuygetJackpotsgetBetRangesgetRoundReplaygetRoundDetailslistCampaignscancelCampaignqueryProviderTransactionslistTournamentsgetTournamentgetLeaderboard
Gamification
Integration
Quick startWidgets on your siteSigned-in playersLaunching gamesGameplay eventsTransportsOutcomes and your obligationsGame cataloguesRewardsOnboarding and go-liveReasons, numbers, currencies
Poker
Integration
OverviewEmbed the poker clientServer APIEvents and webhooks
llms-full.txt
Start here
Aggregation / Part I · FundamentalsCore flow

Game Alligators (GA) puts game studios' games into your casino. Traffic runs in two directions, each with its own key pair. Don't mix them. Direction Who calls whom What it's for Key you use Chapter You → GA You call https://api.rexplay.sit

Aggregation / Part I · FundamentalsRequest & signing

Every call GA sends to your wallet looks like this: http POST /v2/wallet/debit HTTP/1.1 Host: wallet.operator.example Content Type: application/json X API Key Id: key live 01 X Request Id: 0198a1d0 9a30 7f08 a7dd 713e4fd33db0 Idempotency Ke

Aggregation / Part I · FundamentalsEnvelope, money and data formats

Every wallet request has the same outer shape. payload is the action specific part and the per call ids live in payload.meta . json { "request id": "0198a1d0 9a30 7f08 a7dd 713e4fd33db0", "ts": "2026 09 13T12:00:00Z", "operator id": "0197aa

Aggregation / Part I · FundamentalsErrors: one model

Your wallet's codes are Appendix A.1. What GA returns to you is Appendix A.2. Every error from /v2/aggregator/ and /v2/features/ has a non 200 HTTP status and one JSON body, Content Type: application/json : json { "code": "ERROR CODE MAINTE

Aggregation / Part I · FundamentalsIdempotency & retries

Certification tests these hardest. Build them in from day one. The full normative text is in Money Path Rules. Keep every op id with its stored answer for at least 4 months . GA resends for 72 hours, and the margin covers reconciliation dis

Aggregation / Part I · FundamentalsRate limits, pagination, network

Your wallet must answer within 5 seconds per call (§2.7). Aim for well under 1 second. GA doesn't filter your source IP on the Operator API. If you restrict inbound traffic to your wallet, allow GA's outbound addresses: 49.13.169.177 and 46

Aggregation / Part I · FundamentalsMoney Path Rules

The rules below govern the v2 wallet contract when a call goes wrong. The cases are a timeout, a duplicate, a rollback of an operation you never saw, and a win that arrives after the session closed. They're additive: GA removes or renames n

Aggregation / Part II · Operator APIGetting started

1. Get sandbox credentials. Email [integration@gamealligator.com](mailto:integration@gamealligator.com). You receive an operator profile with operator id , the Operator API key pair, and a login to https://operator.rexplay.site . There you

↑ ↓ navigate↵ openesc close
  1. Home
  2. /Integration
  3. /Aggregation
  4. /Money Path Rules
Aggregation

Money Path Rules

MarkdownSource

The rules below govern the v2 wallet contract when a call goes wrong. The cases are a timeout, a duplicate, a rollback of an operation you never saw, and a win that arrives after the session closed. They’re additive: GA removes or renames nothing published in proto/ or openapi/.

Conventions.

  • Normative keywords (MUST, MUST NOT, SHOULD, MAY) are used as in Request for Comments (RFC) 2119.
  • Error codes are written in prose without the ERROR_CODE_ prefix. On the wire they use the published enum form (for example ERROR_CODE_ALREADY_ROLLED_BACK). The same applies to RECONCILE_STATE_*, CREDIT_KIND_*, DEBIT_MODE_* and ORIGINAL_KIND_* values.
  • A business refusal travels on HTTP 200 with {"status":"error","error":{code,message,retryable,retry_after,attributes}}. A success travels as {"status":"ok","data":{…}}.
  • Request examples are reduced to the relevant envelope fields (ts, operator_id, correlation and signature headers are omitted unless relevant). All values are illustrative.

1. Summary

#Rule
1Rollback of an unknown original is a success with original_found=false. The operator remembers the original’s id. A late Debit/Credit with that id gets ALREADY_ROLLED_BACK. The operator never returns UNKNOWN_ORIGINAL to a Rollback
2Mandatory order of checks at the operator
3New enum value IDEMPOTENCY_CONFLICT and the fingerprint field list
4The operator never refuses Credit, SettleGrant, and Rollback for session, player block, or limits. Closed list of terminal Credit refusals
5Reconcile for an unknown operation returns an ok envelope + NOT_APPLIED. It’s a read, never a barrier
6Concurrent duplicates: the second request waits for the commit and receives the first response
7Numbers: op_id retention, GA attempts, resend schedule and horizon, signature window
8Zero amount, exponent mismatch, int64 overflow, unknown fields, and unknown enum values
9Rollback must match the original’s player and currency. DebitCredit checks the stake first and is all-or-nothing. Balance-reducing corrections arrive as an ordinary Debit
10Free rounds and bonus-type credits: what the operator receives, the token rule, no bet required for promo payouts, accrued wins are always settled
11What GA does on an unknown outcome, per operation type
12Deliberate differences from other aggregators

2. Items

2.1 Rollback of an unknown original

Normative text

  1. If the operator holds no record of original_op_id, a Rollback MUST be answered with a success envelope, MUST move no money, and MUST carry original_found=false and the player’s current balance.
  2. The operator MUST remember the ORIGINAL’s id (original_op_id) as rolled back. This is the barrier. Its key is the original’s id, not the Rollback’s op_id.
  3. A Debit MUST check the barrier in the same atomic step that records the debit, before any money moves. The operator serialises a Debit and the Rollback of that Debit on the ORIGINAL’s id.
  4. The operator MUST refuse a later Debit or Credit that carries that op_id with ALREADY_ROLLED_BACK, regardless of its fingerprint.
  5. A Rollback naming an original that the operator is still processing MUST get an error envelope with retryable=true. GA re-drives it until the original resolves.
  6. The operator MUST NOT return UNKNOWN_ORIGINAL to a Rollback. The value stays in the enum.
  7. A repeated Rollback of the same original MUST return the original response and MUST NOT reverse money again.

Example—the operator has never seen op-bet-90:

{
  "request_id": "req-0002",
  "action": "rollback",
  "payload": {
    "meta": {
      "request_id": "req-0002",
      "op_id": "op-rb-91",
      "round_id": "rnd-55"
    },
    "original_op_id": "op-bet-90",
    "original_kind": "ORIGINAL_KIND_DEBIT",
    "money": {
      "currency": "EUR",
      "amount": 1000,
      "exponent": 2
    }
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-8841",
    "balance_after": {
      "currency": "EUR",
      "amount": 25000,
      "exponent": 2
    },
    "original_found": false
  }
}

The Debit with op_id op-bet-90 then arrives late:

{
  "status": "error",
  "error": {
    "code": "ERROR_CODE_ALREADY_ROLLED_BACK",
    "message": "operation was rolled back",
    "retryable": false
  }
}

2.2 Mandatory order of checks

Normative text

  1. The operator MUST evaluate checks in this order: signature → schema → op_id lookup (replay / conflict / already rolled back) → player + currency/exponent → [Debit/DebitCredit only: session, player status, limits, balance] → round state → apply and store the result atomically.
  2. The op_id lookup MUST precede the session, player-status, limit, and balance checks.
  3. A duplicate of an applied Debit MUST return the stored success, even when the balance is now insufficient or the session has expired.
  4. A signature or time failure is a transport-level 401/403 without a code.
  5. For a new Debit, an expired session is SESSION_EXPIRED.

Example—a stake of 10.00 took the balance to 0.00. GA resends the same Debit:

{
  "request_id": "req-0011",
  "action": "debit",
  "payload": {
    "meta": {
      "request_id": "req-0011",
      "op_id": "op-bet-77",
      "round_id": "rnd-40",
      "launch_token": "lt-abc"
    },
    "money": {
      "currency": "EUR",
      "amount": 1000,
      "exponent": 2
    }
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-9001",
    "balance_after": {
      "currency": "EUR",
      "amount": 0,
      "exponent": 2
    }
  }
}

This response is identical to the response to the first request.


2.3 IDEMPOTENCY_CONFLICT

Normative text

  1. The closed error enum has 15 codes plus the ERROR_CODE_UNSPECIFIED default. IDEMPOTENCY_CONFLICT is the only code added after the initial publication.
  2. For the same op_id with a different fingerprint, the operator MUST refuse with IDEMPOTENCY_CONFLICT, and no money moves.
  3. The fingerprint is: player, operation type, currency, amount together with exponent, round, original, grant reference.
  4. This applies while the operation is APPLIED. An op_id that the operator has rolled back, or remembers as rolled back, answers per item 2.1, whatever the fingerprint.
  5. The same op_id with the same fingerprint returns the stored success.

Example—the operator applied op-bet-77 for 10.00. GA now sends the same op_id with 20.00:

{
  "request_id": "req-0031",
  "action": "debit",
  "payload": {
    "meta": {
      "request_id": "req-0031",
      "op_id": "op-bet-77",
      "round_id": "rnd-40",
      "launch_token": "lt-abc"
    },
    "money": {
      "currency": "EUR",
      "amount": 2000,
      "exponent": 2
    }
  }
}
{
  "status": "error",
  "error": {
    "code": "ERROR_CODE_IDEMPOTENCY_CONFLICT",
    "message": "op_id reused with a different fingerprint",
    "retryable": false
  }
}

2.4 What’s never refused

Normative text

  1. The operator MUST NOT refuse Credit and Rollback because the session or token has expired. GA still sends the launch token of that session. Only its expiry isn’t a reason to refuse.
  2. A blocked or disabled player can’t place NEW bets. The operator MUST still accept Credit and Rollback for such a player.
  3. The operator MUST NOT refuse Credit and Rollback for limits.
  4. SettleGrant is a money operation like a Credit and follows the same rule: the operator MUST NOT refuse it for session, player block, or limits.
  5. The terminal refusals of a Credit are a closed list:
    • player not found (PLAYER_NOT_FOUND)
    • currency mismatch (CURRENCY_MISMATCH)
    • invalid request (INVALID_REQUEST)
    • IDEMPOTENCY_CONFLICT
    • “the bet this win refers to is unknown to the operator or was rolled back” (UNKNOWN_ORIGINAL / ALREADY_ROLLED_BACK)
  6. After any other refusal of a Credit, GA resends it.
  7. Round state: the operator refuses a new Debit in a CLOSED or VOIDED round with BUSINESS_REJECTED. It accepts a Credit in OPEN rounds and, as a late win, in CLOSED rounds. It refuses a Credit in a VOIDED round with ALREADY_ROLLED_BACK. It accepts Rollback and Reconcile in any round state.

Example—the player’s session ended hours ago, but the win still arrives:

{
  "request_id": "req-0042",
  "action": "credit",
  "payload": {
    "meta": {
      "request_id": "req-0042",
      "op_id": "op-win-77",
      "round_id": "rnd-40",
      "launch_token": "lt-abc"
    },
    "money": {
      "currency": "EUR",
      "amount": 2500,
      "exponent": 2
    },
    "kind": "CREDIT_KIND_WIN",
    "round_finish": true
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-9002",
    "balance_after": {
      "currency": "EUR",
      "amount": 2500,
      "exponent": 2
    }
  }
}

2.5 Reconcile

Normative text

  1. Reconcile is a read. It MUST always return an ok envelope.

  2. The operator derives the state from its record of original_op_id:

    Operator’s recordReconcile state
    absentNOT_APPLIED
    still being committedUNKNOWN
    appliedAPPLIED
    rolled back / remembered as rolled backNOT_APPLIED
  3. Reconcile MUST NOT record anything. It’s never a barrier.

  4. The operator MUST NOT return UNKNOWN_ORIGINAL to a Reconcile.

  5. For NOT_APPLIED of a Credit, GA’s reading is “resend it”.

Example—the operator never saw op-bet-90:

{
  "request_id": "req-0050",
  "action": "reconcile",
  "payload": {
    "meta": {
      "request_id": "req-0050",
      "op_id": "op-rc-12"
    },
    "original_op_id": "op-bet-90"
  }
}
{
  "status": "ok",
  "data": {
    "state": "RECONCILE_STATE_NOT_APPLIED"
  }
}

The operator processes a later Debit with op_id op-bet-90 normally, because the Reconcile recorded nothing.


2.6 Concurrent duplicates

Normative text

  1. The operator MUST serialise per op_id: it inserts a unique key before business logic runs.
  2. The second request MUST wait for the commit of the first.
  3. If its fingerprint matches, the second request MUST receive the same response as the first. Otherwise it receives IDEMPOTENCY_CONFLICT.
  4. The operator never applies the operation a second time.
  5. The “same response” rule concerns operations that WERE processed. A refused request leaves the op_id unused, and the operator MAY evaluate it again when resent. GA never resends a Debit after your business refusal. GA resends a refused Credit until you accept it. If an earlier attempt of the same Debit ended without an answer, GA treats the Debit as unknown even after a later refusal and sends a Rollback. Keep the barrier (2.4): the earlier request may still reach you.

Example—two requests arrive at once. Both carry op_id op-bet-88, with request_id req-0061 and req-0062. Both receive:

{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-9100",
    "balance_after": {
      "currency": "EUR",
      "amount": 4000,
      "exponent": 2
    }
  }
}

The balance changed once.


2.7 Numbers

Normative text

  1. Both sides MUST keep op_id records for at least 4 months. The 7-day window of the published v1 wallet spec remains the hard minimum for v1 bridges.
  2. For a Debit/DebitCredit in unknown state, GA makes up to 4 quick attempts with the same op_id, 100 ms, 500 ms, and 2 s apart. A Retry-After may stretch a pause up to 10 s. Each attempt waits at most 5 s. All attempts share the operation budget of item 2.11.7 (8 s by default), so a silent operator gets 2 attempts: 5 s, then the rest of the budget.
  3. For a Rollback, and on the same schedule for a Credit/SettleGrant in unknown state, GA resends for up to 72 hours. The backoff is exponential (1 s, doubling, capped at 10 minutes). GA stops at the first logical, valid-envelope response. The limit is the 72-hour horizon, not a number of attempts. This is inside the 7-day v1 window and inside the 4-month retention.
  4. When the 72 hours are over, GA sets manual_review and raises an alert. The state stays unknown, and GA never marks it “failed”.
  5. Every attempt carries a new request_id and the same op_id.
  6. The signature window is 300 s: X-GA-Signature: t=,v1=, rejected when |now − t| > 300. The failure is a transport-level 401/403 without a code.

Example—attempt 2 of a Credit resend (new request_id, same op_id):

X-GA-Signature: t=1790000000,v1=<hex>
{
  "request_id": "req-0072",
  "action": "credit",
  "payload": {
    "meta": {
      "request_id": "req-0072",
      "op_id": "op-win-91",
      "round_id": "rnd-60",
      "launch_token": "lt-abc"
    },
    "money": {
      "currency": "EUR",
      "amount": 500,
      "exponent": 2
    },
    "kind": "CREDIT_KIND_WIN"
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-9200",
    "balance_after": {
      "currency": "EUR",
      "amount": 1500,
      "exponent": 2
    }
  }
}

This is the stored success of attempt 1, which the operator had committed but GA never received.


2.8 Amount and schema validation

Normative text

  1. Money is {currency, amount:int64, exponent:0..18}.
  2. A Debit amount MUST be > 0. A Credit amount MAY be 0 and is then valid. A zero Credit closes a round. A negative amount is INVALID_REQUEST.
  3. The operator MUST refuse an exponent mismatch or an exponent outside 0..18 with CURRENCY_MISMATCH.
  4. The operator MUST refuse an int64 overflow with INVALID_REQUEST.
  5. Both refusals happen before money moves, and the op_id stays unused.
  6. The operator MUST ignore unknown fields.
  7. The operator MUST refuse an unknown enum value in a known field with INVALID_REQUEST.

Example—the operator holds EUR with exponent 2:

{
  "request_id": "req-0080",
  "action": "debit",
  "payload": {
    "meta": {
      "request_id": "req-0080",
      "op_id": "op-bet-95",
      "round_id": "rnd-70",
      "launch_token": "lt-abc"
    },
    "money": {
      "currency": "EUR",
      "amount": 1000,
      "exponent": 3
    }
  }
}
{
  "status": "error",
  "error": {
    "code": "ERROR_CODE_CURRENCY_MISMATCH",
    "message": "exponent mismatch",
    "retryable": false
  }
}

2.9 Rollback matching, DebitCredit, balance-reducing corrections

Normative text

  1. The operator MUST execute a Rollback only if its player and currency match the original’s. Otherwise it refuses the Rollback terminally with INVALID_REQUEST or CURRENCY_MISMATCH, and no money moves.
  2. A Rollback of a Debit is always full: money equals the stored amount of the original. A partial rollback exists only for a Credit, through partial / debit_mode / debited.
  3. DebitCredit MUST check the stake against the current balance FIRST, as for a separate Debit, and only then pay the win of the same call. The operator applies or refuses stake and win together. It’s all-or-nothing.
  4. A provider correction (adjustment) that REDUCES the player’s balance arrives as an ordinary Debit, idempotent by an op_id that GA derives from the provider’s own correction id. One that INCREASES it arrives as a Credit of kind ADJUSTMENT. The correction names no earlier operation and rolls nothing back.
  5. Apply your usual Debit checks. The only refusal the providers define for a correction is insufficient funds (INSUFFICIENT_FUNDS). GA relays your refusal to the provider as a refusal and never turns a refused correction into another operation.
  6. The Debit carries no correction marker in v1.0. A correction can arrive outside an active game session, for example in live-casino settlements and tournaments. If you reject Debits on an expired session, you refuse such a correction, and the provider resolves it on its side. The same applies to any other charge a provider sends outside a session: a participation fee, a contribution to a promo pool, a retried bet that the provider flags as offline.

Example—a 30.00 balance-reducing correction:

{
  "request_id": "req-0090",
  "action": "debit",
  "payload": {
    "meta": {
      "request_id": "req-0090",
      "op_id": "op-corr-5",
      "round_id": "adj-5531"
    },
    "money": {
      "currency": "EUR",
      "amount": 3000,
      "exponent": 2
    }
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-9300",
    "balance_after": {
      "currency": "EUR",
      "amount": 10000,
      "exponent": 2
    }
  }
}

2.10 Free rounds and bonus-type credits

Normative text

  1. GA has two free-round mechanisms. They never share a callback.
  2. Operator-issued grant. The operator calls IssueGrant / ListGrants / CancelGrant. A round played on a grant sends NO Debit and NO Credit to the operator. The win accumulates on the grant, and SettleGrant pays it ONCE (carrying grant_id, total_win, rounds_played) when the grant is exhausted. GA settles a zero-win grant too. Grant states are ACTIVE / EXHAUSTED / CANCELLED / EXPIRED / SETTLED. For an operator-issued grant, SettleGrant is the only money call the operator receives.
  3. Provider-issued promo. The operator receives, per winning spin, an ordinary Credit of kind FREE_ROUND carrying the campaign reference (campaign_ref), or one SettleGrant at the end.
  4. IssueGrant is idempotent by the operator’s idempotency_key. The same key returns the same grant. GA refuses the same key with different parameters. Without a key every call creates a new grant, so the operator SHOULD always send one.
  5. You can cancel only an ACTIVE grant. A repeated cancel returns the same result. GA allows cancelling a partly played ACTIVE grant.
  6. A grant has a hard end date (valid_until). GA refuses a free round consumed after that date.
  7. GA never drops money already won on a grant. GA pays a win of a round played before the grant ended (cancelled, expired, or settled). SettleGrant pays it for the rounds actually played. When the win arrives after settlement, a separate Credit of kind FREE_ROUND carrying the grant reference pays it. GA refuses to the provider a NEW round reported on a grant that has already ended, and that round never reaches you.
  8. Token rule. For free-round, promo, and bonus credits, the operator MUST NOT validate the EXPIRY of the session/token. They may arrive when the player is offline. The token, when sent, must still be one the operator knows.
  9. Credits of kind BONUS, PROMO, JACKPOT, TOURNAMENT, CASHBACK, ADJUSTMENT, FREE_ROUND are ordinary Credits: items 2.2–2.7 apply in full. They’re idempotent by op_id. The operator never refuses them for session, block, or limits. GA resends them until delivered and never rolls them back.
  10. No bet required. A promo, bonus, jackpot, or tournament payout may come without any bet or debit in the round. The operator MUST NOT require one. An ordinary win belongs to its round as usual.
  11. The operator answers success to a provider’s rollback of a free-round bet. The rollback moves no money, because the bet took none. SettleGrant is never a Rollback target.
  12. SettleGrant is one per grant and idempotent by op_id. On an unknown outcome, GA resends it per item 2.7 until acknowledged.

Example—a grant is exhausted, and GA settles it once:

{
  "request_id": "req-0100",
  "action": "settle_grant",
  "payload": {
    "meta": {
      "request_id": "req-0100",
      "op_id": "op-sg-3"
    },
    "grant_id": "grant-2041",
    "total_win": {
      "currency": "EUR",
      "amount": 1800,
      "exponent": 2
    },
    "rounds_played": 20
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-9400",
    "balance_after": {
      "currency": "EUR",
      "amount": 11800,
      "exponent": 2
    }
  }
}

2.11 What GA does on an unknown outcome

Normative text

  1. An unknown outcome is any of: a timeout, a disconnect, any response that isn’t a valid envelope with a known code (including 401/403/404/5xx from a proxy). A valid envelope with a retryable code (RATE_LIMITED, MAINTENANCE, INTERNAL) on a money operation is also an unknown outcome.
  2. Debit / DebitCredit.
    • GA makes up to 4 quick attempts with the same op_id, 100 ms, 500 ms, and 2 s apart, inside the budget of item 2.11.7 (numbers in item 2.7).
    • If the outcome is still unknown, GA fails the bet towards the provider with a retryable error, so the round doesn’t start. GA also generates ONE linked Rollback.
  3. Credit / SettleGrant. GA resends with the same op_id until success or until the resend limit of item 2.7 runs out. GA never rolls back a bet because it couldn’t deliver a win. Only the provider may send that rollback.
  4. Rollback.
    • GA resends with the same op_id per item 2.7 (up to 72 hours, exponential backoff, stopping at the first logical response).
    • A non-retryable refusal, meaning a valid envelope with a non-retryable code, stops resending at once: GA sets manual_review and raises an alert.
  5. A Rollback is never in flight concurrently with its original. GA records a provider’s cancel that arrives while the Debit is in flight and answers it retryable. GA executes it after the Debit resolves.
  6. There is one Rollback per original, and GA reads its amount from the stored original.
  7. An overall operation budget bounds the retry sequence (GA’s own sender setting, 8s by default): the first attempt always goes out. GA starts no retry and waits no backoff the remaining budget can’t hold. It answers the provider retryable with an unknown outcome before the provider’s own timeout expires.

Example—a Debit op-bet-90 gets no valid response within the budget (two attempts on a silent wallet: two request_id values, same op_id). GA fails the bet towards the provider and sends the linked Rollback:

{
  "request_id": "req-0205",
  "action": "rollback",
  "payload": {
    "meta": {
      "request_id": "req-0205",
      "op_id": "op-rb-91",
      "round_id": "rnd-55"
    },
    "original_op_id": "op-bet-90",
    "original_kind": "ORIGINAL_KIND_DEBIT",
    "money": {
      "currency": "EUR",
      "amount": 1000,
      "exponent": 2
    }
  }
}
{
  "status": "ok",
  "data": {
    "operator_tx_id": "tx-8841",
    "balance_after": {
      "currency": "EUR",
      "amount": 25000,
      "exponent": 2
    },
    "original_found": false
  }
}

If the Debit reaches the operator later, the operator refuses it with ALREADY_ROLLED_BACK (item 2.1).


2.12 Deliberate differences from other aggregators

The published GA contract governs. Some of its choices differ from what other aggregators do. Don’t “fix” them when porting an existing wallet integration:

  • A business refusal travels on HTTP 200 with the status in the body. Non-200 statuses are transport-level only.
  • An error response carries no balance.
  • Money is int64 in minor units plus an explicit exponent, never a fixed scale, and never a decimal string.
  • A signature failure is a transport-level 401/403 without a body status.
  • A partial rollback exists, but only for a Credit (partial, debit_mode, debited). A rollback of a Debit is always full.
  • A Credit is never refused for limits or session (item 2.4).
  • A round may stay OPEN forever. GA doesn’t require every round to be closed.
  • A duplicate returns the stored success (item 2.6), never a conflict status.
  • GA doesn’t send free-round bets to the operator (item 2.10). The operator learns the rounds from SettleGrant.

3. Conformance additions

Check idSetupActionExpected
W2-DELTA-01 debit after rollback-of-unknownThe operator has no record of op_id D. The player has a known balance B1. Rollback with original_op_id = D. 2. Debit with op_id = D: once with the original amount, once with a different amount1. ok envelope, original_found=false, balance B, no money moved. 2. Both Debits refused with ALREADY_ROLLED_BACK. Balance still B
W2-DELTA-02 duplicate debit when balance is now insufficientDebit D (stake S) applied. The balance is now below S. Also run with the session expiredThe same Debit resent: same op_id, same fingerprint, new request_idok envelope identical to the first response (same operator_tx_id and balance_after). Balance unchanged
W2-DELTA-03 duplicate with a different amountDebit D (amount A) appliedDebit with the same op_id and amount A′ ≠ AIDEMPOTENCY_CONFLICT. Balance unchanged. The stored result of D unchanged
W2-DELTA-04 credit after session expiryDebit applied in a session. The session/token has since expiredCredit for the same round, carrying the launch token of that sessionok envelope. The operator credits the balance exactly once
W2-DELTA-05 concurrent duplicatesA fresh op_id, a known balanceTwo or more simultaneous identical Debits (different request_id, same op_id)Every request gets the same ok response. The operator applies exactly one debit
W2-DELTA-06 exponent mismatchThe player’s currency has exponent e at the operatorDebit with the same currency and an exponent ≠ eCURRENCY_MISMATCH. No money moved. The op_id stays unused

PreviousRate limits, pagination, networkNextGetting started
Integration support: integration@gamealligator.comIntegration center
On this page
1. Summary2. Items2.1 Rollback of an unknown original2.2 Mandatory order of checks2.3 IDEMPOTENCY_CONFLICT2.4 What’s never refused2.5 Reconcile2.6 Concurrent duplicates2.7 Numbers2.8 Amount and schema validation2.9 Rollback matching, DebitCredit, balance-reducing corrections2.10 Free rounds and bonus-type credits2.11 What GA does on an unknown outcome2.12 Deliberate differences from other aggregators3. Conformance additions
↑ Back to top