Setting up your funding integration
Register the URLs Moov should call, then exchange a signing secret. You host the endpoints; Moov POSTs to them.
Three steps: register URLs, exchange a signing secret, and confirm the request shape.
Register your provider URLs #
Register independent URLs with Moov Money:
| URL | Called when | Purpose |
|---|---|---|
AuthorizationURL | A user initiates a payment | Place a hold on their funding source |
CaptureURL | The recipient completes a claim | Settle (capture) a previously placed hold |
HoldReleaseURL | A payment is canceled or expires | Release a hold, returning funds to the sender |
CreditURL | A request has been paid into your wallet | Book a deposit to the requester |
Moov Money POSTs to each registered URL verbatim, with no path appended.
The URLs may live at different hosts, bases, or paths; they are treated
as opaque endpoints. They can also be one URL: every request JWT carries
a top-level typ (authorize, capture, release, or
credit-account) to route on. Paths in the API reference
(authorize,
capture,
release,
credit account)
are illustrative only. Register CreditURL before go-live if you
collect on requests; it isn’t called until requests are enabled for
your program. (Card-funded programs skip all four: an OCT to the
requester’s FI-issued card credits them instead.)
There is no API for URL registration: send the URLs to your Moov integration contact, who configures them for your program. Changing a URL later goes through the same channel.
Exchange signing secrets #
Request and response bodies are encrypted JWEs. The wrapping key is a raw 32-byte secret issued via the Moov Money API. Authenticate with your Moov API key (Dashboard → Developers → API keys) as HTTP Basic auth:
curl -X POST "https://api.moov.money/providers/$PROVIDER_ID/signing-secrets" \
-u "$MOOV_API_KEY_ID:$MOOV_API_KEY_SECRET" \
-H "X-Moov-Version: v2026.10.00" \
-H "X-Idempotency-Key: $(uuidgen)"
X-Idempotency-Key is required; without it the call returns 400. The
201 nests the secret under signingSecret:
{
"signingSecret": {
"secretID": "sec_01HF5J9ZKQT4RXP8M2VYBN3D",
"createdOn": "2026-08-31T12:00:00Z",
"revokedOn": null,
"secret": "c2VjcmV0LXZhbHVlLWZvci1leGFtcGxlLW9ubHk"
}
}
Replaying the same key within 24 hours returns 409
(idempotency-key-reused) and never repeats the plaintext. If your first
call timed out before you stored the secret, create a new one with a new
key and revoke the orphan.
Field-by-field: create signing secret.
See sender authentication for more on this credential. It’s the same API key used to register senders and mint their access tokens.
The secret is returned exactly once, base64url-encoded without padding
(RFC 4648 §5). Decode it to recover the raw 32-byte AES key and store it in
your secrets manager. It cannot be retrieved again, only rotated.
To rotate, create a new secret, deploy it, then revoke the old one (list, revoke). More than one secret can be active at once. Moov encrypts requests with the newest active secret and decrypts your response with any active one, so accept either key until the old one is revoked. A revoked secret stops working immediately.
The cryptographic parameters, both directions:
- Key management:
A256KW(AES-256 key wrap) - Content encryption:
A256GCM - JWE header:
{"alg":"A256KW","enc":"A256GCM","typ":"JWT","cty":"JWT"} - The inner payload is a JWT with
iatandexpat the top level and all Moov claims under amoovobject
See Encryption for a worked example of decrypting a request and encrypting a response.
Confirm the transport shape #
Each endpoint accepts HTTPS POST with Content-Type: application/json.
The request body is a JSON object with a single request field carrying the
compact-serialized JWE; your response is a JSON object with a single
response field carrying the JWE reply:
// Request from Moov Money
{ "request": "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2R0NNIiwidHlwIjoiSldUIiwiY3R5IjoiSldUIn0.…" }
// Your response
{ "response": "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2R0NNIiwidHlwIjoiSldUIiwiY3R5IjoiSldUIn0.…" }
All business fields (amounts, references, the idempotency key) travel inside the JWE claims, never in the outer JSON.
Next steps #
- Encryption: implement the JWE handling.
- Ledger endpoints: outcomes and semantics.
- Idempotency and retries: the guarantees your ledger must uphold.