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

# Create v2

> Creates a new payment link for an active account. Simplified body compared to v1 — several fields (`title`, `is_multiple_payment`, `is_unlimited_usage`, `redirect_url_enabled`) are no longer accepted and are derived automatically instead. See `CreatePaymentLinkV2Request` for the full set of derivation rules.



## OpenAPI

````yaml https://payment-b2b.singapay.id/api/docs/merchant-api.json post /api/v2.0/payment-link/{account_id}
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 standard Singapay SP000–SP020 dictionary
      codes and messages. Field-level validation detail is returned in
      `data.errors` for **SP018**. The `/charge` endpoint is additionally
      protected by **`X-Signature`** + **`X-Timestamp`**
      (`verify.signature-internal`); see operation parameters for the signing
      scheme. Asynchronous outcomes (bind / unbind / charge) are HTTP POST
      callbacks to `callback_urls.direct_debit_notif_url` — see the Direct Debit
      **webhooks** (`directDebitBindingNotification`,
      `directDebitUnbindingNotification`, `directDebitTransactionNotification`).
      All three share that single URL; discriminate on `event`.
  - 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).
  - name: Retail Store
    description: >-
      Native Retail Store money-in — generate an Alfamart / Indomaret payment
      code the customer pays at the cashier, then read its status
      (`RetailTransactionController`, prefix `v1.0/retail-transactions`). Only
      two endpoints: create and show. `account_id` is the account ULID;
      `transaction_id` is the platform-assigned
      `retail_transactions.transaction_id` string returned by create. Payment
      confirmation arrives as a POST callback to
      `callback_urls.transaction_notif_url` with `event = retail-transaction`.
  - name: Settlement Transaction
    description: >-
      Read-only listing of the transactions inside a settlement
      (`SettlementMerchantApiController`, `GET
      v1.0/settlement-transactions/{identifier}`). A sub-menu of the merchant
      Transaction Record APIs. Merchant-scoped — only settlements with status
      `completed` are exposed. `{identifier}` is the numeric `settlements.id` or
      the `settlements.reference_no`. Each item mirrors the money-in transaction
      shape (`account`, `fees`, `amount`, `post_timestamp`,
      `processed_timestamp`, `has_settle`, `settle_at`). Merchants cannot
      create, approve, or refund settlements; those actions are BOSS-only.
paths:
  /api/v2.0/payment-link/{account_id}:
    post:
      tags:
        - Payment Link
      summary: Create v2
      description: >-
        Creates a new payment link for an active account. Simplified body
        compared to v1 — several fields (`title`, `is_multiple_payment`,
        `is_unlimited_usage`, `redirect_url_enabled`) are no longer accepted and
        are derived automatically instead. See `CreatePaymentLinkV2Request` for
        the full set of derivation rules.
      operationId: paymentLinkV2Store
      parameters:
        - name: account_id
          in: path
          required: true
          schema:
            description: Account identifier in ULID format.
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePaymentLinkV2Request'
      responses:
        '200':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderSuccessPaymentLinkV2'
        '400':
          description: Reference number URL collision (`payment_url` already exists)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderErrorEnvelope400'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderErrorEnvelope401'
        '403':
          description: Access denied to this account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderErrorEnvelope403'
        '404':
          description: Account not found or inactive
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderErrorEnvelope404'
        '405':
          description: Method not allowed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderErrorEnvelope405'
        '422':
          description: >-
            Validation error (including invalid `payment_link_type`, `items`
            sent when `payment_link_type` is `total`, `total_amount` sent when
            `payment_link_type` is `items`, dynamic limits, invalid payment
            method codes, no payment methods eligible for the amount,
            `customer_name`/`customer_email`/`customer_phone` sent for a
            multi-use link, or `reminder_unit`/`reminder_period` and
            `customer_notification_preference.payment_link_reminder` disagreeing
            on whether a reminder is configured — either side present without
            the other)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResponderErrorEnvelope422'
      security:
        - BearerAuth: []
          PartnerId: []
