Verify OTP
Completes OTP verification for either payment or unbinding flows. Use transaction_id for payment OTP (after POST /charge returns requires_otp=true), or binding_id + unbind_context for unbind OTP (after POST /bindings/{id}/unbind returns otp_handoff). Submitting both or neither returns 422 SP018.
Authorizations
JWT issued by POST /api/v1.1/access-token/b2b. Send Authorization: Bearer <token>.
Merchant API key (Credential.api_key). Required on every request.
Body
Submits an OTP to complete either a payment authorization or an unbind operation. Use transaction_id for payment-OTP flows, or binding_id + unbind_context for unbind-OTP flows. Exactly one of these flow definitions must be present.
OTP value the customer received from their bank.
4 - 8"123456"
Required for the payment-OTP flow; the id returned by POST /charge when requires_otp=true.
"01HZX9JK4M5N6P7Q8R9STUVWXY"
Required for the unbinding-OTP flow; together with unbind_context from the original /unbind response.
"01HZX9JK4M5N6P7Q8R9STUVWXY"
Verbatim otp_handoff block returned by POST /bindings/{binding_id}/unbind (when otp_required=true). Required for the unbinding-OTP flow.
Response
SP000 OTP accepted. For the payment flow, data matches DirectDebitTransactionData and status moves PENDING_OTP → PENDING (final SUCCESS arrives via webhook). For the unbinding flow, data matches DirectDebitBindingData; the binding stays ACTIVE until the direct-debit.unbinding.succeeded callback flips it to UNBOUND.
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.
SingaPay custom business response code.
"SP000"
Human-readable label paired with response_code.
"Successfully"
Endpoint-specific payload on success, or error context (validation message, inquiry result with status invalid, etc.).
