BGaming Integration Guide
Panduan Integrasi BGaming
Use this guide to connect an operator to the backend: manage player balances with a transfer or seamless wallet, then launch and run games for your players.
Gunakan panduan ini untuk menghubungkan operator ke backend: kelola saldo pemain dengan transfer atau seamless wallet, lalu launch dan jalankan game untuk pemain Anda.
Overview
Gambaran Umum
The wallet API authenticates an operator, resolves its stored wallet type, validates the player and currency, and records financial activity in a provider-neutral ledger.
Wallet API mengautentikasi operator, membaca tipe wallet yang tersimpan, memvalidasi pemain dan mata uang, lalu mencatat aktivitas finansial pada ledger yang netral terhadap provider.
Transfer wallet is used when this backend owns the playable balance. Use deposit and withdraw to move funds, and use balance, rollback, and transaction history for operations and audit.
Transfer wallet digunakan ketika backend ini menjadi pemilik saldo bermain. Gunakan deposit dan withdraw untuk memindahkan dana, serta balance, rollback, dan riwayat transaksi untuk operasi dan audit.
Seamless wallet is used when the operator keeps the authoritative balance. The backend sends signed requests to the operator's wallet service for balance, debit, credit, rollback, and transaction-status checks.
Seamless wallet digunakan ketika operator tetap menjadi pemilik saldo utama. Backend mengirim request bertanda tangan ke layanan wallet operator untuk balance, debit, credit, rollback, dan pemeriksaan status transaksi.
Authentication
Autentikasi
All public /api/v1/wallet/* routes require the active operator API token as a bearer token. POST requests also require JSON content type.
Semua route publik /api/v1/wallet/* memerlukan API token operator aktif sebagai bearer token. Request POST juga wajib menggunakan content type JSON.
If the operator has an IP allowlist, the request must come from one of those exact IP addresses. Proxy headers are trusted only when the backend is configured with trusted proxy CIDRs.
Jika operator memiliki daftar IP yang diizinkan, request harus berasal dari salah satu IP tersebut. Header proxy hanya dipercaya jika backend dikonfigurasi dengan CIDR proxy tepercaya.
Public wallet requests are not HMAC-signed. HMAC signing applies only to outbound seamless wallet callbacks.
Request wallet publik tidak menggunakan HMAC. HMAC hanya digunakan untuk callback seamless wallet yang dikirim keluar oleh backend.
Authorization: Bearer <operator_api_token>
Content-Type: application/json
X-Request-ID: request-unique-id
X-Request-ID is optional. When omitted or invalid, the backend creates one and returns it in the response header.
X-Request-ID bersifat opsional. Jika tidak dikirim atau tidak valid, backend akan membuatnya dan mengembalikannya pada header respons.
Common Response Format
Format Respons Umum
Every application outcome uses HTTP 200 OK. Always check the JSON status and code. Success contains data only; failure contains error only.
Semua hasil aplikasi menggunakan HTTP 200 OK. Selalu periksa status dan code pada JSON. Respons sukses hanya memiliki data; respons gagal hanya memiliki error.
{
"status": true,
"code": "SUCCESS",
"data": {}
}
{
"status": false,
"code": "VALIDATION_ERROR",
"error": {}
}
Decimal Money Rules
Aturan Nominal Desimal
Money is decimal 1:1 with a maximum of two decimal places. Do not convert to cents, sen, or other minor units. Amounts must be greater than zero and no greater than 1000000000000.00.
Nominal uang menggunakan desimal 1:1 dengan maksimal dua angka di belakang koma. Jangan mengubah nominal menjadi cents, sen, atau minor unit lainnya. Amount harus lebih besar dari nol dan tidak lebih dari 1000000000000.00.
- IDR 100000.00 is sent as
"100000.00". - USD 1.00 is sent as
"1.00". "1.001", zero, and negative values are rejected.
- IDR 100000.00 dikirim sebagai
"100000.00". - USD 1.00 dikirim sebagai
"1.00". "1.001", nol, dan nilai negatif akan ditolak.
The current API serializes decimal response fields as JSON strings and may omit trailing zeros, for example "100000". Treat that value as the same decimal amount as 100000.00.
API saat ini menulis field desimal pada respons sebagai string JSON dan dapat menghilangkan nol di belakang, misalnya "100000". Nilai tersebut tetap sama dengan desimal 100000.00.
Idempotency
reference_id is the idempotency key for debit, deposit, and withdraw. rollback_reference_id is the idempotency key for rollback. Keys are unique per operator.
reference_id adalah idempotency key untuk debit, deposit, dan withdraw. rollback_reference_id adalah idempotency key untuk rollback. Key harus unik per operator.
For seamless callbacks, request_id is a per-call correlation UUID generated by the backend. It can change between calls and must not be used as the financial idempotency key. Deduplicate mutations by reference_id.
Pada callback seamless, request_id adalah UUID korelasi per pemanggilan yang dibuat oleh backend. Nilainya dapat berubah antar pemanggilan dan tidak boleh digunakan sebagai idempotency key finansial. Deduplicate mutasi berdasarkan reference_id.
- Retry the same financial intent with the same reference and identical fields.
- An identical completed duplicate returns the original successful result without changing the balance again.
- Reusing a reference with different user, amount, currency, or operation returns
IDEMPOTENCY_CONFLICT. - After
TRANSACTION_STATUS_UNKNOWN, never create a new reference for the same intent.
- Ulangi transaksi yang sama dengan reference dan field yang sama.
- Duplikat identik yang sudah selesai mengembalikan hasil awal tanpa mengubah saldo lagi.
- Penggunaan ulang reference dengan user, amount, currency, atau operasi berbeda menghasilkan
IDEMPOTENCY_CONFLICT. - Setelah
TRANSACTION_STATUS_UNKNOWN, jangan membuat reference baru untuk transaksi yang sama.
Games: Hosts & Base URLs
Game: Host & Base URL
Game delivery uses three hosts served by one backend. The operator API (player and launch) lives on the API host. The launch URL opens on the game host, and the game loads static assets from the CDN host.
Pengiriman game memakai tiga host yang dilayani satu backend. API operator (pemain dan launch) berada di host API. Launch URL terbuka di host game, dan game memuat aset statis dari host CDN.
Replace these example hosts with the base URLs assigned to your environment.
Ganti host contoh ini dengan base URL yang diberikan untuk environment Anda.
Purpose Host Used for
API api-bgaming.ohmybet.online Player + launch + gameplay API
Game shell bgaming.ohmybet.online Opens the launch_url in a browser
CDN assets cdn-bgaming.ohmybet.online Game loader, bundle, textures, fontsTujuan Host Dipakai untuk
API api-bgaming.ohmybet.online API pemain + launch + gameplay
Shell game bgaming.ohmybet.online Membuka launch_url di browser
Aset CDN cdn-bgaming.ohmybet.online Loader game, bundle, tekstur, fonthttps://api-bgaming.ohmybet.online/api/v1
Create a Player
Buat Pemain
A player is owned by the operator and identified by a stable external_user_id. Create the player once before launching a game. The player currency must be an exact three-letter uppercase code.
Pemain dimiliki oleh operator dan diidentifikasi oleh external_user_id yang stabil. Buat pemain sekali sebelum launch game. Currency pemain harus kode tiga huruf kapital persis.
Headers: Authorization: Bearer <operator_api_token>, Content-Type: application/json
Request fields
Field request
Field Type Requirement Description Example
operator_id string Required Must equal the authenticated operator. 93dc...934c5f
external_user_id string Required Stable player ID owned by operator. namaakun
username string Optional Display name. Akun Satu
currency string Required Exact uppercase 3-letter currency. USDField Tipe Kebutuhan Deskripsi Contoh
operator_id string Wajib Harus sama dengan operator terautentikasi. 93dc...934c5f
external_user_id string Wajib ID pemain stabil milik operator. namaakun
username string Opsional Nama tampilan. Akun Satu
currency string Wajib Mata uang 3 huruf kapital persis. USDNotes: Reusing the same external_user_id returns the existing player. New players start with a zero balance; fund a transfer-wallet player with the deposit endpoint.
Catatan: Memakai ulang external_user_id yang sama mengembalikan pemain yang ada. Pemain baru bersaldo nol; isi saldo pemain transfer wallet dengan endpoint deposit.
{
"operator_id": "93dc0dc4-aa54-40f7-9efe-e8ecf4934c5f",
"external_user_id": "namaakun",
"currency": "USD"
}{
"status": true,
"code": "SUCCESS",
"data": {
"id": "339b0990-79ed-4084-be06-2c49806d0f9f",
"operator_id": "93dc0dc4-aa54-40f7-9efe-e8ecf4934c5f",
"external_user_id": "namaakun",
"currency": "USD",
"balance_amount": "0",
"status": "active"
}
}Launch a Game
Launch Game
Request a one-time launch URL for a player and a game. Open the returned launch_url in the player's browser to start the session. The launch token is single-use and short-lived; request a fresh launch for each play session.
Minta launch URL sekali pakai untuk seorang pemain dan sebuah game. Buka launch_url yang dikembalikan di browser pemain untuk memulai sesi. Launch token bersifat sekali pakai dan berumur pendek; minta launch baru untuk setiap sesi bermain.
Headers: Authorization: Bearer <operator_api_token>, Content-Type: application/json
Request fields
Field request
Field Type Requirement Description Example
game_code string Required Canonical game code. BonanzaTrillion
external_user_id string Required Active player external ID. namaakun
currency string Required Exact player currency. USDField Tipe Kebutuhan Deskripsi Contoh
game_code string Wajib Kode game kanonik. BonanzaTrillion
external_user_id string Wajib External ID pemain aktif. namaakun
currency string Wajib Currency pemain persis. USDNotes: The player and a currency configuration for the game must exist. Unknown game returns GAME_NOT_FOUND; an unconfigured currency returns CURRENCY_NOT_CONFIGURED.
Catatan: Pemain dan konfigurasi currency untuk game harus ada. Game tak dikenal menghasilkan GAME_NOT_FOUND; currency yang belum dikonfigurasi menghasilkan CURRENCY_NOT_CONFIGURED.
{
"game_code": "BonanzaTrillion",
"external_user_id": "namaakun",
"currency": "USD"
}{
"status": true,
"code": "SUCCESS",
"data": {
"launch_url": "https://bgaming.ohmybet.online/games/BonanzaTrillion/USD?launch_token=...",
"game_code": "BonanzaTrillion",
"game_type": "slot",
"currency": "USD"
}
}BASE_URL="https://api-bgaming.ohmybet.online"
TOKEN="op_live_b4fdec69a4d16b8c62f6af178a3eb68ae0c6bb553f553603"
OPERATOR_ID="93dc0dc4-aa54-40f7-9efe-e8ecf4934c5f"
curl -sS -X POST "$BASE_URL/api/v1/game/launch" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"game_code\":\"BonanzaTrillion\",\"external_user_id\":\"namaakun\",\"currency\":\"USD\"}"Gameplay Protocol
Protokol Gameplay
After the launch URL opens, the game client talks to the gameplay endpoint directly. This is the native game protocol, not the operator wallet API. As an operator you do not call it; it is documented here for reference.
Setelah launch URL terbuka, client game berkomunikasi langsung ke endpoint gameplay. Ini protokol game native, bukan wallet API operator. Sebagai operator Anda tidak memanggilnya; didokumentasikan di sini sebagai referensi.
The player session is authenticated by the play_token in the URL path. A CSRF token is verified only if the client sends the X-CSRF-Token header.
Sesi pemain diautentikasi oleh play_token di path URL. CSRF token diverifikasi hanya jika client mengirim header X-CSRF-Token.
Commands include init (load options and balance), spin (place a bet), and freespin (play a free spin). Every response uses HTTP 200 and the native game shape with api_version, the command payload, balance, and flow.
Command meliputi init (muat opsi dan saldo), spin (pasang taruhan), dan freespin (mainkan free spin). Setiap respons memakai HTTP 200 dan bentuk game native dengan api_version, payload command, balance, dan flow.
POST /api/BonanzaTrillion/3035793/<play_token>
X-CSRF-Token: <csrf_token>
Content-Type: application/json
{ "command": "init" }{
"api_version": "2",
"options": {
"available_bets": [20, 40, 60, 100, 200],
"default_bet": 100,
"currency": { "code": "USD", "symbol": "$", "subunits": 100, "exponent": 2 }
},
"balance": { "game": 0, "wallet": 100000 },
"flow": { "state": "ready", "command": "init", "available_actions": ["init", "spin"] }
}{ "command": "spin", "options": { "bet": 100 } }Supported Games
Game Tersedia
Each game is identified by its canonical game_code and exposes a per-currency bet configuration. Long-run payout follows the player or operator RTP setting.
Setiap game diidentifikasi oleh game_code kanonik dan punya konfigurasi taruhan per-currency. Payout jangka panjang mengikuti pengaturan RTP pemain atau operator.
game_code Type Description
BonanzaTrillion slot Cascade slot with tumbling pays, scatter free spins, buy feature, and x2-x500 multipliers.
Aviamasters casual Flight game; the plane collects multipliers and must land to win, or crashes into the sea.game_code Tipe Deskripsi
BonanzaTrillion slot Slot cascade dengan tumbling pays, free spins scatter, beli fitur, dan multiplier x2-x500.
Aviamasters casual Game penerbangan; pesawat mengumpulkan multiplier dan harus mendarat untuk menang, atau jatuh ke laut.Live Trial
Coba Langsung
Launch either game against the live environment using the demo operator and player below. Each click requests a fresh launch URL and opens the game in a new tab. The demo credentials are intentionally public for trial use.
Launch salah satu game ke environment live memakai operator dan pemain demo di bawah. Setiap klik meminta launch URL baru dan membuka game di tab baru. Kredensial demo ini sengaja dibuat publik untuk keperluan uji coba.
API host https://api-bgaming.ohmybet.online
Operator ID 93dc0dc4-aa54-40f7-9efe-e8ecf4934c5f
Player namaakun
Currency USDHost API https://api-bgaming.ohmybet.online
Operator ID 93dc0dc4-aa54-40f7-9efe-e8ecf4934c5f
Pemain namaakun
Currency USDBonanza Trillion
slotCascade slot with free spins and buy feature.
Slot cascade dengan free spins dan beli fitur.
Aviamasters
casualFlight game; land the plane to win.
Game penerbangan; daratkan pesawat untuk menang.
Transfer Wallet
Transfer mode stores the authoritative playable balance in this backend. A common integration flow is: check balance, deposit funds, withdraw funds when required, and use rollback only to reverse one completed transaction.
Mode transfer menyimpan saldo bermain utama di backend ini. Alur integrasi umumnya: periksa saldo, lakukan deposit, lakukan withdraw bila diperlukan, dan gunakan rollback hanya untuk membalik satu transaksi yang sudah selesai.
https://api-bgaming.ohmybet.online/api/v1
Replace the example host with the base URL assigned to your environment.
Ganti host contoh dengan base URL yang diberikan untuk environment Anda.
Balance
Returns the current local balance for an active transfer-wallet player. This endpoint does not create a ledger transaction.
Mengembalikan saldo lokal saat ini untuk pemain transfer wallet yang aktif. Endpoint ini tidak membuat transaksi ledger.
Headers: Authorization: Bearer <operator_api_token>
Request body: None. Send the fields as query parameters.
Body request: Tidak ada. Kirim field sebagai query parameter.
Query fields
Field query
Field Type Requirement Description Example
external_user_id string Required Player ID owned by the operator. player-1001
currency string Required Exact uppercase 3-letter currency. IDRField Tipe Kebutuhan Deskripsi Contoh
external_user_id string Wajib ID pemain milik operator. player-1001
currency string Wajib Mata uang 3 huruf kapital persis. IDRNotes: Currency must match the player currency. Unknown users return USER_NOT_FOUND.
Catatan: Currency harus sama dengan currency pemain. User yang tidak ditemukan menghasilkan USER_NOT_FOUND.
GET /api/v1/wallet/balance?external_user_id=player-1001¤cy=IDR
Authorization: Bearer <operator_api_token>{
"status": true,
"code": "SUCCESS",
"data": {
"balance_amount": "100000",
"currency": "IDR",
"timestamp": "2026-06-12T00:00:00Z"
}
}{
"status": false,
"code": "CURRENCY_MISMATCH",
"error": {}
}Deposit
Credits the transfer-wallet player's local balance and writes one completed ledger row.
Menambah saldo lokal pemain transfer wallet dan menulis satu row ledger berstatus completed.
Headers: Authorization: Bearer <operator_api_token>, Content-Type: application/json
Request fields
Field request
Field Type Requirement Description Example
operator_id string Required Must equal the authenticated operator. 7fe0...2b1
external_user_id string Required Active player external ID. player-1001
reference_id string Required Unique idempotency key per operator. deposit-0001
amount decimal Required Positive, max 2 decimals. 100000.00
currency string Required Exact player currency. IDRField Tipe Kebutuhan Deskripsi Contoh
operator_id string Wajib Harus sama dengan operator terautentikasi. 7fe0...2b1
external_user_id string Wajib External ID pemain aktif. player-1001
reference_id string Wajib Idempotency key unik per operator. deposit-0001
amount decimal Wajib Positif, maksimal 2 desimal. 100000.00
currency string Wajib Harus sama dengan currency pemain. IDRNotes: Unknown JSON fields are rejected. A different operator_id returns FORBIDDEN.
Catatan: Field JSON yang tidak dikenal akan ditolak. operator_id yang berbeda menghasilkan FORBIDDEN.
{
"operator_id": "7fe0c978-3eb2-4e19-bc69-e2cdb74a12b1",
"external_user_id": "player-1001",
"reference_id": "deposit-0001",
"amount": "100000.00",
"currency": "IDR"
}{
"status": true,
"code": "SUCCESS",
"data": {
"id": "c2ea59c1-d143-46d1-bff4-6e302038849b",
"operator_id": "7fe0c978-3eb2-4e19-bc69-e2cdb74a12b1",
"user_id": "2ff15b51-a20a-4694-a01a-f1ad77ec34d7",
"external_user_id": "player-1001",
"wallet_type": "transfer",
"type": "credit",
"amount": "100000",
"currency": "IDR",
"balance_before": "0",
"balance_after": "100000",
"reference_id": "deposit-0001",
"status": "completed",
"failure_code": null,
"metadata": {},
"created_at": "2026-06-12T00:00:00Z",
"completed_at": "2026-06-12T00:00:00Z"
}
}{
"status": false,
"code": "IDEMPOTENCY_CONFLICT",
"error": {}
}Withdraw
Debits the transfer-wallet player's local balance. The operation fails without changing the balance when funds are insufficient.
Mengurangi saldo lokal pemain transfer wallet. Operasi gagal tanpa mengubah saldo jika saldo tidak mencukupi.
Headers: Authorization: Bearer <operator_api_token>, Content-Type: application/json
Request fields
Field request
Field Type Requirement Description Example
operator_id string Required Must equal the authenticated operator. 7fe0...2b1
external_user_id string Required Active player external ID. player-1001
reference_id string Required Unique idempotency key per operator. withdraw-0001
amount decimal Required Positive, max 2 decimals. 25000.00
currency string Required Exact player currency. IDRField Tipe Kebutuhan Deskripsi Contoh
operator_id string Wajib Harus sama dengan operator terautentikasi. 7fe0...2b1
external_user_id string Wajib External ID pemain aktif. player-1001
reference_id string Wajib Idempotency key unik per operator. withdraw-0001
amount decimal Wajib Positif, maksimal 2 desimal. 25000.00
currency string Wajib Harus sama dengan currency pemain. IDRNotes: An insufficient attempt is recorded as a failed debit and returns INSUFFICIENT_BALANCE.
Catatan: Percobaan dengan saldo tidak cukup dicatat sebagai debit gagal dan menghasilkan INSUFFICIENT_BALANCE.
{
"operator_id": "7fe0c978-3eb2-4e19-bc69-e2cdb74a12b1",
"external_user_id": "player-1001",
"reference_id": "withdraw-0001",
"amount": "25000.00",
"currency": "IDR"
}{
"status": true,
"code": "SUCCESS",
"data": {
"id": "52406740-b02d-4ffc-955f-598cc7f013d7",
"operator_id": "7fe0c978-3eb2-4e19-bc69-e2cdb74a12b1",
"user_id": "2ff15b51-a20a-4694-a01a-f1ad77ec34d7",
"external_user_id": "player-1001",
"wallet_type": "transfer",
"type": "debit",
"amount": "25000",
"currency": "IDR",
"balance_before": "100000",
"balance_after": "75000",
"reference_id": "withdraw-0001",
"status": "completed",
"failure_code": null,
"metadata": {},
"created_at": "2026-06-12T00:01:00Z",
"completed_at": "2026-06-12T00:01:00Z"
}
}{
"status": false,
"code": "INSUFFICIENT_BALANCE",
"error": {}
}Rollback
Reverses one completed credit or debit. The amount and currency are loaded from the original ledger row and must not be sent by the client.
Membalik satu credit atau debit yang sudah completed. Amount dan currency dibaca dari ledger transaksi awal dan tidak boleh dikirim oleh client.
Headers: Authorization: Bearer <operator_api_token>, Content-Type: application/json
Request fields
Field request
Field Type Requirement Description Example
external_user_id string Required Owner of the original transaction. player-1001
original_reference_id string Required Reference of completed credit/debit. withdraw-0001
rollback_reference_id string Required Unique idempotency key for rollback. rollback-0001Field Tipe Kebutuhan Deskripsi Contoh
external_user_id string Wajib Pemilik transaksi awal. player-1001
original_reference_id string Wajib Reference credit/debit yang completed. withdraw-0001
rollback_reference_id string Wajib Idempotency key unik untuk rollback. rollback-0001Notes: Only one rollback is allowed per original transaction. A completed rollback marks the original transaction as reversed.
Catatan: Hanya satu rollback diperbolehkan untuk setiap transaksi awal. Rollback yang selesai mengubah status transaksi awal menjadi reversed.
{
"external_user_id": "player-1001",
"original_reference_id": "withdraw-0001",
"rollback_reference_id": "rollback-0001"
}{
"status": true,
"code": "SUCCESS",
"data": {
"transaction_id": "bbd69c4f-7bc6-46d2-b6ce-3bdbf927d75a",
"balance_after": "99000",
"currency": "IDR",
"timestamp": "2026-06-12T00:03:00Z"
}
}{
"status": false,
"code": "TRANSACTION_ALREADY_ROLLED_BACK",
"error": {}
}Transactions
Returns ledger rows owned by the authenticated operator. Results are ordered newest first.
Mengembalikan row ledger milik operator terautentikasi. Hasil diurutkan dari yang terbaru.
Headers: Authorization: Bearer <operator_api_token>
Request body: None. All filters are query parameters.
Body request: Tidak ada. Semua filter dikirim sebagai query parameter.
Query fields
Field query
Field Type Requirement Description Example
external_user_id string Optional Filter by player external ID. player-1001
type string Optional credit, debit, or rollback. debit
status string Optional pending, completed, failed, reversed, mismatch. completed
reference_id string Optional Exact reference filter. withdraw-0001
limit integer Optional Default 20; minimum 1; maximum 100. 20
offset integer Optional Default 0; range 0 through 10000. 0Field Tipe Kebutuhan Deskripsi Contoh
external_user_id string Opsional Filter berdasarkan external ID pemain. player-1001
type string Opsional credit, debit, atau rollback. debit
status string Opsional pending, completed, failed, reversed, mismatch. completed
reference_id string Opsional Filter reference persis. withdraw-0001
limit integer Opsional Default 20; minimum 1; maksimum 100. 20
offset integer Opsional Default 0; rentang 0 sampai 10000. 0Notes: This is ledger history, not a single-purpose transaction-status endpoint.
Catatan: Endpoint ini adalah riwayat ledger, bukan endpoint khusus status satu transaksi.
GET /api/v1/wallet/transactions?external_user_id=player-1001&limit=20&offset=0
Authorization: Bearer <operator_api_token>{
"status": true,
"code": "SUCCESS",
"data": {
"items": [
{
"id": "52406740-b02d-4ffc-955f-598cc7f013d7",
"operator_id": "7fe0c978-3eb2-4e19-bc69-e2cdb74a12b1",
"user_id": "2ff15b51-a20a-4694-a01a-f1ad77ec34d7",
"external_user_id": "player-1001",
"wallet_type": "transfer",
"type": "debit",
"amount": "25000",
"currency": "IDR",
"balance_before": "100000",
"balance_after": "75000",
"reference_id": "withdraw-0001",
"status": "completed",
"failure_code": null,
"metadata": {},
"created_at": "2026-06-12T00:01:00Z",
"completed_at": "2026-06-12T00:01:00Z"
}
],
"limit": 20,
"offset": 0
}
}{
"status": false,
"code": "INVALID_TRANSACTION_STATUS",
"error": {}
}Testing Transfer Wallet
Pengujian Transfer Wallet
- Start with a player balance of 0.00.
- Deposit 100000.00. Expected balance: 100000.00.
- Withdraw 25000.00. Expected balance: 75000.00.
- Rollback the withdraw. Expected balance: 100000.00.
- Repeat the same request with the same reference. The balance must not change twice.
- Mulai dengan saldo pemain 0.00.
- Deposit 100000.00. Saldo yang diharapkan: 100000.00.
- Withdraw 25000.00. Saldo yang diharapkan: 75000.00.
- Rollback withdraw. Saldo yang diharapkan: 100000.00.
- Ulangi request yang sama dengan reference yang sama. Saldo tidak boleh berubah dua kali.
BASE_URL="https://api.example.com"
TOKEN="replace-with-operator-token"
OPERATOR_ID="7fe0c978-3eb2-4e19-bc69-e2cdb74a12b1"
curl -sS -X POST "$BASE_URL/api/v1/wallet/deposit" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"operator_id\":\"$OPERATOR_ID\",\"external_user_id\":\"player-1001\",\"reference_id\":\"test-deposit-1\",\"amount\":\"100000.00\",\"currency\":\"IDR\"}"
curl -sS -X POST "$BASE_URL/api/v1/wallet/withdraw" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"operator_id\":\"$OPERATOR_ID\",\"external_user_id\":\"player-1001\",\"reference_id\":\"test-withdraw-1\",\"amount\":\"25000.00\",\"currency\":\"IDR\"}"
curl -sS -X POST "$BASE_URL/api/v1/wallet/rollback" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"external_user_id":"player-1001","original_reference_id":"test-withdraw-1","rollback_reference_id":"test-rollback-1"}'
curl -sS "$BASE_URL/api/v1/wallet/balance?external_user_id=player-1001¤cy=IDR" \
-H "Authorization: Bearer $TOKEN"Seamless Wallet
In seamless mode, the operator wallet remains the balance authority. Configure the operator with wallet_type = seamless, an HTTPS callback_url, and an active credential. The backend records mutation state locally, then calls the operator wallet service.
Pada mode seamless, wallet operator tetap menjadi pemilik saldo utama. Konfigurasikan operator dengan wallet_type = seamless, callback_url HTTPS, dan credential aktif. Backend mencatat status mutasi secara lokal, lalu memanggil layanan wallet operator.
- The backend receives or creates a game wallet operation.
- For debit, credit, and rollback, it writes a pending ledger row.
- It sends a signed POST request to the operator callback URL.
- A valid success response completes the local ledger row.
- An unknown mutation outcome remains pending and is checked through transaction status.
- Backend menerima atau membuat operasi wallet game.
- Untuk debit, credit, dan rollback, backend menulis row ledger pending.
- Backend mengirim POST bertanda tangan ke callback URL operator.
- Respons sukses yang valid menyelesaikan row ledger lokal.
- Hasil mutasi yang belum pasti tetap pending dan diperiksa melalui transaction status.
Public API Triggers
Pemicu API Publik
The operator-facing backend API exposes the routes below. They use bearer authentication described above.
API backend yang digunakan operator menyediakan route berikut. Semua route menggunakan bearer authentication yang dijelaskan sebelumnya.
Method Path Request fields Notes
GET /api/v1/wallet/balance external_user_id (Required), currency (Required) Calls callback /balance.
POST /api/v1/wallet/debit external_user_id, reference_id, amount, currency (all Required) Calls callback /debit.
POST /api/v1/wallet/rollback external_user_id, original_reference_id, rollback_reference_id Calls callback /rollback.
GET /api/v1/wallet/transactions All query fields Optional; same filters as transfer documentation Reads local audit ledger.Method Path Field request Catatan
GET /api/v1/wallet/balance external_user_id (Wajib), currency (Wajib) Memanggil callback /balance.
POST /api/v1/wallet/debit external_user_id, reference_id, amount, currency (semua Wajib) Memanggil callback /debit.
POST /api/v1/wallet/rollback external_user_id, original_reference_id, rollback_reference_id Memanggil callback /rollback.
GET /api/v1/wallet/transactions Semua field query Opsional; filter sama dengan dokumentasi transfer Membaca audit ledger lokal.There is no public /api/v1/wallet/credit route. Credit is initiated by internal game settlement. There is also no public transaction-status route; reconciliation calls the operator callback directly.
Tidak ada route publik /api/v1/wallet/credit. Credit dibuat oleh settlement game internal. Tidak ada route publik transaction-status; proses rekonsiliasi memanggil callback operator secara langsung.
{
"external_user_id": "player-1001",
"reference_id": "bet-round-0001",
"amount": "1000.00",
"currency": "IDR"
}{
"status": true,
"code": "SUCCESS",
"data": {
"transaction_id": "7d64613c-4e45-4bc5-9fea-2ac0cf51cadd",
"balance_after": "99000",
"currency": "IDR",
"timestamp": "2026-06-12T01:00:00Z"
}
}{
"status": false,
"code": "TRANSACTION_STATUS_UNKNOWN",
"error": {}
}Callback Authentication and Signing
Autentikasi dan Signature Callback
The backend sends all seamless callbacks as POST JSON requests to the configured callback base URL. The operator must verify the HMAC before processing the request.
Backend mengirim semua callback seamless sebagai request POST JSON ke callback base URL yang dikonfigurasi. Operator wajib memverifikasi HMAC sebelum memproses request.
Header Requirement Description
Content-Type Required application/json
X-Signature Required Lowercase hex HMAC-SHA256.
X-Timestamp Required RFC3339; also included in the JSON body.
X-Key-Version Required Credential key version used for signing.Header Kebutuhan Deskripsi
Content-Type Wajib application/json
X-Signature Wajib HMAC-SHA256 dalam hex lowercase.
X-Timestamp Wajib RFC3339; juga terdapat pada body JSON.
X-Key-Version Wajib Versi credential yang digunakan untuk signature.Notes: Verify the exact raw JSON bytes received. Do not parse and re-encode the body before signature verification.
Catatan: Verifikasi byte JSON mentah yang diterima. Jangan parse lalu encode ulang body sebelum memverifikasi signature.
POST
/debit
2026-06-12T01:00:00Z
{"operator_code":"OPERATOR_A",...}operation = METHOD + "\n" + PATH + "\n" + X-Timestamp
message = operation + "\n" + raw_json_body
signature = hex(HMAC-SHA256(secret_key, message))Callback: Balance
The operator implements this endpoint to return the authoritative player balance.
Operator mengimplementasikan endpoint ini untuk mengembalikan saldo utama pemain.
Headers: Content-Type, X-Signature, X-Timestamp, X-Key-Version
Request fields
Field request
Field Type Requirement Description Example
operator_code string Required Canonical authenticated operator code. OPERATOR_A
external_user_id string Required Player external ID. player-1001
currency string Required Exact uppercase currency. IDR
request_id UUID Required Unique outbound request correlation ID. 4d33...78a2
timestamp string Required RFC3339 signing timestamp. 2026-06-12T01:00:00Z
metadata object Conditional Sent only when internal context exists. {"game_id":"duckhunters"}Field Tipe Kebutuhan Deskripsi Contoh
operator_code string Wajib Kode operator terautentikasi. OPERATOR_A
external_user_id string Wajib External ID pemain. player-1001
currency string Wajib Currency kapital persis. IDR
request_id UUID Wajib ID korelasi request outbound yang unik. 4d33...78a2
timestamp string Wajib Timestamp RFC3339 untuk signature. 2026-06-12T01:00:00Z
metadata object Kondisional Dikirim hanya jika konteks internal ada. {"game_id":"duckhunters"}Notes: Return HTTP 200. The response currency must exactly match the request. A timeout maps to UPSTREAM_TIMEOUT on the public API.
Catatan: Kembalikan HTTP 200. Currency pada respons harus sama persis dengan request. Timeout dipetakan menjadi UPSTREAM_TIMEOUT pada API publik.
{
"operator_code": "OPERATOR_A",
"external_user_id": "player-1001",
"currency": "IDR",
"request_id": "4d33e43a-85d9-4986-b96a-5c3a523d78a2",
"timestamp": "2026-06-12T01:00:00Z"
}{
"status": true,
"code": "SUCCESS",
"data": {
"balance": "100000.00",
"currency": "IDR"
}
}{
"status": false,
"code": "USER_NOT_FOUND",
"error": {}
}Callback: Debit
Deducts money from the operator-owned player wallet. The operator must process reference_id idempotently.
Mengurangi saldo wallet pemain milik operator. Operator wajib memproses reference_id secara idempotent.
Headers: Content-Type, X-Signature, X-Timestamp, X-Key-Version
Request fields
Field request
Field Type Requirement Description Example
operator_code string Required Canonical operator code. OPERATOR_A
external_user_id string Required Player external ID. player-1001
currency string Required Exact uppercase currency. IDR
request_id UUID Required Unique request correlation ID. 4d33...78a2
timestamp string Required RFC3339 signing timestamp. 2026-06-12T01:00:00Z
transaction_id UUID Required Backend outbound transaction ID. 9d1a...e042
reference_id string Required Stable financial idempotency key. bet-round-0001
amount decimal Required Positive decimal, max 2 places. 1000.00
metadata object Conditional Sent only when internal context exists. {"round_id":"round-1"}Field Tipe Kebutuhan Deskripsi Contoh
operator_code string Wajib Kode operator. OPERATOR_A
external_user_id string Wajib External ID pemain. player-1001
currency string Wajib Currency kapital persis. IDR
request_id UUID Wajib ID korelasi request yang unik. 4d33...78a2
timestamp string Wajib Timestamp RFC3339 untuk signature. 2026-06-12T01:00:00Z
transaction_id UUID Wajib ID transaksi outbound dari backend. 9d1a...e042
reference_id string Wajib Idempotency key finansial yang stabil. bet-round-0001
amount decimal Wajib Desimal positif, maksimal 2 angka. 1000.00
metadata object Kondisional Dikirim hanya jika konteks internal ada. {"round_id":"round-1"}Notes: On success, return matching reference_id, amount, and currency. Any HTTP non-200, malformed body, or mismatched success data becomes an unknown outcome.
Catatan: Pada respons sukses, kembalikan reference_id, amount, dan currency yang sama. HTTP selain 200, body rusak, atau data sukses yang berbeda dianggap sebagai hasil belum pasti.
{
"operator_code": "OPERATOR_A",
"external_user_id": "player-1001",
"currency": "IDR",
"request_id": "4d33e43a-85d9-4986-b96a-5c3a523d78a2",
"timestamp": "2026-06-12T01:00:00Z",
"transaction_id": "9d1af7a2-b8aa-4d54-a25b-f0f062c9e042",
"reference_id": "bet-round-0001",
"amount": "1000.00"
}{
"status": true,
"code": "SUCCESS",
"data": {
"transaction_id": "operator-debit-10001",
"reference_id": "bet-round-0001",
"amount": "1000.00",
"balance_after": "99000.00",
"currency": "IDR"
}
}{
"status": false,
"code": "INSUFFICIENT_BALANCE",
"error": {}
}Callback: Credit
Adds a game settlement or win to the operator-owned wallet. This callback is initiated internally; there is no public credit route.
Menambahkan settlement atau kemenangan game ke wallet milik operator. Callback ini dibuat secara internal; tidak ada route credit publik.
Headers: Content-Type, X-Signature, X-Timestamp, X-Key-Version
Request fields
Field request
Field Type Requirement Description Example
operator_code string Required Canonical operator code. OPERATOR_A
external_user_id string Required Player external ID. player-1001
currency string Required Exact uppercase currency. IDR
request_id UUID Required Unique request correlation ID. 6fb8...80dc
timestamp string Required RFC3339 signing timestamp. 2026-06-12T01:01:00Z
transaction_id UUID Required Backend outbound transaction ID. d1ae...f393
reference_id string Required Stable credit idempotency key. win-round-0001
amount decimal Required Positive decimal, max 2 places. 2500.00
metadata object Conditional Sent only when internal context exists. {"round_id":"round-1"}Field Tipe Kebutuhan Deskripsi Contoh
operator_code string Wajib Kode operator. OPERATOR_A
external_user_id string Wajib External ID pemain. player-1001
currency string Wajib Currency kapital persis. IDR
request_id UUID Wajib ID korelasi request yang unik. 6fb8...80dc
timestamp string Wajib Timestamp RFC3339 untuk signature. 2026-06-12T01:01:00Z
transaction_id UUID Wajib ID transaksi outbound dari backend. d1ae...f393
reference_id string Wajib Idempotency key credit yang stabil. win-round-0001
amount decimal Wajib Desimal positif, maksimal 2 angka. 2500.00
metadata object Kondisional Dikirim hanya jika konteks internal ada. {"round_id":"round-1"}Notes: Duplicate delivery with identical fields must return the original result and must not credit twice.
Catatan: Pengiriman ulang dengan field identik harus mengembalikan hasil awal dan tidak boleh menambah saldo dua kali.
{
"operator_code": "OPERATOR_A",
"external_user_id": "player-1001",
"currency": "IDR",
"request_id": "6fb82253-0602-4a31-b776-cf7a04cb80dc",
"timestamp": "2026-06-12T01:01:00Z",
"transaction_id": "d1ae0e35-9bc7-4059-a2e7-5fcc1a51f393",
"reference_id": "win-round-0001",
"amount": "2500.00"
}{
"status": true,
"code": "SUCCESS",
"data": {
"transaction_id": "operator-credit-10001",
"reference_id": "win-round-0001",
"amount": "2500.00",
"balance_after": "101500.00",
"currency": "IDR"
}
}{
"status": false,
"code": "IDEMPOTENCY_CONFLICT",
"error": {}
}Callback: Rollback
Reverses one completed debit or credit in the operator wallet.
Membalik satu debit atau credit yang sudah completed pada wallet operator.
Headers: Content-Type, X-Signature, X-Timestamp, X-Key-Version
Request fields
Field request
Field Type Requirement Description Example
operator_code string Required Canonical operator code. OPERATOR_A
external_user_id string Required Player external ID. player-1001
currency string Required Copied from original ledger row. IDR
request_id UUID Required Unique request correlation ID. 1a4b...da31
timestamp string Required RFC3339 signing timestamp. 2026-06-12T01:02:00Z
transaction_id UUID Required Backend outbound rollback ID. 7560...4900
reference_id string Required Rollback idempotency key. rollback-0001
original_reference_id string Required Original debit or credit reference. bet-round-0001
amount decimal Required Copied from original ledger row. 1000.00
metadata object Conditional Sent only when internal context exists. {"round_id":"round-1"}Field Tipe Kebutuhan Deskripsi Contoh
operator_code string Wajib Kode operator. OPERATOR_A
external_user_id string Wajib External ID pemain. player-1001
currency string Wajib Disalin dari ledger transaksi awal. IDR
request_id UUID Wajib ID korelasi request yang unik. 1a4b...da31
timestamp string Wajib Timestamp RFC3339 untuk signature. 2026-06-12T01:02:00Z
transaction_id UUID Wajib ID rollback outbound dari backend. 7560...4900
reference_id string Wajib Idempotency key rollback. rollback-0001
original_reference_id string Wajib Reference debit atau credit awal. bet-round-0001
amount decimal Wajib Disalin dari ledger transaksi awal. 1000.00
metadata object Kondisional Dikirim hanya jika konteks internal ada. {"round_id":"round-1"}Notes: The success response must return matching rollback reference, original reference, amount, and currency.
Catatan: Respons sukses harus mengembalikan rollback reference, original reference, amount, dan currency yang sama.
{
"operator_code": "OPERATOR_A",
"external_user_id": "player-1001",
"currency": "IDR",
"request_id": "1a4b1805-cd06-47ec-9f2a-b78a8799da31",
"timestamp": "2026-06-12T01:02:00Z",
"transaction_id": "75604c6c-d4db-432e-9330-a09850324900",
"reference_id": "rollback-0001",
"original_reference_id": "bet-round-0001",
"amount": "1000.00"
}{
"status": true,
"code": "SUCCESS",
"data": {
"transaction_id": "operator-rollback-10001",
"reference_id": "rollback-0001",
"original_reference_id": "bet-round-0001",
"amount": "1000.00",
"balance_after": "100000.00",
"currency": "IDR"
}
}{
"status": false,
"code": "TRANSACTION_ALREADY_ROLLED_BACK",
"error": {}
}Callback: Transaction Status
Used by the reconciliation worker to resolve a pending seamless mutation after an unknown outcome.
Digunakan oleh worker rekonsiliasi untuk menyelesaikan mutasi seamless yang pending setelah hasil belum pasti.
Headers: Content-Type, X-Signature, X-Timestamp, X-Key-Version
Request fields
Field request
Field Type Requirement Description Example
operator_code string Required Canonical operator code. OPERATOR_A
external_user_id string Required Player external ID. player-1001
currency string Required Original transaction currency. IDR
request_id UUID Required Unique request correlation ID. 34ed...c71d
timestamp string Required RFC3339 signing timestamp. 2026-06-12T01:05:00Z
reference_id string Required Original mutation reference to resolve. bet-round-0001Field Tipe Kebutuhan Deskripsi Contoh
operator_code string Wajib Kode operator. OPERATOR_A
external_user_id string Wajib External ID pemain. player-1001
currency string Wajib Currency transaksi awal. IDR
request_id UUID Wajib ID korelasi request yang unik. 34ed...c71d
timestamp string Wajib Timestamp RFC3339 untuk signature. 2026-06-12T01:05:00Z
reference_id string Wajib Reference mutasi awal yang akan diperiksa. bet-round-0001Notes: transaction_status must be completed, failed, or not_found. Optional comparison fields, when returned, must match the original transaction.
Catatan: transaction_status harus completed, failed, atau not_found. Field pembanding opsional harus sama dengan transaksi awal jika dikembalikan.
{
"operator_code": "OPERATOR_A",
"external_user_id": "player-1001",
"currency": "IDR",
"request_id": "34ed7529-f847-4910-91b0-f19bf7c7c71d",
"timestamp": "2026-06-12T01:05:00Z",
"reference_id": "bet-round-0001"
}{
"status": true,
"code": "SUCCESS",
"data": {
"transaction_status": "completed",
"operator_transaction_id": "operator-debit-10001",
"transaction_type": "debit",
"amount": "1000.00",
"currency": "IDR",
"reference_id": "bet-round-0001"
}
}{
"status": false,
"code": "TRANSACTION_NOT_FOUND",
"error": {}
}Testing Seamless Wallet
Pengujian Seamless Wallet
- Configure a seamless operator callback URL and active credential secret.
- Start the operator wallet at 100000.00.
- Call the public debit API for 1000.00. The operator callback receives
/debit; expected balance is 99000.00. - Return a credit of 2500.00 from a game settlement; expected balance is 101500.00.
- Rollback the debit; expected balance is 102500.00.
- Simulate a debit timeout, then answer
/transaction-statuswith the actual result.
- Konfigurasikan callback URL operator seamless dan secret credential aktif.
- Mulai dengan saldo wallet operator 100000.00.
- Panggil API debit publik sebesar 1000.00. Callback operator menerima
/debit; saldo yang diharapkan 99000.00. - Kembalikan credit settlement game sebesar 2500.00; saldo yang diharapkan 101500.00.
- Rollback debit; saldo yang diharapkan 102500.00.
- Simulasikan timeout debit, lalu jawab
/transaction-statusdengan hasil sebenarnya.
BASE_URL="https://api.example.com"
TOKEN="replace-with-seamless-operator-token"
curl -sS -X POST "$BASE_URL/api/v1/wallet/debit" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"external_user_id":"player-1001","reference_id":"seamless-test-debit-1","amount":"1000.00","currency":"IDR"}'SECRET="replace-with-operator-secret"
TIMESTAMP="2026-06-12T01:00:00Z"
PATH_VALUE="/debit"
BODY='{"operator_code":"OPERATOR_A","external_user_id":"player-1001","currency":"IDR","request_id":"4d33e43a-85d9-4986-b96a-5c3a523d78a2","timestamp":"2026-06-12T01:00:00Z","transaction_id":"9d1af7a2-b8aa-4d54-a25b-f0f062c9e042","reference_id":"seamless-test-debit-1","amount":"1000.00"}'
printf 'POST\n%s\n%s\n%s' "$PATH_VALUE" "$TIMESTAMP" "$BODY" |
openssl dgst -sha256 -hmac "$SECRET" -hexKnown Error Codes
Kode Error yang Dikenal
The codes below are returned by the public wallet handlers or accepted from the seamless operator wallet service.
Kode berikut dikembalikan oleh handler wallet publik atau diterima dari layanan seamless wallet operator.
Code Meaning
SUCCESS Request completed successfully.
VALIDATION_ERROR Missing field, invalid JSON, wrong content type, or unknown field.
UNAUTHORIZED Bearer token is missing, invalid, expired, revoked, or operator is inactive.
FORBIDDEN Client IP or request operator identity is not allowed.
RATE_LIMITED Request rate limit was exceeded.
USER_NOT_FOUND Player was not found for the authenticated operator.
USER_INACTIVE Player status is not active.
INVALID_CURRENCY Currency is not exactly three uppercase ASCII letters.
CURRENCY_MISMATCH Request currency differs from player or upstream currency.
INVALID_AMOUNT Amount is zero, negative, or has more than two decimal places.
AMOUNT_LIMIT_EXCEEDED Amount is greater than 1000000000000.00.
BALANCE_OVERFLOW Balance mutation failed its safety checks.
INSUFFICIENT_BALANCE Wallet cannot cover the debit.
WALLET_TYPE_NOT_SUPPORTED Route cannot run for the authenticated wallet type.
IDEMPOTENCY_CONFLICT Reference was reused with different immutable fields.
TRANSACTION_NOT_FOUND Original transaction or requested transaction does not exist.
TRANSACTION_NOT_ROLLBACKABLE Original transaction is not completed or cannot be reversed.
TRANSACTION_ALREADY_ROLLED_BACK Original transaction was already reversed.
INVALID_TRANSACTION_TYPE Transaction list type filter is invalid.
INVALID_TRANSACTION_STATUS Transaction list status filter is invalid.
INVALID_PAGINATION limit or offset is outside the accepted range.
PROVIDER_UNAVAILABLE Seamless wallet provider is unavailable.
UPSTREAM_TIMEOUT Seamless balance or status request timed out.
TRANSACTION_STATUS_UNKNOWN Mutation result is uncertain and requires reconciliation.
UNSUPPORTED_OPERATION Wallet strategy does not support the requested operation.
INTERNAL_ERROR Unexpected internal or configuration failure.Code Arti
SUCCESS Request berhasil.
VALIDATION_ERROR Field kurang, JSON invalid, content type salah, atau field tidak dikenal.
UNAUTHORIZED Bearer token tidak ada/tidak valid, credential kedaluwarsa/dicabut, atau operator tidak aktif.
FORBIDDEN IP client atau identitas operator pada request tidak diizinkan.
RATE_LIMITED Batas jumlah request terlampaui.
USER_NOT_FOUND Pemain tidak ditemukan untuk operator terautentikasi.
USER_INACTIVE Status pemain tidak aktif.
INVALID_CURRENCY Currency bukan tiga huruf ASCII kapital.
CURRENCY_MISMATCH Currency request berbeda dari pemain atau upstream.
INVALID_AMOUNT Amount nol, negatif, atau lebih dari dua desimal.
AMOUNT_LIMIT_EXCEEDED Amount lebih besar dari 1000000000000.00.
BALANCE_OVERFLOW Mutasi saldo gagal pada pemeriksaan keamanan.
INSUFFICIENT_BALANCE Saldo tidak cukup untuk debit.
WALLET_TYPE_NOT_SUPPORTED Route tidak dapat dijalankan untuk tipe wallet operator.
IDEMPOTENCY_CONFLICT Reference digunakan ulang dengan field penting yang berbeda.
TRANSACTION_NOT_FOUND Transaksi awal atau transaksi yang diminta tidak ditemukan.
TRANSACTION_NOT_ROLLBACKABLE Transaksi awal belum completed atau tidak dapat dibalik.
TRANSACTION_ALREADY_ROLLED_BACK Transaksi awal sudah dibalik.
INVALID_TRANSACTION_TYPE Filter type pada daftar transaksi tidak valid.
INVALID_TRANSACTION_STATUS Filter status pada daftar transaksi tidak valid.
INVALID_PAGINATION limit atau offset di luar rentang.
PROVIDER_UNAVAILABLE Provider seamless wallet tidak tersedia.
UPSTREAM_TIMEOUT Request balance atau status seamless mengalami timeout.
TRANSACTION_STATUS_UNKNOWN Hasil mutasi belum pasti dan memerlukan rekonsiliasi.
UNSUPPORTED_OPERATION Strategi wallet tidak mendukung operasi.
INTERNAL_ERROR Kegagalan internal atau konfigurasi yang tidak terduga.Seamless upstream code mapping
Pemetaan kode upstream seamless
The operator wallet may also return DUPLICATE_TRANSACTION (mapped to IDEMPOTENCY_CONFLICT), OPERATOR_SUSPENDED (mapped to provider unavailable), and INVALID_SIGNATURE or INVALID_TIMESTAMP (mapped to INTERNAL_ERROR). A mutation response with INTERNAL_ERROR is treated as an unknown outcome.
Wallet operator juga dapat mengembalikan DUPLICATE_TRANSACTION (dipetakan ke IDEMPOTENCY_CONFLICT), OPERATOR_SUSPENDED (dipetakan ke provider unavailable), serta INVALID_SIGNATURE atau INVALID_TIMESTAMP (dipetakan ke INTERNAL_ERROR). Respons mutasi dengan INTERNAL_ERROR dianggap sebagai hasil belum pasti.