Phoenix Games
Guidelines

Core Requirements

Technical requirements for webhook implementation

Performance

MetricValue
Maximum response time500ms
Recommended response timeUnder 100ms
Connect timeout5 seconds
Request timeout30 seconds (120s for batch deposit)

If your endpoint doesn't respond within the timeout, the request is treated as a failure. For connection errors specifically, Phoenix retries up to 3 times with exponential backoff (1s, 2s, 4s). Timeouts and other errors are not retried at the HTTP level, but unprocessed transactions will be redelivered through Phoenix's internal message queue.

HTTP Status

Always return HTTP 200 for both success and error responses. Use the type field in the JSON body to indicate the outcome:

{"type": "SUCCESS", "balance": 100.00, "timestamp": 1712401234567}
{"type": "ERROR", "code": "INSUFFICIENT_BALANCE", "balance": 100.00}

Non-200 responses without a parseable JSON body are treated as system failures.

Idempotency

Every transaction has a tx_id. If you receive the same tx_id twice, return the same response without processing the transaction again.

The tx_id format is predictable:

  • Withdraw: withdraw:bet:{bet_id}
  • Deposit: deposit:bet:{bet_id}

Store the tx_id and the result for each processed transaction. On a duplicate request, look up the stored result and return it.

Amounts

All amounts in requests are integers representing cents. A value of 5000 means 50.00 in the player's currency.

The balance field in responses is a float in the player's currency. A balance of 50.00 means 50 dollars/currency units.

Use integer arithmetic for all balance calculations. Do not use floating-point math on cent values.

Error Codes

CodeMeaning
INSUFFICIENT_BALANCENot enough funds for withdraw
PLAYER_NOT_FOUNDUnknown player ID
BET_NOT_FOUNDUnknown transaction ID (for rollback of non-existent withdraw)
BET_ALREADY_CLOSEDBet was already settled (for rollback after deposit)
INVALID_REQUESTMissing or malformed fields

Concurrency

Multiple requests for the same player can arrive at the same time. Use database-level locking (e.g., SELECT ... FOR UPDATE) or atomic operations to prevent race conditions. This is especially important for:

  • Multiple simultaneous withdraws from the same player
  • A withdraw and a rollback arriving at the same time
  • Duplicate tx_id requests arriving concurrently