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

# Commit a credit

> Execute the transfer from Meridian's sponsored account to the recipient.



## OpenAPI

````yaml products/bank-transfers/credit-api-example/credit-api-example.yaml POST /credits/commit
openapi: 3.1.0
info:
  title: Meridian Credit API — Reference Specification
  version: 1.0.0
  summary: >-
    Recommended API surface for bank partners receiving credit (payout)
    instructions from Meridian.
  description: >
    This is Meridian's **reference specification** for a bank partner Credit
    API. It is the API the

    **bank partner hosts** and **Meridian calls** whenever a product event
    requires funds to be pushed

    from Meridian's sponsored account to a customer's account at the home bank
    (for example, a customer

    withdrawal from a Retail Virtual Account).


    Partners are not required to implement this exact contract — Meridian adapts
    to existing partner

    APIs during onboarding. However, partners building a Credit API from scratch
    should start here:

    an API matching this specification plugs directly into Meridian's
    integration layer with minimal

    custom mapping, which shortens the integration timeline considerably.


    ## Lifecycle


    Meridian drives every credit through the same sequence:


    1. **`POST /credits`** (optional) — register the credit instruction ahead of
    any processing.
       The bank persists the data structure and returns `RECEIVED`. No checks against the recipient
       account, no money movement.
    2. **`POST /credits/validate`** (optional but recommended) — confirm the
    recipient account can
       receive the credit before any money movement. No funds move. Safe to call repeatedly.
    3. **`POST /credits/commit`** — execute the transfer. Idempotent on
    `transactionId`.

    4. **`GET /credits/{transactionId}`** — retrieve the current status.
    Meridian's workflow engine
       polls this until the credit reports `COMPLETED` or `FAILED`; it may also call it **before**
       commit as a pre-check, so an unknown `transactionId` must return `404` (not an error status),
       which Meridian treats as "not yet committed" rather than a failure.
    5. **Status webhook** (optional) — proactively notify Meridian of a final
    status instead of
       waiting for polling. See the `webhooks` section.

    Steps 1 and 2 are independent: Meridian may call validate without a prior
    create, and commit

    without either. Every request carries the full instruction payload, so no
    step depends on

    bank-side state from an earlier one.


    ## Response model


    If your core system can settle synchronously, returning a final result
    (`COMPLETED` or `FAILED`)

    straight from `commit` lets Meridian update the customer sooner. Meridian
    does not depend on it,

    though: it polls the status endpoint until the credit is terminal either
    way, so a synchronous

    final result is an optimization rather than a requirement.


    Most partners settle asynchronously. That is the expected case: return
    `PROCESSING` from commit

    and expose the final state via `GET /credits/{transactionId}` and, ideally,
    the status webhook.

    Align the polling and retry strategy with Meridian during onboarding.


    ## Idempotency


    `transactionId` is Meridian's unique identifier for the credit and is the
    idempotency key.

    If a `commit` is received for a `transactionId` that was already processed,
    return the original

    outcome (do not credit twice). If the payload differs from the original
    request for the same

    `transactionId`, return `409`.


    ## Business failures vs transport failures


    A credit that is *received and rejected by business rules* (account closed,
    limit exceeded,

    compliance block) is a **`200` response** with `status: FAILED` plus a
    machine-readable

    `errorCode`. Reserve `4xx`/`5xx` for malformed requests, authentication
    failures, and genuine

    server faults. This distinction is load-bearing: Meridian retries transport
    failures but treats

    business failures as final.


    ## Conventions


    These are the conventions used throughout this specification. They are
    recommendations, not

    requirements — Meridian can adapt to the bank's preferred formats during
    onboarding.


    - Amounts are strings with up to 2 decimal places (never floats), with an
    ISO 4217 currency code.

    - Country codes are ISO 3166-1 alpha-2 (`PH`, `US`).

    - Timestamps are RFC 3339 / ISO 8601 with timezone offset.

    - All requests and responses are `application/json` over HTTPS (TLS 1.2+).
  contact:
    name: Meridian Implementation Team
    url: https://docs.mnai.com/products/bank-transfers/credit-api
servers:
  - url: https://api.examplebank.com/meridian/v1
    description: Production (partner-hosted)
  - url: https://sandbox.examplebank.com/meridian/v1
    description: Sandbox (required before go-live)
security:
  - bearerAuth: []
tags:
  - name: Credits
    description: Validate, execute, and track credit (payout) instructions.
