Accounting Operation — This webhook fires on settlement lifecycle events (completion, refund, refund cancellation). It reports money movements between your
pending_balance, available_balance, and your bank account.Information
| Method | Path | Format | Authentication |
|---|---|---|---|
| POST | https://your-webhook-url/callback | json | HMAC SHA512 Signature |
POST request to your configured settlement_notif_url whenever a settlement batch reaches a final state, or when a settled transaction is refunded / has its refund cancelled.
This webhook may share a callback URL with other event types. Always route by the
event value in the body. See Shared webhook endpoints.Events
This single webhook covers three settlement events, distinguished by theevent field:
event | Fired when | data contains |
|---|---|---|
settlement.completed | A settlement batch is completed — either a sequential settlement is approved by Finance, or a parallel (auto) settlement is created by the scheduler. | settlement, total_transactions |
settlement.refunded | A single settled transaction is refunded back from your balance (settlement method balance / auto-balance only). | settlement, refund |
settlement.refund_cancelled | A previous refund is cancelled and the balance is restored. | settlement, refund |
Settlement currently supports money-in transactions only (Virtual Account, QRIS, Payment Link, E-Wallet). Refund events apply only to settlements using the
balance or auto-balance method.Request Details
Headers
| Field | Value | Type | Mandatory | Description |
|---|---|---|---|---|
Content-Type | application/json | Alphabetic | Yes | Specifies JSON format for the request body |
User-Agent | SingaPaymentGateway/1.0 | Alphabetic | Yes | Identifies the source of the webhook |
Accept | application/json | Alphabetic | Yes | Expected response format |
X-PARTNER-ID | — | Alphanumeric | Yes | Your API Key from the merchant dashboard |
X-Signature | — | Alphanumeric | Yes | HMAC SHA512 signature (128 chars) for request verification |
X-Timestamp | — | Numeric | Yes | Unix timestamp in seconds when the request was sent |
Authorization | Bearer <random_token> | Alphanumeric | Yes | System-generated random bearer token; used as a component in the signature |
The
Authorization token for settlement webhooks is a randomly generated string — not a user access token. Settlement events are triggered by an admin approval, a scheduler, or a refund action (system events), not a user request. Extract the token as-is and use it in the string to sign. See How to Validate Signature below.Body Parameters — common envelope
Every settlement webhook shares the same top-level envelope:HTTP Status Code. Always
200.Indicates a successful event. Always
true.Event type identifier. One of
"settlement.completed", "settlement.refunded", "settlement.refund_cancelled".Event timestamp in format
"d M Y H:i:s". Example: "18 Jun 2026 10:00:00"Container for the settlement details (and, for refund events, the refund details).
data.settlement (present on all events)
The settlement batch the event relates to.
data.total_transactions (settlement.completed only)
Number of transactions included in the completed settlement batch. Example:
5data.refund (settlement.refunded & settlement.refund_cancelled only)
Details of the individual transaction that was refunded or had its refund cancelled.
Payload Examples
settlement.completed
settlement.completed (bank-account)
settlement.refunded
settlement.refund_cancelled
Security and responses
Return HTTP200 promptly after validating the request. For retry behavior, see Webhook retry mechanism.
Verify every webhook using Security and signature validation. Use your configured settlement_notif_url path when building StringToSign.
Handle duplicate deliveries idempotently using stable identifiers from the payload — for settlement.completed use data.settlement.reference_no; for refund events combine data.settlement.reference_no with data.refund.settlement_detail_id (and the event).
Settlement Specific Notes
One callback URL, three events
One callback URL, three events
All three events are delivered to the same
settlement_notif_url. Always branch on the event field. A settlement.completed payload has total_transactions; refund events have a refund object instead.Sequential vs auto settlement
Sequential vs auto settlement
is_auto_created = false means a sequential settlement approved by Finance (approved_by is the approver’s name). is_auto_created = true means a parallel auto settlement created by the scheduler (approved_by = "SYSTEM"). Both arrive as settlement.completed.amount vs total_to_transfer
amount vs total_to_transfer
amount is the total net amount of the settled transactions. total_to_transfer is what was actually moved out — amount - settlement_fee. The settlement_fee is only non-zero for the bank-account method.Refunds only for balance methods
Refunds only for balance methods
settlement.refunded and settlement.refund_cancelled fire only for settlements using the balance or auto-balance method. Refund deducts (and cancel restores) the transaction’s net amount from your available_balance — fees are not refunded.Refund state via flags
Refund state via flags
Track refund state with
is_refunded and is_refund_cancelled. An active refund is is_refunded=true, is_refund_cancelled=false. A cancelled refund is is_refunded=true, is_refund_cancelled=true — note is_refunded stays true.Nullable fields
Nullable fields
transfer_status and the recipient.* fields are null for balance / auto-balance settlements. Actor fields (refunded_by, refund_cancelled_by, actor) and account_id may be null. Handle null gracefully.Timestamp format & timezone
Timestamp format & timezone
All timestamps (
timestamp, approved_at, start_date, end_date, refunded_at, refund_cancelled_at) use the format "d M Y H:i:s" (e.g. "18 Jun 2026 10:00:00") in Asia/Jakarta (WIB) timezone — not UTC.