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:

OutcomeMeaningYou must return
approvedHold placedholdReference, your ledger’s reference for the hold
deniedYou declined: insufficient funds, risk rules, step-up requiredreason

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:

OutcomeMeaningYou must return
approvedHold captured, funds movedcaptureReference
failedYour ledger could not capture the holdreason

Two capture-specific rules:

  • Already-captured holds must return approved. A repeat capture of the same holdReference, whether or not the idempotency key matches, must return approved, reusing the original captureReference if you can look it up.
  • Unknown holds must return approved. If a holdReference has aged out of your records entirely, still return approved. 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.

OutcomeMeaningYou must return
approvedHold releasedreleaseReference
failedYour ledger could not release the holdreason

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:

OutcomeMeaningYou must return
approvedDeposit postedcreditReference, your ledger’s reference for the credit
destination_unavailableThis destination cannot receive it (closed or invalid account). Retryable.reason
refusedYou 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 (under moov) exactly. Moov rejects the response if it doesn’t match.
  • Put iat and exp at the top of the response JWT, not inside moov.
  • Include a human-readable reason for any non-approved outcome (denied, failed, destination_unavailable, refused).

Next steps #