> ## Documentation Index
> Fetch the complete documentation index at: https://docs.singapay.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment (One-Time)

> Charges a card for a one-time payment (full or installment).



## OpenAPI

````yaml https://payment-b2b.singapay.id/api/docs/merchant-api.json post /api/v2.0/card/{account_id}/payment
openapi: 3.1.0
info:
  title: Singa Merchant API
  description: >-
    OpenAPI specification for the merchant/partner HTTP API. All routes below
    are additionally protected by `ip.whitelisted.merchant` — the caller IP must
    be registered for the credential or merchant. Obtain a JWT using `POST
    /api/v1.0/access-token/b2b` (Basic auth) or `POST
    /api/v1.1/access-token/b2b` (X-Signature) before calling secured endpoints.
  version: 1.0.0
servers:
  - url: https://sandbox-payment-b2b.singapay.id
    description: >-
      API host. Paths include `/api` prefix (see `RouteServiceProvider`).
      Replace scheme/host with your environment.
security: []
tags:
  - name: Security
    description: >-
      Merchant authentication (`OauthMerchantTokenController`). **v1.1** B2B
      token uses `X-CLIENT-ID`, `X-PARTNER-ID`, and `X-Signature` (no Basic
      auth). Secured routes also require the issued Bearer JWT plus
      `X-PARTNER-ID`.
  - name: Accounts
    description: >-
      Account management (`routes/merchantApiRoute.php`, `v1.0`). Path parameter
      `{id}` is always the account ULID.
  - name: Balance Inquiry
    description: >-
      Merchant and per-account balance inquiry (`BalanceController`, `v1.0`).
      Path `account_id` is the account ULID.
  - name: Statements
    description: >-
      Per-account statement list and detail
      (`AccountController::accountStatements`, `accountStatementDetail`, prefix
      `v1.0/statements`). Flugger responses; detail path param `{statement_id}`
      maps to `statements.transaction_id`.
  - name: Payment Link
    description: >-
      Payment link CRUD and payment-method catalog (`PaymentLinkApiController`,
      prefix `v1.0/payment-link-manage`). `account_id` is ULID;
      `payment_link_id` is numeric `payment_links.id`.
  - name: Payment Link History
    description: >-
      Payment link transaction/history listing and detail
      (`PaymentLinkApiController`, prefix `v1.0/payment-link-histories`).
      `history_id` is numeric `payment_link_histories.id`.
  - name: Virtual Account
    description: >-
      Native VA CRUD (`VirtualAccountController`, prefix
      `v1.0/virtual-accounts`). `account_id` and `virtual_account_id` are ULIDs.
  - name: VA Transaction
    description: >-
      VA money-in transaction listing and detail (`VirtualAccountController`,
      prefix `v1.0/va-transactions`).
  - name: QRIS (Money In)
    description: >-
      MPM dynamic QRIS list, show, and generate (`QrisMpmDynamicApiController`,
      prefix `v1.0/qris-dynamic`).
  - name: QRIS (Money Out)
    description: >-
      Issuer MPM decode/inquiry, payment credit (money out), and transaction
      status (`QrisIssuerMpmController`, `QrisApiV2Controller::checkStatus`,
      prefix `v2.0/qris`). Related list/detail: `GET
      /api/v2.0/qris/transaction/...`.
  - name: E-Wallet (Money In)
    description: >-
      E-Wallet Native checkout and transactions (`EwalletNativeApiController`,
      `EwalletNativeTransactionApiController`, `EwalletNativeV2ApiController`).
      Paths include `v1.0/ewallet-native`, `v1.0/ewallet-native-transactions`,
      and `v2.0/ewallet-native`.
  - name: E-Wallet (Money Out)
    description: >-
      E-wallet disbursement / top-up to beneficiary wallets
      (`EWalletTopUpController`, prefix `v2.0/ewallet`). Responses use the
      custom **`MerchantV2ApiEnvelope`** with **`MerchantV2ResponseCode`**
      (SP000–SP020).
  - name: Card (Money In)
    description: >-
      One-time card payment, cancel, and inquiry
      (`CardPaymentMerchantApiController`, prefix `v2.0/card`).
  - name: Subscription (Recurring)
    description: >-
      Credit-card recurring subscription plans (`SubscriptionPlanApiController`,
      prefix `v2.0/recurring`). Plan `{id}` is UUID (`sub_plans.id`).
  - name: Direct Debit
    description: >-
      Direct Debit — bind a customer bank account once via hosted webview, then
      charge it host-to-host (`DirectDebitMerchantController`, prefix
      `v2.0/direct-debit`). Binding `{binding_id}` and transaction
      `{transaction_id}` are UUIDs. Responses use the
      **`MerchantV2ApiEnvelope`** with both standard SP000–SP020 codes and
      Direct-Debit-specific codes (`SP_DD_*`). The `/charge` endpoint is
      additionally protected by **`X-Signature`** + **`X-Timestamp`**
      (`verify.signature-internal`); see operation parameters for the signing
      scheme.
  - name: Account Transfer
    description: >-
      Move funds between sub-accounts within the same merchant
      (`AnotherAccountApiController`, prefix `v1.0/account-transfer`). The
      transfer endpoint requires request signature headers
      (`verify.signature-internal`). Both accounts must belong to the
      authenticated merchant and be accessible to the credential.
  - name: Disbursement (Money Out)
    description: >-
      Bank disbursement (`DisbursementController` **v1.0**,
      `DisbursementV2Controller` **v2.0**). **v1.0**
      list/show/fee/beneficiary/transfer use Flugg envelopes; v1 inquiry-status
      uses the **custom v2 envelope** (`MerchantV2ApiEnvelope`, codes
      **SP000–SP020**). **v2.0** check-beneficiary, transfer, and inquiry-status
      use the same custom envelope — see component schema
      **`MerchantV2ResponseCode`** for the full response code table.
  - name: Cardless Withdrawal
    description: >-
      Cardless withdrawal API for initiating ATM cash withdrawals without a
      physical card. Supports creating withdrawals with OTP generation, listing
      transaction history, viewing transaction details, canceling pending
      withdrawals, and deleting canceled records. All endpoints use the
      `v1.0/cardless-withdrawals` route prefix and the standard success/error
      response envelope. Path parameter `{id}` refers to the `transaction_id`
      (platform-assigned business identifier).
