Redeem to a bank account
A redeem turns tokens in a holder's wallet into fiat paid to the organisation's registered bank account. The organisation creates the redeem, which returns deposit instructions: a muxed address, the exact token amount, and an expiry. The holder's wallet then sends that amount to that address. The platform attributes the payment, burns the tokens and pays out.
Every request below except the payment runs in CI against an in-process core on FakeChain, so a response that stops matching its # expect line fails the build. The payment is the one step a wallet must sign, so it is shown as prose.
Register and prove the wallet
Create the source wallet and prove control of it, as in the mint guide.
POST /v1/counterparties
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"type": "stellar_wallet",
"address": "{{WALLET_ADDRESS}}",
"label": "redeem guide"
}
# expect 201
# save CPTY = $.id
# save CHALLENGE = $.ownership_proof.challenge_xdr
# sign SIGNED_CHALLENGE = CHALLENGE
POST /v1/counterparties/{{CPTY}}/ownership-proof
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"signed_challenge_xdr": "{{SIGNED_CHALLENGE}}"
}
# expect 200
Register the bank account
Create a bank_account counterparty with POST /v1/counterparties. Its currency must match the asset's denomination, because the payout is in that currency.
POST /v1/counterparties
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"type": "bank_account",
"label": "Redeem account",
"beneficiary_name": "Acme Testnet Ltd",
"bank_name": "Testnet mock bank",
"account_number": "GB00TEST12345678",
"routing_code": "TEST0001",
"currency": "USD"
}
# expect 201
# save BANK = $.id
Create the redeem
POST /v1/transfers creates a redeem when source.type is stellar and the destination is a bank account. The response's deposit_instructions carries the muxed address to pay, the exact amount, and an expiry.
POST /v1/transfers
authorization: Bearer {{KEY}}
idempotency-key: {{uuid}}
content-type: application/json
{
"source": { "type": "stellar", "asset": "USDX", "counterparty_id": "{{CPTY}}" },
"destination": { "type": "fiat", "currency": "USD", "rail": "wire", "counterparty_id": "{{BANK}}" },
"amount": "25.00"
}
# expect 201
# save TRANSFER = $.id
# save MUXED = $.deposit_instructions.muxed_address
# save PAY_AMOUNT = $.deposit_instructions.amount
Read it back with GET /v1/transfers/{id}. It waits in awaiting_funds until the tokens arrive.
GET /v1/transfers/{{TRANSFER}}
authorization: Bearer {{KEY}}
# expect 200
Send the payment
This step belongs to the holder's wallet, so it is not run in CI: from the wallet, send exactly {{PAY_AMOUNT}} of the asset to the muxed address {{MUXED}} before the instructions expire. Pay the exact amount from the registered source address in one payment. The platform attributes a matching payment to this redeem, then burns the tokens and pays out to the bank account. A payment that is short, late or from another address goes to suspense instead of completing the redeem.