# API Contract Draft - QRIS Soundbox Platform v1 ## 1. Prinsip API - gunakan HTTPS - semua endpoint device memakai auth khusus device - semua endpoint admin/merchant memakai RBAC - endpoint create yang sensitif wajib support idempotency key - response harus punya request_id / trace_id ## 2. Admin / Merchant APIs ### Merchant - `POST /admin/merchants` - `GET /admin/merchants` - `GET /admin/merchants/{merchantId}` - `PATCH /admin/merchants/{merchantId}` - `POST /admin/merchants/{merchantId}/approve` - `POST /admin/merchants/{merchantId}/reject` #### Create Merchant - `POST /admin/merchants` Request body: ```json { "legal_name": "Toko Indo", "brand_name": "Toko Indo", "settlement_account_reference": "bank:9876543210", "settlement_account_type": "merchant_bank_account", "payout_mode": "merchant_direct", "fee_profile_id": "fee_basic" } ``` `payout_mode`: - `merchant_direct` (default): payout mengikuti rekening/referensi milik merchant. - `manual`: payout dilakukan manual/offline oleh tim operasi. Response: ```json { "data": { "id": "m_123", "merchant_code": "m_123abc", "legal_name": "Toko Indo", "brand_name": "Toko Indo", "settlement_account_reference": "bank:9876543210", "settlement_account_type": "merchant_bank_account", "payout_mode": "merchant_direct" }, "request_id": "req_001", "timestamp": "2026-05-24T00:00:00Z" } ``` Catatan penting: - Pada fase awal, settlement tidak ditarik ke rekening perusahaan. - Pencairan merchant dilakukan via `payout_account_reference` milik merchant. - Untuk merchant yang belum punya integrasi payout otomatis, gunakan `payout_mode: manual`. ### Outlet - `POST /admin/merchants/{merchantId}/outlets` - `GET /admin/outlets` - `GET /admin/outlets/{outletId}` - `PATCH /admin/outlets/{outletId}` ### Terminal - `POST /admin/outlets/{outletId}/terminals` - `GET /admin/terminals` - `GET /admin/terminals/{terminalId}` - `PATCH /admin/terminals/{terminalId}` ### Device / TMS - `POST /admin/devices` - `GET /admin/devices` - `GET /admin/devices/{deviceId}` - `PATCH /admin/devices/{deviceId}` - `POST /admin/devices/{deviceId}/bind` - `POST /admin/devices/{deviceId}/unbind` - `POST /admin/devices/{deviceId}/commands` - `GET /admin/devices/{deviceId}/commands` - `GET /admin/devices/{deviceId}/commands/{commandId}` - `GET /admin/devices/{deviceId}/heartbeats` - `GET /admin/devices/{deviceId}/notifications` - `POST /admin/seed` ### Transactions - `GET /admin/transactions` - `GET /admin/transactions/{transactionId}` - `POST /admin/transactions/{transactionId}/retry-notification` ### Settlements - `GET /admin/settlements` - `GET /admin/settlements/{settlementId}` - `POST /admin/settlements/run` - `POST /admin/settlements/{settlementId}/retry-payout` - Catatan: endpoint ini dipakai untuk batch/reconciliation status; eksekusi payout dilakukan sesuai konfigurasi `payout_mode` merchant. ## 3. Device APIs ### Provisioning - `POST /device/provision/activate` - `POST /device/provision/refresh-credential` ### Heartbeat - `POST /device/heartbeat` Sample request: ```json { "device_id": "sbx_001", "timestamp": "2026-05-23T10:00:00Z", "firmware_version": "1.0.3", "network_strength": 78, "battery_level": 92, "state": "idle" } ``` ### Config - `GET /device/config` - `POST /device/config/ack` - `POST /device/commands/ack` ### Device command payload ack Device mengirim: ```json { "device_id": "sbx_001", "command_id": "cmd_123", "status": "delivered", "reason": "ok", "result_payload": { "payment_result": "ok" } } ``` `status` untuk ACK: `delivered` | `failed` | `timeout`. ### Dynamic QR create - `POST /device/transactions/dynamic-qr` Headers: - `Authorization: Bearer ` - `Idempotency-Key: ` Request: ```json { "device_id": "sbx_001", "terminal_id": "term_001", "amount": 50000, "currency": "IDR", "request_id": "req_123" } ``` Response: ```json { "request_id": "req_123", "transaction_id": "tx_123", "qr_type": "dynamic", "qr_payload": "000201010212...", "expires_at": "2026-05-23T10:05:00Z", "status": "awaiting_payment" } ``` ## 4. Merchant Portal APIs - `GET /merchant/me` - `GET /merchant/dashboard/summary` - `GET /merchant/transactions` - `GET /merchant/transactions/{transactionId}` - `GET /merchant/settlements` - `GET /merchant/settlements/{settlementId}` - `GET /merchant/devices` - `GET /merchant/outlets` ## 5. Webhook Receiver - `POST /integrations/qris/callback` - `POST /integrations/bank/payout-callback` ## 6. Catatan Error Model Gunakan error code yang konsisten, misalnya: - `DEVICE_UNAUTHORIZED` - `DEVICE_NOT_BOUND` - `DEVICE_CAPABILITY_NOT_SUPPORTED` - `INVALID_AMOUNT` - `DUPLICATE_REQUEST` - `PARTNER_TIMEOUT` - `TRANSACTION_NOT_FOUND` - `SETTLEMENT_NOT_ELIGIBLE` - `MERCHANT_PAYOUT_NOT_CONFIGURED`