paths:
  /credits/commit:
    post:
      tags:
        - Credits
      summary: Execute a credit (money movement)
      description: >
        Initiates the intra-bank transfer from Meridian's sponsored account to
        the customer's account.


        **Idempotent on `transactionId`**: replays of an already-processed
        transaction must return the

        original outcome without moving funds again. A replay whose payload
        differs from the original

        must return `409`.


        Return `COMPLETED` or `FAILED` synchronously whenever possible. Return
        `PROCESSING` only when

        the outcome genuinely cannot be known synchronously; Meridian will then
        poll

        `GET /credits/{transactionId}` until a final status is available.
      operationId: commitCredit
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreditInstruction'
            examples:
              instruction:
                $ref: '#/components/examples/CreditInstructionExample'
      responses:
        '200':
          description: >-
            Commit outcome (business rejections also return 200 with `status:
            FAILED`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreditResult'
              examples:
                completed:
                  summary: Synchronous success (preferred)
                  value:
                    transactionId: mrdn-9f2c1e4a-71bd-4c5e-a2f3-8d6b0c9e1a27
                    status: COMPLETED
                    bankReference: EBNK20260812000123456
                    completedAt: '2026-08-12T15:04:05+08:00'
                processing:
                  summary: Asynchronous fallback (Meridian polls until final)
                  value:
                    transactionId: mrdn-9f2c1e4a-71bd-4c5e-a2f3-8d6b0c9e1a27
                    status: PROCESSING
                    bankReference: EBNK20260812000123456
                rejected:
                  summary: Business rejection (final)
                  value:
                    transactionId: mrdn-9f2c1e4a-71bd-4c5e-a2f3-8d6b0c9e1a27
                    status: FAILED
                    errorCode: LIMIT_EXCEEDED
                    errorMessage: Credit exceeds the recipient's monthly inbound limit.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: The `transactionId` was already used with a different payload.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  schemas:
    CreditInstruction:
      type: object
      description: A credit (payout) instruction from Meridian to the bank.
      required:
        - transactionId
        - amount
        - recipient
      properties:
        transactionId:
          type: string
          maxLength: 64
          description: >
            Meridian's unique identifier for this credit and the idempotency
            key. Stable across

            retries and across the validate/commit/status lifecycle of one
            transaction.
          example: mrdn-9f2c1e4a-71bd-4c5e-a2f3-8d6b0c9e1a27
        amount:
          $ref: '#/components/schemas/MonetaryAmount'
        recipient:
          $ref: '#/components/schemas/Recipient'
        sender:
          $ref: '#/components/schemas/Party'
          description: >
            Originator of the funds (KYC data). Included on commit for
            compliance screening.

            Field-level availability is confirmed during onboarding, and some
            corridors add further

            compliance fields (for example the sender's relationship to the
            recipient, or source of

            income) that Meridian agrees with the bank at that time.
        purpose:
          type: string
          maxLength: 140
          description: Human-readable purpose / remittance information for the transfer.
          example: Wallet withdrawal payout
        metadata:
          type: object
          additionalProperties:
            type: string
          description: >
            Additional key/value context supplied by Meridian (e.g. a
            customer-facing reference to

            print on statements). Banks should persist and echo these where
            their core allows, but

            must not require fields beyond those agreed at onboarding.
    CreditResult:
      type: object
      description: Outcome of a validate, commit, or status call. One shape for all three.
      required:
        - transactionId
        - status
      properties:
        transactionId:
          type: string
          description: Echo of Meridian's transaction identifier.
        status:
          $ref: '#/components/schemas/CreditStatus'
        bankReference:
          type: string
          maxLength: 64
          description: >
            The bank's own reference for the transfer, if one exists. Meridian
            stores this for

            reconciliation and support. Include it on every response after
            commit.
        errorCode:
          type: string
          description: >
            Machine-readable failure code. **Required whenever `status` is
            `FAILED`.** Use a stable,

            documented set; Meridian maps these to customer-facing outcomes.
            Recommended baseline:


            - `ACCOUNT_NOT_FOUND`

            - `ACCOUNT_INACTIVE`

            - `NAME_MISMATCH`

            - `LIMIT_EXCEEDED`

            - `INVALID_AMOUNT`

            - `COMPLIANCE_REJECTED`

            - `INSUFFICIENT_FUNDS` (sponsored account)

            - `DUPLICATE_TRANSACTION`

            - `BANK_SYSTEM_ERROR`
        errorMessage:
          type: string
          maxLength: 500
          description: >-
            Human-readable detail for the failure. Not shown to customers
            verbatim.
        completedAt:
          type: string
          format: date-time
          description: RFC 3339 timestamp when the credit reached a final status.
    ApiError:
      type: object
      description: Transport-level error payload for 4xx/5xx responses.
      required:
        - errorCode
        - errorMessage
      properties:
        errorCode:
          type: string
        errorMessage:
          type: string
    MonetaryAmount:
      type: object
      required:
        - value
        - currency
      properties:
        value:
          type: string
          pattern: ^\d+(\.\d{1,2})?$
          description: Decimal amount as a string, up to 2 decimal places. Never a float.
          example: '1500.00'
        currency:
          type: string
          pattern: ^[A-Z]{3}$
          description: ISO 4217 currency code.
          example: PHP
    Recipient:
      type: object
      description: The customer being credited at the home bank.
      required:
        - account
        - firstName
        - lastName
      properties:
        account:
          $ref: '#/components/schemas/BankAccount'
        firstName:
          type: string
          maxLength: 70
          example: Maria
        middleName:
          type: string
          maxLength: 70
        lastName:
          type: string
          maxLength: 70
          example: Santos
    Party:
      type: object
      description: A person involved in the transaction (KYC subject).
      required:
        - firstName
        - lastName
      properties:
        firstName:
          type: string
          maxLength: 70
        middleName:
          type: string
          maxLength: 70
        lastName:
          type: string
          maxLength: 70
        dateOfBirth:
          type: string
          format: date
          description: >
            ISO 8601 date (YYYY-MM-DD). Some destinations require the sender's
            date of birth for

            compliance screening and reject the credit without it, so support
            this field even though

            it is not marked required here.
          example: '1990-01-15'
        countryOfResidence:
          type: string
          pattern: ^[A-Z]{2}$
          description: ISO 3166-1 alpha-2.
          example: PH
        address:
          $ref: '#/components/schemas/PostalAddress'
    CreditStatus:
      type: string
      description: >
        Transaction state machine:


        - `RECEIVED` — registered; nothing checked and nothing moved

        - `VALIDATED` — the recipient account passed eligibility checks

        - `PROCESSING` — money movement is underway

        - `COMPLETED` — terminal; the funds reached the recipient

        - `FAILED` — terminal; the credit will not be delivered

        - `UNKNOWN` — outcome not yet determinable, for example a timeout in
        your core system or an
          unreachable downstream rail; not terminal

        Status moves only forward through that order, though skipping steps is
        fine, and terminal

        statuses must never change once reported. `UNKNOWN` is exempt from the
        ordering and may be

        followed by any status. Prefer it over guessing `FAILED`, since a
        terminal status can never

        be walked back.
      enum:
        - RECEIVED
        - VALIDATED
        - PROCESSING
        - COMPLETED
        - FAILED
        - UNKNOWN
    BankAccount:
      type: object
      description: Account identification at the home bank (intra-bank transfer target).
      required:
        - accountNumber
      properties:
        accountNumber:
          type: string
          maxLength: 34
          description: >-
            Account number in the bank's canonical format (or IBAN where
            applicable).
          example: '001234567890'
    PostalAddress:
      type: object
      properties:
        addressLines:
          type: array
          items:
            type: string
            maxLength: 70
          maxItems: 3
        city:
          type: string
          maxLength: 35
        stateProvince:
          type: string
          maxLength: 35
        postalCode:
          type: string
          maxLength: 16
        country:
          type: string
          pattern: ^[A-Z]{2}$
          description: ISO 3166-1 alpha-2.
          example: PH
  examples:
    CreditInstructionExample:
      summary: PHP 1,500.00 payout to a bank account
      description: >
        The same instruction is sent to create, validate, and commit. Only the
        endpoint changes.
      value:
        transactionId: mrdn-9f2c1e4a-71bd-4c5e-a2f3-8d6b0c9e1a27
        amount:
          value: '1500.00'
          currency: PHP
        recipient:
          account:
            accountNumber: '001234567890'
          firstName: Maria
          lastName: Santos
        sender:
          firstName: Juan
          lastName: Cruz
          dateOfBirth: '1990-01-15'
          address:
            addressLines:
              - 123 Test Street
            city: Taguig
            stateProvince: Metro Manila
            postalCode: '1634'
            country: PH
        metadata:
          reference: R9x8k2m4p6w1c3v5b7n9q0z2
  responses:
    BadRequest:
      description: >-
        Malformed request (missing/invalid fields). Not retryable without
        correction.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            errorCode: VALIDATION_ERROR
            errorMessage: >-
              amount.value must be a decimal string with at most 2 decimal
              places.
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    ServerError:
      description: Unexpected bank-side failure. Meridian treats this as retryable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        Assume OAuth 2.0 client credentials issued by the bank, presented as a
        bearer token.

        Meridian can adapt to the bank's preferred authentication scheme during
        onboarding.

````