Endorsements
How endorsements gate what a customer can do, and how to request new ones.
Every instrument and every movement type is gated by an endorsement. The sequence is always the same:
- Request the endorsement you need.
- Wait for it to reach
APPROVED. - Call the endpoint it unlocks.
Calling the endpoint first returns endorsement_not_enabled. Check the endorsement before you call rather than relying on the error.
Reading them
GET /v1/customers/{customerId}/endorsements
Every entry has two gates, and both have to clear before anything provisions.
endorsement_status is Alfred's own product and rail eligibility.
| Value | What it means for the instrument |
|---|---|
INCOMPLETE | The instrument is not usable and nothing provisions. |
APPROVED | The instrument is usable and the endpoint will now succeed. |
PAUSED | The endorsement is withdrawn temporarily. Existing instruments stop accepting new movement, and balances are unaffected. |
REVOKED | The endorsement is withdrawn permanently. Requesting it again creates a new endorsement instead of resuming this one. |
provider_endorsements[] is the provider-side approval, which Alfred doesn't control.
Approved and still waiting
A customer can read APPROVED on our side and still not provision, because a provider endorsement is outstanding.
That shows up as reason_code: provider_processing with next_action: none. Neither the customer nor you has anything to do, and Alfred is not the party holding it up. Keep listening for the webhook until the provider responds.
This is worth handling explicitly in your UI, because "approved but nothing happened" reads like a bug otherwise.
Requesting one
POST /v1/customers/{customerId}/endorsements
{ "endorsement": "fiat_collection" }The customer has to be ACTIVE. If it isn't, the endorsement stays at INCOMPLETE indefinitely.
For fiat_collection the request itself triggers provisioning. You don't create the instrument first and then ask for permission.
Wait on customer.endorsement.updated reaching APPROVED.
The catalog
| Endorsement | Unlocks |
|---|---|
fiat_collection | Receiving local currency into a virtual account |
stablecoin_payin | Receiving stablecoin to a deposit address |
stablecoin_balance | Holding a stablecoin balance |
fiat_payout.cross_border | Paying out to a bank account in another country |
stablecoin_payout.third_party | Paying out to a wallet that isn't the customer's own |
corporate_usd_account | Opening a Corporate USD Account |
local_stablecoin.MXNa | Holding MXNa in Mexico |
local_stablecoin.ARSa | Holding ARSa in Argentina |
local_stablecoin.COPa | Holding COPa in Colombia |
local_stablecoin.BRZ | Holding BRZ in Brazil |
Local stablecoin endorsements are granted per asset because eligibility is decided per jurisdiction. Approval for MXNa does not imply approval for BRZ.
Pauses and revocations
PAUSED and REVOKED arrive on customer.endorsement.updated with no other warning. They stop new movement on instruments that were working the day before.
Many integrations only handle INCOMPLETE moving to APPROVED. If yours does that, the first time an endorsement is withdrawn payments will start failing with no visible explanation. Handle all four values.
Updated 5 days ago

