# 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 <device-token>`
- `Idempotency-Key: <uuid>`

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`
