Skip to main content
POST
/
api
/
v2.0
/
direct-debit
/
charge
Charge
curl --request POST \
  --url https://sandbox-payment-b2b.singapay.id/api/v2.0/direct-debit/charge \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'X-PARTNER-ID: <api-key>' \
  --header 'X-Signature: <x-signature>' \
  --header 'X-Timestamp: <x-timestamp>' \
  --data '
{
  "account_id": "01HZX9JK4M5N6P7Q8R9STUVWXY",
  "binding_id": "01HZX9JK4M5N6P7Q8R9STUVWXY",
  "merchant_reference": "ref-123456",
  "amount": 10000,
  "currency": "IDR",
  "description": "Description of the charge"
}
'
{
  "response_code": "SP000",
  "response_message": "Charge accepted",
  "data": {
    "transaction_id": "7c2e1a4b-9d6f-4e3a-8b1c-2d4f9a1c5b3e",
    "binding_id": "9a1c5b3e-2d4f-4d8c-93cf-9a1c5b3e2d4f",
    "account_id": "01HZX9JK4M5N6P7Q8R9STUVWXY",
    "merchant_reference": "INV-2026-0001",
    "amount": 150000,
    "currency": "IDR",
    "description": "Subscription June 2026",
    "status": "PENDING",
    "requires_otp": false,
    "paid_at": null,
    "failure_code": null,
    "failure_reason": null,
    "web_redirect_url": null,
    "created_at": "2026-06-04T08:30:01+07:00",
    "updated_at": "2026-06-04T08:30:01+07:00"
  }
}

Authorizations

Authorization
string
header
required

JWT issued by POST /api/v1.1/access-token/b2b. Send Authorization: Bearer <token>.

X-PARTNER-ID
string
header
required

Merchant API key (Credential.api_key). Required on every request.

Headers

X-Signature
string
required

HMAC-SHA512 hex signature, computed as HMAC_SHA512(clientSecret, "{HTTP_METHOD}:{REQUEST_URI}:{ACCESS_TOKEN}:{SHA256_HEX(MINIFIED_BODY)}:{X_TIMESTAMP}"). MINIFIED_BODY is the request body with object keys recursively sorted alphabetically and re-serialised with no whitespace (an empty/missing body hashes the empty string). ACCESS_TOKEN is the bearer token without the Bearer prefix. Signature mismatch returns 401 with response_code=4019900.

X-Timestamp
string<date-time>
required

ISO-8601 timestamp of the request; used as part of the signed string and rejected by the gateway if more than ±5 minutes off the server clock.

Body

application/json

Pulls funds from an active binding into the merchant settlement account identified by account_id. The binding must be ACTIVE. merchant_reference is an idempotency key; replaying the same value returns 409 SP_DD_DUPLICATE_REFERENCE with the original transaction_id in data.

account_id
string
required

ULID of the merchant settlement account that should receive the funds. Must be owned by the authenticated merchant; access policy on the account is also enforced.

Example:

"01HZX9JK4M5N6P7Q8R9STUVWXY"

binding_id
string<uuid>
required

UUID of an ACTIVE DirectDebitBinding owned by the merchant.

Example:

"01HZX9JK4M5N6P7Q8R9STUVWXY"

merchant_reference
string
required

Merchant-side unique idempotency key for this charge.

Maximum string length: 100
Example:

"ref-123456"

amount
number
required

Amount to debit, in the unit of currency. Minimum 1 IDR.

Required range: x >= 1
Example:

10000

currency
string | null

ISO-4217. Defaults to IDR (the only value supported by Direct Debit).

Required string length: 3
Example:

"IDR"

description
string | null

Customer-facing description for this charge. This value is stored with the transaction and may appear in reports.

Maximum string length: 512
Example:

"Description of the charge"

Response

SP000 Charge accepted. data matches DirectDebitTransactionData; status=PENDING (await settlement webhook) or status=FAILED if the upstream rejected immediately. fees are present only on a later SUCCESS.

SingaPay Merchant API v2 custom response envelope (ApiResponderHelper::responseJson, ApiResponseTrait). Business outcome is determined by response_code (SP000–SP020), not by HTTP status alone. On success (SP000), data holds the operation payload. On errors, data often includes a message and may echo request fields.

response_code
string
required

SingaPay custom business response code.

Example:

"SP000"

response_message
string
required

Human-readable label paired with response_code.

Example:

"Successfully"

data
object | null

Endpoint-specific payload on success, or error context (validation message, inquiry result with status invalid, etc.).