components:
  schemas:
    CreatePaymentLinkV2Request:
      description: >-
        v2 simplifies the v1 body: `title`, `is_multiple_payment`,
        `is_unlimited_usage`, and `redirect_url_enabled` are no longer accepted
        — they are derived automatically from the other fields.
      required:
        - reff_no
        - payment_link_type
      properties:
        reff_no:
          description: Merchant reference number for this payment link.
          type: string
          maxLength: 40
          pattern: ^[^\s\/]+$
          example: INV20240513001
        description:
          description: Optional free-text description for the payment link.
          type:
            - string
            - 'null'
          maxLength: 255
          example: 'Invoice #INV20240513001'
        payment_link_type:
          description: >-
            Must be exactly `total` or `items` (422 on any other value).
            Determines which of `total_amount` / `items` is required — the other
            one must not be sent at all: `total` requires `total_amount` and
            rejects `items` if sent (422); `items` requires `items` and rejects
            `total_amount` if sent (422), since it's computed from items
            server-side.
          type: string
          enum:
            - total
            - items
          example: total
        max_usage:
          description: >-
            Maximum number of successful payments allowed. Omit for a single-use
            link (defaults to `1`). `0` means unlimited. Any value greater than
            `1` makes this a multi-use link —
            `is_multiple_payment`/`is_unlimited_usage`/`required_customer_detail`
            are derived from this value and cannot be set directly.
          type:
            - integer
            - 'null'
          maximum: 999
          minimum: 0
          example: 1
        expired_at:
          description: >-
            Optional expiration timestamp, any date/time string parseable by PHP
            (ISO 8601 recommended, e.g. `2026-08-10T00:00:00+07:00`). Must be in
            the future. Omit or send `null` to default to 24 hours from creation
            (D+1) — unlike v1, this is never left unset.
          type:
            - string
            - 'null'
          format: date-time
          example: '2026-08-10T00:00:00+07:00'
        total_amount:
          description: >-
            Total payment amount. Required when `payment_link_type` is `total`;
            must not be sent at all when `payment_link_type` is `items` (422) —
            it's computed from `items` server-side instead, so sending both
            would be ambiguous. Minimum/maximum depend on merchant configuration
            and the resolved payment methods.
          type:
            - number
            - 'null'
          example: 150000
        items:
          description: >-
            Line items. Required when `payment_link_type` is `items`; must not
            be sent at all when `payment_link_type` is `total` (422).
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/PaymentLinkLineItemRequest'
          minItems: 1
        whitelisted_payment_method:
          description: >-
            Restricts accepted payment methods for this link. Omit, send `null`,
            or send an empty array to auto-select whichever active payment-link
            methods are actually eligible for the resolved `total_amount` — v2
            never leaves this unrestricted the way v1 does. Each entry must be a
            valid payment method code.
          type:
            - array
            - 'null'
          items:
            type: string
        success_redirect_url:
          description: >-
            URL to redirect the payer after successful payment. Must start with
            http:// or https://. Sending either this or `expired_redirect_url`
            automatically enables `redirect_url`.
          type:
            - string
            - 'null'
          format: uri
          maxLength: 2048
          example: https://merchant.example.com/payment/success
        expired_redirect_url:
          description: >-
            URL to redirect the payer after payment expiry. Must start with
            http:// or https://.
          type:
            - string
            - 'null'
          format: uri
          maxLength: 2048
          example: https://merchant.example.com/payment/expired
        optional_metadata:
          description: Optional merchant-defined metadata stored with the payment link.
          type:
            - object
            - 'null'
          additionalProperties: true
        customer_name:
          description: >-
            Pre-fills the known customer name for a single-use link. Only
            allowed when `max_usage` resolves to `1`; sending this alongside a
            multi-use `max_usage` returns a 422. Required together with
            `customer_email`/`customer_phone` if any of the three is provided,
            and required (along with the other two) whenever
            `customer_notification_preference.payment_link_created` or
            `customer_notification_preference.payment_link_reminder` is
            non-empty — regardless of which channel(s) are selected.
          type:
            - string
            - 'null'
          maxLength: 100
          example: Jane Doe
        customer_email:
          description: Pre-fills the known customer email. See `customer_name`.
          type:
            - string
            - 'null'
          format: email
          maxLength: 255
          example: jane@example.com
        customer_phone:
          description: >-
            Pre-fills the known customer phone number. Unlike
            `customer_name`/`customer_email`, not required merely by providing
            one of the other two fields — only required when
            `customer_notification_preference.payment_link_created` or
            `customer_notification_preference.payment_link_reminder` is
            non-empty.
          type:
            - string
            - 'null'
          maxLength: 50
          example: '081234567890'
        required_customer_number:
          description: >-
            Only meaningful when `max_usage` > 1. Whether the payer must fill in
            a phone number at checkout. Defaults to `true` for multi-use links
            unless explicitly set to `false`.
          type:
            - boolean
            - 'null'
          example: true
        required_customer_email:
          description: >-
            Only meaningful when `max_usage` > 1. Whether the payer must fill in
            an email at checkout. Defaults to `true` for multi-use links unless
            explicitly set to `false`.
          type:
            - boolean
            - 'null'
          example: true
        customer_notification_preference:
          description: >-
            Which channels notify the customer at each lifecycle event. Only
            accepted for a single-use link. Having any channel (whatsapp or
            email) in either `payment_link_created` or `payment_link_reminder`
            requires `customer_name`, `customer_email`, AND `customer_phone` all
            three — not just the field the selected channel would use (422 if
            any is missing). WhatsApp incurs a fixed notification fee charged to
            the merchant's balance at send time; email is always free.
          properties:
            payment_link_created:
              description: >-
                Channels that notify the customer immediately when the link is
                created.
              type:
                - array
                - 'null'
              items:
                type: string
                enum:
                  - whatsapp
                  - email
              example:
                - whatsapp
                - email
            payment_link_reminder:
              description: >-
                Channels that notify the customer once, `reminder_period`
                `reminder_unit`(s) before `expired_at`. Non-empty requires
                `reminder_unit`/`reminder_period` to also be sent (422 if either
                is missing).
              type:
                - array
                - 'null'
              items:
                type: string
                enum:
                  - whatsapp
                  - email
              example:
                - whatsapp
          type:
            - object
            - 'null'
        reminder_unit:
          description: >-
            Unit for `reminder_period`. Tied directly to
            `customer_notification_preference.payment_link_reminder`, not just
            to `reminder_period`: required (422 if missing) whenever
            `payment_link_reminder` has at least one channel, and prohibited
            (422 if sent) whenever it's empty or
            `customer_notification_preference` is omitted entirely.
          type:
            - string
            - 'null'
          enum:
            - day
            - hour
          example: day
        reminder_period:
          description: >-
            How long before `expired_at` the reminder fires, in `reminder_unit`
            units: 1–24 for `hour`, 1–30 for `day`. Must resolve to a time
            strictly after `created_at` (422 otherwise). Same
            `payment_link_reminder`-tied required/prohibited 422 rule as
            `reminder_unit`.
          type:
            - integer
            - 'null'
          example: 1
      type: object
    ResponderSuccessPaymentLinkV2:
      required:
        - status
        - success
      properties:
        status:
          description: HTTP status code.
          type: integer
          example: 200
        success:
          description: Indicates whether the request was successful.
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/PaymentLinkV2Resource'
          description: Payment link resource payload.
      type: object
    ResponderErrorEnvelope400:
      required:
        - status
        - success
        - error
      properties:
        status:
          type: integer
          example: 400
        success:
          type: boolean
          example: false
        error:
          $ref: '#/components/schemas/ResponderErrorBody400'
      type: object
    ResponderErrorEnvelope401:
      required:
        - status
        - success
        - error
      properties:
        status:
          type: integer
          example: 401
        success:
          type: boolean
          example: false
        error:
          $ref: '#/components/schemas/ResponderErrorBody401'
      type: object
    ResponderErrorEnvelope403:
      required:
        - status
        - success
        - error
      properties:
        status:
          type: integer
          example: 403
        success:
          type: boolean
          example: false
        error:
          $ref: '#/components/schemas/ResponderErrorBody403'
      type: object
    ResponderErrorEnvelope404:
      required:
        - status
        - success
        - error
      properties:
        status:
          type: integer
          example: 404
        success:
          type: boolean
          example: false
        error:
          $ref: '#/components/schemas/ResponderErrorBody404'
      type: object
    ResponderErrorEnvelope405:
      required:
        - status
        - success
        - error
      properties:
        status:
          type: integer
          example: 405
        success:
          type: boolean
          example: false
        error:
          $ref: '#/components/schemas/ResponderErrorBody405'
      type: object
    ResponderErrorEnvelope422:
      required:
        - status
        - success
        - error
      properties:
        status:
          type: integer
          example: 422
        success:
          type: boolean
          example: false
        error:
          $ref: '#/components/schemas/ResponderErrorBody422'
        data:
          type: object
          example:
            errors:
              field:
                - error message
          additionalProperties: true
      type: object
    PaymentLinkLineItemRequest:
      required:
        - name
        - quantity
        - unit_price
      properties:
        name:
          description: Line item name shown to the payer.
          type: string
          maxLength: 255
          example: Product A
        quantity:
          description: Number of units for this line item.
          type: integer
          minimum: 1
          example: 1
        unit_price:
          description: >-
            Unit price per item. Negative values are permitted for discount line
            items.
          type: number
          example: 150000
      type: object
    PaymentLinkV2Resource:
      description: >-
        Payment link resource returned by the v2 create/get/update endpoints.
        Includes nested account details when available. Distinct from
        `PaymentLinkResource` (v1) — v2 exposes `payment_link_type`,
        `redirect_url_enabled`, `target_customer_details_enabled`,
        `customer_notification_preference`, `reminder_unit`, and
        `reminder_period` instead.
      properties:
        id:
          description: >-
            Payment link identifier. Use this value as `{link_id}` in path
            parameters.
          type: integer
          example: 103
        reff_no:
          description: Merchant reference number assigned to the payment link.
          type: string
          example: INV20240513001
        description:
          description: Free-text description for the payment link.
          type:
            - string
            - 'null'
          example: 'Invoice #INV20240513001'
        source:
          description: >-
            How the payment link was created: `api v1`, `api v2`, or
            `dashboard`.
          type:
            - string
            - 'null'
          example: api v2
        payment_url:
          description: Hosted payment page URL for this payment link.
          type: string
          example: https://example.com/payment-link
        status:
          description: Configured payment link status.
          type: string
          example: open
        is_expired:
          description: Whether the payment link is currently expired.
          type: boolean
          example: false
        payment_link_type:
          description: >-
            Derived from whether line items were stored for this link — not an
            accepted input field. `items` when the link has line items, `total`
            otherwise.
          type: string
          enum:
            - total
            - items
          example: total
        is_multiple_payment:
          description: >-
            Whether this link accepts more than one successful payment
            (`max_usage` > 1 or unlimited).
          type: boolean
          example: false
        is_unlimited_usage:
          description: Whether this link has no usage cap (`max_usage` = 0).
          type: boolean
          example: false
        max_usage:
          description: >-
            Maximum number of successful payments permitted. `0` means
            unlimited.
          type: integer
          example: 1
        current_usage:
          description: Current number of successful payments recorded for the link.
          type: integer
          example: 0
        expired_at:
          description: Expiration datetime in ISO 8601 format.
          type:
            - string
            - 'null'
          example: '2024-05-13T00:00:00Z'
        required_customer_detail:
          description: >-
            Whether the payer must fill in a customer-detail form at checkout
            (used for multi-use links, where the payer is not known in advance).
          type: boolean
          example: true
        required_customer_fields:
          description: >-
            Which customer-detail fields are required from the payer at checkout
            when `required_customer_detail` is true.
          properties:
            name:
              type: boolean
              example: true
            phone:
              type: boolean
              example: false
            email:
              type: boolean
              example: false
          type: object
        total_amount:
          description: Total payment amount for the payment link.
          type: number
          example: 150000
        items:
          description: >-
            Line items stored for the payment link. `null` when the link was
            created with `payment_link_type: "total"` or without item details.
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/PaymentLinkLineItemStored'
        whitelisted_payment_method:
          description: >-
            List of allowed payment method codes for this link. When the
            create/update request omits this field, it is auto-populated with
            whichever payment methods are actually eligible for `total_amount`
            at that time — never left empty.
          type: array
          items:
            type: string
        redirect_url_enabled:
          description: >-
            Derived from whether either redirect URL below is set — not an
            accepted input field.
          type: boolean
          example: false
        success_redirect_url:
          description: Redirect URL for successful payment.
          type:
            - string
            - 'null'
          example: https://merchant.example.com/payment/success
        expired_redirect_url:
          description: Redirect URL for expired payment.
          type:
            - string
            - 'null'
          example: https://merchant.example.com/payment/expired
        optional_metadata:
          description: Merchant-defined metadata attached to the payment link.
          type:
            - object
            - 'null'
          additionalProperties: true
        target_customer_details_enabled:
          description: >-
            Whether the merchant pre-supplied any known-payer contact info
            (`customer_name`, `customer_email`, or `customer_phone`) for this
            single-use link. Not the same as `required_customer_detail`.
          type: boolean
          example: true
        customer_name:
          description: >-
            Pre-filled/known customer name. Only set on single-use (`max_usage`
            = 1) links where the merchant knows the payer in advance.
          type:
            - string
            - 'null'
          example: Jane Doe
        customer_email:
          description: Pre-filled/known customer email. Only set on single-use links.
          type:
            - string
            - 'null'
          example: jane@example.com
        customer_phone:
          description: >-
            Pre-filled/known customer phone number. Only set on single-use
            links.
          type:
            - string
            - 'null'
          example: '081234567890'
        customer_notification_preference:
          description: >-
            Which channels notify the customer at each lifecycle event. WhatsApp
            incurs a fixed notification fee (charged to the merchant's balance);
            email is always free.
          properties:
            payment_link_created:
              type: array
              items:
                type: string
                enum:
                  - whatsapp
                  - email
              example:
                - whatsapp
                - email
            payment_link_reminder:
              type: array
              items:
                type: string
                enum:
                  - whatsapp
                  - email
              example:
                - whatsapp
          type:
            - object
            - 'null'
        reminder_unit:
          description: >-
            Unit for `reminder_period`. Only set when a reminder channel is
            configured.
          type:
            - string
            - 'null'
          enum:
            - day
            - hour
            - null
          example: day
        reminder_period:
          description: >-
            How long before `expired_at` the reminder notification fires, in
            `reminder_unit` units.
          type:
            - integer
            - 'null'
          example: 1
        created_at:
          description: Resource creation datetime in ISO 8601 format.
          type:
            - string
            - 'null'
          example: '2024-05-13T00:00:00Z'
        updated_at:
          description: Last update datetime in ISO 8601 format.
          type:
            - string
            - 'null'
          example: '2024-05-13T00:00:00Z'
        account:
          oneOf:
            - $ref: '#/components/schemas/PaymentLinkV2AccountResource'
              description: >-
                Related account resource when available. Slimmer than v1's full
                Account resource — only `id` and `name`.
            - type: 'null'
          description: >-
            Related account resource when available. Slimmer than v1's full
            Account resource — only `id` and `name`.
          example:
            id: 1
            name: Account 1
      type: object
    ResponderErrorBody400:
      properties:
        code:
          type: integer
          example: 400
        message:
          type: string
          example: Bad Request.
      type: object
    ResponderErrorBody401:
      properties:
        code:
          type: integer
          example: 401
        message:
          type: string
          example: Unauthorized merchant, please sign in
      type: object
    ResponderErrorBody403:
      properties:
        code:
          type: integer
          example: 403
        message:
          type: string
          example: Access denied.
      type: object
    ResponderErrorBody404:
      properties:
        code:
          type: integer
          example: 404
        message:
          type: string
          example: Account not found.
      type: object
    ResponderErrorBody405:
      properties:
        code:
          type: integer
          example: 4059901
        message:
          type: string
          example: >-
            The PATCH method is not supported for this route. Supported methods:
            GET, HEAD, POST.
      type: object
    ResponderErrorBody422:
      properties:
        code:
          type: integer
          example: 422
        message:
          type: string
          example: Validation error.
        errors:
          type: object
          example:
            field:
              - error message
      type: object
    PaymentLinkLineItemStored:
      properties:
        name:
          description: Line item name stored on the payment link.
          type: string
          example: Product A
        quantity:
          description: Stored quantity for the line item.
          type: integer
          example: 1
        unit_price:
          description: Stored unit price for the line item.
          type: number
          example: 150000
        subtotal:
          description: Calculated line item subtotal (`quantity x unit_price`).
          type: number
          example: 150000
      type: object
    PaymentLinkV2AccountResource:
      description: >-
        Slim account resource nested under `PaymentLinkV2Resource.account` —
        only `id` and `name`. Distinct from v1's full `Account` schema, which
        also exposes account_number, status, account_type, kyb_status,
        legal_name, brand_name, kyb_onboarding_url, and invite_members.
      properties:
        id:
          description: Account identifier in ULID format.
          type: string
          example: 01M1BFRSG3BY6AQ1PE8PB7RCB5
        name:
          description: Account display name.
          type: string
          example: Jeremy Main Account
      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

````