paths:
  /api/v2.0/card/{account_id}/payment:
    post:
      tags:
        - Card (Money In)
      summary: Payment (One-Time)
      description: Charges a card for a one-time payment (full or installment).
      operationId: cardMerchantPayment
      parameters:
        - name: account_id
          in: path
          required: true
          schema:
            description: Account ULID
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCardOneTimePaymentRequest'
      responses:
        '200':
          description: >-
            **SP000** Successfully — payment accepted (may require 3-D Secure;
            check `data.action`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardPaymentSuccessResponse'
        '400':
          description: >-
            **SP012** Bad Request / validation (`data.errors`), or **SP001**
            Transaction Failure (provider declined).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/CardErrorBadRequestResponse'
                  - $ref: '#/components/schemas/CardErrorTransactionFailureResponse'
        '403':
          description: Access denied to this account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardErrorAccessDeniedResponse'
        '404':
          description: '**SP020** Merchant Account Not Found.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardErrorAccountNotFoundResponse'
        '500':
          description: '**SP002** General Failure — unexpected error.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardErrorGeneralFailureResponse'
      security:
        - BearerAuth: []
          PartnerId: []
components:
  schemas:
    CreateCardOneTimePaymentRequest:
      description: >-
        Request payload for a one-time card payment (full or installment).
        Customer billing details and card credentials are mandatory; installment
        fields are optional.
      required:
        - amount
        - goods_name
        - customer_name
        - customer_email
        - customer_phone
        - customer_address
        - customer_city
        - customer_state
        - customer_postal_code
        - customer_country
        - card_number
        - card_expiry
        - card_cvv
        - card_holder_name
        - card_holder_email
      properties:
        amount:
          description: >-
            Charge amount in IDR (whole number). Must be within the limits
            defined by
            `config(default_money_in_out.min_card_amount|max_card_amount)`.
          type: number
          example: 150000
        reference_no:
          description: Merchant reference for the transaction. Auto-generated when omitted.
          type:
            - string
            - 'null'
          maxLength: 100
          example: INV-2024-0012
        goods_name:
          description: Name or description of the goods/service being purchased.
          type: string
          maxLength: 255
          example: Premium Subscription
        customer_name:
          description: Full name of the paying customer.
          type: string
          maxLength: 255
          example: John Doe
        customer_email:
          description: Customer email address.
          type: string
          format: email
          maxLength: 255
          example: john.doe@example.com
        customer_phone:
          description: Customer contact phone number.
          type: string
          maxLength: 50
          example: '081234567890'
        customer_address:
          description: Customer billing street address.
          type: string
          maxLength: 500
          example: Jl. Jenderal Sudirman No. 1
        customer_city:
          description: Customer billing city.
          type: string
          maxLength: 100
          example: Jakarta
        customer_state:
          description: Customer billing state or province.
          type: string
          maxLength: 100
          example: DKI Jakarta
        customer_postal_code:
          description: Customer billing postal code.
          type: string
          maxLength: 20
          example: '10220'
        customer_country:
          description: Customer country as a 2-letter ISO 3166-1 alpha-2 code.
          type: string
          maxLength: 2
          minLength: 2
          example: ID
        description:
          description: Optional free-text note for the transaction.
          type:
            - string
            - 'null'
          maxLength: 500
          example: Monthly premium plan payment
        card_number:
          description: >-
            Card primary account number (PAN). Spaces are stripped before
            processing.
          type: string
          maxLength: 20
          example: '4000000000000002'
        card_expiry:
          description: Card expiry in `MMYY` format.
          type: string
          maxLength: 4
          minLength: 4
          example: '0828'
        card_cvv:
          description: Card verification value (CVV/CVC) printed on the card.
          type: string
          maxLength: 4
          example: '123'
        card_holder_name:
          description: Cardholder name as printed on the card.
          type: string
          maxLength: 45
          example: JOHN DOE
        card_holder_email:
          description: Cardholder email address.
          type: string
          format: email
          maxLength: 100
          example: john.doe@example.com
        installment:
          description: >-
            Set to `true` to pay by installment. Defaults to `false` (full
            payment).
          type:
            - boolean
            - 'null'
          example: false
        installment_month:
          description: >-
            Installment tenor in months. Required only when `installment` is
            `true`.
          type:
            - string
            - 'null'
          enum:
            - '3'
            - '6'
            - '12'
          example: '3'
      type: object
    CardPaymentSuccessResponse:
      description: >-
        Merchant v2 envelope returned on a successful one-time payment request
        (`SP000`, HTTP 200).
      required:
        - response_code
        - response_message
        - data
      properties:
        response_code:
          $ref: '#/components/schemas/MerchantV2ResponseCode'
        response_message:
          $ref: '#/components/schemas/MerchantV2ResponseMessage'
        data:
          $ref: '#/components/schemas/CardPaymentData'
      type: object
      example:
        response_code: SP000
        response_message: Successfully
        data:
          transaction_id: '101222025010112000099887766'
          reference_no: INV-2024-0012
          status: processing
          provider_transaction_id: TXN202501011200001234
          provider_auth_no: '123456'
          card_masked: 400000******0002
          issuing_bank: BCA
          acquiring_bank: BRI
          result_code: '0000'
          action: redirect
          requires_3ds: true
          payment_url: https://secure-3ds.example.com/auth/...
    CardErrorBadRequestResponse:
      description: >-
        Merchant v2 envelope for validation or bad-request failures (`SP012`,
        HTTP 400). Validation failures include `data.errors` keyed by field
        name.
      required:
        - response_code
        - response_message
      properties:
        response_code:
          description: Business response code.
          type: string
          example: SP012
        response_message:
          description: Human-readable message.
          type: string
          example: Bad Request
        data:
          description: Validation context. Present on input validation failures.
          properties:
            errors:
              description: Field-level validation messages.
              type: object
              example:
                amount:
                  - The amount must be at least 10000.
              additionalProperties: true
          type:
            - object
            - 'null'
      type: object
      example:
        response_code: SP012
        response_message: The amount field is required.
        data:
          errors:
            amount:
              - The amount field is required.
    CardErrorTransactionFailureResponse:
      description: >-
        Merchant v2 envelope when the provider declines or the transaction
        cannot be processed (`SP001`, HTTP 400). `data.status` reflects the
        resulting transaction state.
      required:
        - response_code
        - response_message
      properties:
        response_code:
          description: Business response code.
          type: string
          example: SP001
        response_message:
          description: Provider error message.
          type: string
          example: Transaction Failure
        data:
          properties:
            transaction_id:
              type: string
              example: '101222025010112000099887766'
            reference_no:
              type: string
              example: INV-2024-0012
            status:
              type: string
              example: failed
          type:
            - object
            - 'null'
      type: object
      example:
        response_code: SP001
        response_message: Card declined by issuer
        data:
          transaction_id: '101222025010112000099887766'
          reference_no: INV-2024-0012
          status: failed
    CardErrorAccessDeniedResponse:
      description: >-
        Merchant v2 envelope when the authenticated merchant is not allowed to
        access this account (HTTP 403). Returned by the controller with a
        numeric `403` response code.
      required:
        - response_code
        - response_message
      properties:
        response_code:
          description: HTTP-aligned access-denied code.
          type: integer
          example: 403
        response_message:
          description: Human-readable message.
          type: string
          example: Access denied to this account.
        data:
          type:
            - object
            - 'null'
          example: null
      type: object
      example:
        response_code: 403
        response_message: Access denied to this account.
        data: null
    CardErrorAccountNotFoundResponse:
      description: >-
        Merchant v2 envelope when the `{account_id}` does not belong to the
        authenticated merchant (`SP020`, HTTP 404).
      required:
        - response_code
        - response_message
      properties:
        response_code:
          description: Business response code.
          type: string
          example: SP020
        response_message:
          description: Human-readable message.
          type: string
          example: Merchant Account Not Found
        data:
          type:
            - object
            - 'null'
          example: null
      type: object
      example:
        response_code: SP020
        response_message: Merchant Account Not Found
        data: null
    CardErrorGeneralFailureResponse:
      description: >-
        Merchant v2 envelope for unexpected server-side failures (`SP002`, HTTP
        500).
      required:
        - response_code
        - response_message
      properties:
        response_code:
          description: Business response code.
          type: string
          example: SP002
        response_message:
          description: Human-readable message.
          type: string
          example: An unexpected error occurred
        data:
          type:
            - object
            - 'null'
          example: null
      type: object
      example:
        response_code: SP002
        response_message: An unexpected error occurred
        data: null
    MerchantV2ResponseCode:
      description: SingaPay custom business response code.
      type: string
      example: SP000
    MerchantV2ResponseMessage:
      description: Human-readable label paired with `response_code`.
      type: string
      example: Successfully
    CardPaymentData:
      description: >-
        Payload returned on a one-time payment request
        (`CardPaymentMerchantApiService::mapPaymentResponseToV2`). When the card
        requires 3-D Secure, `action` is `redirect` and the merchant must
        forward the customer to `payment_url`; otherwise `action` is `complete`.
      properties:
        transaction_id:
          description: SingaPay card transaction identifier.
          type: string
          example: '101222025010112000099887766'
        reference_no:
          description: Merchant reference for the transaction.
          type: string
          example: INV-2024-0012
        status:
          description: Customer-facing transaction status.
          type: string
          enum:
            - pending
            - processing
            - success
            - failed
          example: processing
        provider_transaction_id:
          description: Payment provider transaction identifier (TXID).
          type:
            - string
            - 'null'
          example: TXN202501011200001234
        provider_auth_no:
          description: Authorization number returned by the issuer.
          type:
            - string
            - 'null'
          example: '123456'
        card_masked:
          description: Masked card number (PAN).
          type:
            - string
            - 'null'
          example: 400000******0002
        issuing_bank:
          description: Issuing bank name.
          type:
            - string
            - 'null'
          example: BCA
        acquiring_bank:
          description: Acquiring bank name.
          type:
            - string
            - 'null'
          example: BRI
        result_code:
          description: Raw provider result code (`0000` indicates success).
          type:
            - string
            - 'null'
          example: '0000'
        action:
          description: >-
            Next step for the merchant: `redirect` (3-D Secure required) or
            `complete`.
          type: string
          enum:
            - redirect
            - complete
          example: redirect
        requires_3ds:
          description: Present and `true` when 3-D Secure authentication is required.
          type:
            - boolean
            - 'null'
          example: true
        payment_url:
          description: >-
            3-D Secure redirect URL / HTML form. Present only when `action` is
            `redirect`.
          type:
            - string
            - 'null'
          example: https://secure-3ds.example.com/auth/...
        html_form:
          description: Raw 3-D Secure HTML form. Present only when `action` is `redirect`.
          type:
            - string
            - 'null'
          example: >-
            <form action="https://secure-3ds.example.com/auth"
            method="POST">...</form>
        immediate_success:
          description: >-
            Present when `action` is `complete`; `true` when the payment was
            authorized without 3-D Secure.
          type:
            - boolean
            - 'null'
          example: false
      type: object
  securitySchemes:
    BearerAuth:
      type: http
      description: >-
        JWT issued by `POST /api/v1.1/access-token/b2b`. Send `Authorization:
        Bearer <token>`.
      bearerFormat: JWT
      scheme: bearer
    PartnerId:
      type: apiKey
      description: Merchant API key (`Credential.api_key`). Required on every request.
      name: X-PARTNER-ID
      in: header

````