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

# Overview

> A reference specification for bank partners building a Credit API from scratch.

This section is Meridian's **reference specification** for a bank partner Credit API. It describes 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, such as a customer withdrawal from a Retail Virtual Account.

<Note>
  Partners are not required to implement this exact contract. Meridian adapts to existing partner APIs during onboarding. See [Credit API](/products/bank-transfers/credit-api) for how that integration works.
</Note>

If you are building a Credit API from scratch, 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:

<Steps>
  <Step title="Prepare Credit: create (optional)">
    `POST /credits` registers the credit instruction ahead of any processing. The bank persists the data structure and returns `RECEIVED`. No checks against the recipient account, and no money movement.
  </Step>

  <Step title="Prepare Credit: validate (optional but recommended)">
    `POST /credits/validate` confirms the recipient account can receive the credit before any money movement. No funds move, and it is safe to call repeatedly.
  </Step>

  <Step title="Execute Credit: commit">
    `POST /credits/commit` executes the transfer. It is idempotent on `transactionId`.
  </Step>

  <Step title="Confirm Credit: get transaction status">
    `GET /credits/{transactionId}` returns the current status. Meridian's workflow engine polls this until the credit reports `COMPLETED` or `FAILED`, and may also call it **before** commit as a pre-check. An unknown `transactionId` must return `404` rather than an error status, so Meridian treats it as "not yet committed" rather than a failure.
  </Step>

  <Step title="Confirm Credit: status webhook (optional)">
    Proactively notify Meridian of a final status instead of waiting for polling.
  </Step>
</Steps>

<Note>
  Create and validate 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.
</Note>

## 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, and that is the expected case. Return `PROCESSING` from commit and expose the final state via `GET /credits/{transactionId}` and, ideally, the [status webhook](/products/bank-transfers/credit-api-example/status-webhook). Align the polling and retry strategy with Meridian during onboarding.

### When you cannot determine the outcome

Report `UNKNOWN` when you genuinely do not know the result yet, such as a timeout inside your core system or an unreachable downstream rail. It is not a terminal status, so Meridian keeps polling, and you can follow it with any other status later.

<Tip>
  `UNKNOWN` is always better than guessing `FAILED`. `COMPLETED` and `FAILED` are terminal and can never be walked back, so a wrong guess is unrecoverable.
</Tip>

## Idempotency

`transactionId` is Meridian's unique identifier for the credit and serves as the idempotency key. If a commit is received for a `transactionId` that was already processed, return the original outcome and 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, such as a closed account, an exceeded limit, or a compliance block, is a **`200` response** with `status: FAILED` plus a machine-readable `errorCode`. Reserve `4xx` and `5xx` for malformed requests, authentication failures, and genuine server faults.

<Warning>
  This distinction is load-bearing. Meridian retries transport failures but treats business failures as final.
</Warning>

## 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 a timezone offset.
* All requests and responses are `application/json` over HTTPS (TLS 1.2+).
