Skip to main content
POST
/
api
/
v2.0
/
direct-debit
/
bindings
Binding Card
curl --request POST \
  --url https://sandbox-payment-b2b.singapay.id/api/v2.0/direct-debit/bindings \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'X-PARTNER-ID: <api-key>' \
  --data '
{
  "customer_ref": "cust-9001",
  "phone_no": "+6281234567890",
  "bank_code": "008",
  "payment_otp_mode": "WITH_OTP",
  "success_redirect_url": "https://example.com/success",
  "failure_redirect_url": "https://example.com/failure"
}
'
{
  "response_code": "SP000",
  "response_message": "Binding initiated",
  "data": {
    "binding_id": "9a1c5b3e-2d4f-4d8c-93cf-9a1c5b3e2d4f",
    "status": "PENDING_AUTH",
    "customer_ref": "cust-9001",
    "bank_code": "008",
    "redirect_url": "https://hosted-webview.example.com/dd/bind?token=eyJhbGc...",
    "expires_at": "2026-06-04T07:40:00+07:00",
    "payment_otp_mode": "WITH_OTP"
  }
}

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.

Body

application/json

Initiates a Direct Debit binding flow. The merchant must redirect the customer to the returned redirect_url to complete bank authentication. bank_code is optional; when omitted the hosted webview renders a bank picker. payment_otp_mode is a preferred charge-time mode and the bank may still enforce its own OTP rules.

customer_ref
string
required

Merchant-side stable id for the customer (NOT the bank account number). Used to scope future bindings of the same customer.

Required string length: 4 - 15
Example:

"cust-9001"

phone_no
string
required

Customer mobile phone in E.164-ish form (e.g. +6281234567890). The bank may use this to deliver OTP.

Maximum string length: 20
Example:

"+6281234567890"

bank_code
string | null

3-digit BI/SNAP code of the target bank. Common values: 002 BRI, 008 Mandiri, 009 BNI, 011 Danamon, 014 BCA, 022 CIMB, 490 BNC.

Required string length: 3
Example:

"008"

payment_otp_mode
enum<string> | null

Preferred OTP behavior for later charge requests. The actual bank flow may still require OTP regardless of this hint.

Available options:
WITH_OTP,
WITHOUT_OTP
Example:

"WITH_OTP"

success_redirect_url
string<uri> | null

Where the hosted webview redirects after a successful authorization.

Maximum string length: 512
Example:

"https://example.com/success"

failure_redirect_url
string<uri> | null

Where the hosted webview redirects after a failed/cancelled authorization.

Maximum string length: 512
Example:

"https://example.com/failure"

Response

SP000 Binding initiated — data matches DirectDebitBindingInitiationData. The customer must open redirect_url to authenticate.

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.).