Ledger endpoints
Each call is an HTTPS POST with a JWE envelope.
Authorize places a hold; that hold then ends in capture or release.
Field-by-field claims are in the API reference: authorize, capture, release, credit account. A paid request is the other direction: credit books a deposit after money is already in your wallet.
Authorize #
Called when a user initiates a payment. You decide whether to place a hold on their funding source. Claims: authorize.
The request claims include the payout ID, your own externalID for the
sender (so you can resolve them without Moov’s participant IDs), an opaque
fundingSource token, the amount, and a fraudScore from 0.0 to 1.0,
where higher means riskier. You may factor the score into your decision, for
example requiring step-up authentication above a threshold. How that score
is produced, and when a payment is held for review instead, is in
trust & safety.
Outcomes on 200 OK:
| Outcome | Meaning | You must return |
|---|---|---|
approved | Hold placed | holdReference, your ledger’s reference for the hold |
denied | You declined: insufficient funds, risk rules, step-up required | reason |
Moov supplies your holdReference back to you on the later capture or
release call for the same payout.
Do not return 200 with any other outcome value to signal a processing
failure. Moov Money treats unmodeled outcomes as an internal unknown
result and discards your reason. If your ledger is unavailable, return a
retryable HTTP status (408, 429, or 5xx) instead.
Capture #
Called after the recipient completes their claim onto a debit card, Apple Pay, or Google Pay. You settle the hold, debiting the sender so you can originate the push-to-card payment. See flow of funds. Claims: capture.
The request carries the holdReference you returned on authorize. Capture
has no denied outcome. Either you captured the hold or you did not:
| Outcome | Meaning | You must return |
|---|---|---|
approved | Hold captured, funds moved | captureReference |
failed | Your ledger could not capture the hold | reason |
Two capture-specific rules:
- Already-captured holds must return
approved. A repeat capture of the sameholdReference, whether or not the idempotency key matches, must returnapproved, reusing the originalcaptureReferenceif you can look it up. - Unknown holds must return
approved. If aholdReferencehas aged out of your records entirely, still returnapproved. Moov Money treats unknown holds as already captured; the alternative would strand funds in flight. If this doesn’t fit your ledger model, escalate to Moov before implementing.
Release #
Called when a payment is canceled or its 10-day claim window expires. You release the hold, returning funds to the sender. Claims: release.
The request carries the holdReference plus a non-normative reason, with
values like canceled (user-initiated) and expired (hold TTL exceeded)
so you can distinguish them in your ledger.
| Outcome | Meaning | You must return |
|---|---|---|
approved | Hold released | releaseReference |
failed | Your ledger could not release the hold | reason |
Releasing an already-released hold must return approved, reusing the
original releaseReference when you can.
Credit #
Called after a request has been paid and the funds are in your
wallet (received). You book a deposit to the requester. Same JWE
envelope as authorize. Claims:
credit account.
The request carries requestID (the request-for-payment, not a payout
ID), requesterExternalID, fundingDestination (opaque token for
where the deposit lands), the amount, and an idempotencyKey. Deduplicate
on that key so a retry never double-posts. The key’s scope is one
disbursement attempt.
Outcomes on 200 OK:
| Outcome | Meaning | You must return |
|---|---|---|
approved | Deposit posted | creditReference, your ledger’s reference for the credit |
destination_unavailable | This destination cannot receive it (closed or invalid account). Retryable. | reason |
refused | You refuse the deposit itself. Terminal; Moov begins reversal. | reason |
Do not return 200 with unknown or any other unmodeled value.
Moov synthesizes unknown for timeouts and unrecognized outcomes; if
your ledger is down, return 408, 429, or a 5xx so Moov retries
the same idempotencyKey. Other 4xx are terminal.
Repeating an approved credit with the same key must return approved
and the original creditReference.
Card-funded programs skip this callback: the requester is credited by an OCT to their FI-issued card instead. See flow of funds.
Every response, every time #
Regardless of endpoint or outcome:
- Echo the request’s
idempotencyKey(undermoov) exactly. Moov rejects the response if it doesn’t match. - Put
iatandexpat the top of the response JWT, not insidemoov. - Include a human-readable
reasonfor any non-approvedoutcome (denied,failed,destination_unavailable,refused).
Next steps #
- Idempotency and retries: the delivery guarantees behind these rules.
- API reference: every claim, with examples. Start with credit account if you collect on requests.