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

# Access Token v1.1

> Exchanges merchant credentials for a JWT access token using the OAuth 2.0 client credentials grant. Authenticates with an HMAC-SHA512 signature (`X-Signature`) instead of a client secret. Use the returned `access_token` as the `Authorization: Bearer <token>` header on subsequent secured requests.



## OpenAPI

````yaml https://payment-b2b.singapay.id/api/docs/merchant-api.json post /api/v1.1/access-token/b2b
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/v1.1/access-token/b2b:
    post:
      tags:
        - Security
      summary: Access Token v1.1
      description: >-
        Exchanges merchant credentials for a JWT access token using the OAuth
        2.0 client credentials grant. Authenticates with an HMAC-SHA512
        signature (`X-Signature`) instead of a client secret. Use the returned
        `access_token` as the `Authorization: Bearer <token>` header on
        subsequent secured requests.
      operationId: accessTokenB2bV11
      parameters:
        - name: X-PARTNER-ID
          in: header
          description: >-
            Merchant API key that identifies the partner. Used together with
            `X-CLIENT-ID` to resolve the merchant credentials.
          required: true
          schema:
            type: string
            example: a1b2c3d4-5678-90ab-cdef-1234567890ab
        - name: X-CLIENT-ID
          in: header
          description: >-
            Merchant client identifier (`client_id`) issued to the merchant
            during onboarding.
          required: true
          schema:
            type: string
            example: SGP-CLIENT-001
        - name: X-Signature
          in: header
          description: >-
            Lowercase hexadecimal HMAC-SHA512 digest of
            `{client_id}_{client_secret}_{YYYYMMDD}` signed with the merchant
            `client_secret`. Valid only for the current server date (`Ymd`).
          required: true
          schema:
            type: string
            example: >-
              c8f1d3e2a4b6...0f9e8d7c6b5a4938271605f4e3d2c1b0a9f8e7d6c5b4a3928170f6e5d4c3b2a1
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OAuthClientCredentialsBody'
      responses:
        '200':
          description: >-
            Authentication succeeded. The response `data` contains the issued
            JWT and its metadata (`OAuthAccessTokenResponseData`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecuritySuccessResponse200'
        '401':
          description: >-
            Authentication failed — invalid credentials, invalid signature, or
            the merchant could not be resolved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecurityErrorResponse401'
        '403':
          description: >-
            Forbidden — the request originates from an IP address that is not
            whitelisted for the merchant, or the `X-PARTNER-ID` is not
            permitted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecurityErrorResponse403'
        '422':
          description: >-
            Unprocessable Entity — a required header is missing or the
            `grant_type` field is absent or not equal to `client_credentials`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SecurityErrorResponse422'
      security:
        - PartnerId: []
components:
  schemas:
    OAuthClientCredentialsBody:
      description: >-
        Request body for the OAuth 2.0 client credentials grant. The only
        supported value for `grant_type` is `client_credentials`; any other
        value is rejected with HTTP 422.
      required:
        - grant_type
      properties:
        grant_type:
          description: >-
            The OAuth grant type. Must be the literal string
            `client_credentials`.
          type: string
          enum:
            - client_credentials
          example: client_credentials
      type: object
    SecuritySuccessResponse200:
      description: >-
        Standard success envelope returned by the security endpoints. Wraps the
        issued token payload in the Flugger responder format (`status`,
        `success`, `data`).
      properties:
        status:
          description: HTTP status code of the response.
          type: integer
          example: 200
        success:
          description: >-
            Indicates whether the request was processed successfully. Always
            `true` for a 200 response.
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/OAuthAccessTokenResponseData'
          description: The access token payload.
      type: object
    SecurityErrorResponse401:
      description: >-
        Error envelope returned when authentication fails (HTTP 401). Typical
        causes: the credentials resolved from `X-PARTNER-ID` + `X-CLIENT-ID` do
        not exist, the `X-Signature` does not match, or the merchant linked to
        the credentials could not be found.
      properties:
        status:
          description: HTTP status code of the response.
          type: integer
          example: 401
        success:
          description: >-
            Indicates whether the request was processed successfully. Always
            `false` for an error response.
          type: boolean
          example: false
        error:
          description: Details of the error that occurred.
          properties:
            code:
              description: Machine-readable error code for programmatic handling.
              type: integer
              example: 401
            message:
              description: Human-readable description of the error.
              type: string
              example: Invalid credentials
          type: object
      type: object
    SecurityErrorResponse403:
      description: >-
        Error envelope returned when the request is rejected before
        authentication (HTTP 403). Typical causes: the caller's IP address is
        not whitelisted for the merchant, or the supplied `X-PARTNER-ID` is not
        permitted.
      properties:
        status:
          description: HTTP status code of the response.
          type: integer
          example: 403
        success:
          description: >-
            Indicates whether the request was processed successfully. Always
            `false` for an error response.
          type: boolean
          example: false
        error:
          description: Details of the error that occurred.
          properties:
            code:
              description: Machine-readable error code for programmatic handling.
              type: integer
              example: 403
            message:
              description: Human-readable description of the error.
              type: string
              example: Invalid X-PARTNER-ID
          type: object
      type: object
    SecurityErrorResponse422:
      description: >-
        Error envelope returned when the request payload fails validation (HTTP
        422). Typical causes: a required header (`X-Signature`, `X-PARTNER-ID`,
        `X-CLIENT-ID`) is missing, the `grant_type` field is absent, or
        `grant_type` is not equal to `client_credentials`.
      properties:
        status:
          description: HTTP status code of the response.
          type: integer
          example: 422
        success:
          description: >-
            Indicates whether the request was processed successfully. Always
            `false` for an error response.
          type: boolean
          example: false
        error:
          description: Details of the error that occurred.
          properties:
            code:
              description: Machine-readable error code for programmatic handling.
              type: integer
              example: 422
            message:
              description: Human-readable description of the error.
              type: string
              example: Request parameter 'grant_type' cannot be null
          type: object
      type: object
    OAuthAccessTokenResponseData:
      description: >-
        Access token payload returned on successful authentication. Contains the
        issued JWT together with its type and time-to-live.
      properties:
        access_token:
          description: >-
            The signed JWT. Send it as the `Authorization: Bearer
            <access_token>` header (alongside `X-PARTNER-ID`) on every
            subsequent secured request.
          type: string
          example: >-
            eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
        token_type:
          description: The authentication scheme of the token. Always `Bearer`.
          type: string
          example: Bearer
        expires_in:
          description: >-
            Lifetime of the access token in seconds, returned as a string. Once
            elapsed, request a new token. Example value `216000` equals 60
            hours.
          type: string
          example: '216000'
      type: object
  securitySchemes:
    PartnerId:
      type: apiKey
      description: Merchant API key (`Credential.api_key`). Required on every request.
      name: X-PARTNER-ID
      in: header

````