/api/v1/mystery/redemption/prepare cards:redeem Starts a physical redemption: stores the address, locks in the cheapest shipping rate, and returns the transactions the END USER sends from the wallet holding the card — the redemption flag plus the shipping payment (a USDC approve and a payShipping call locked to the quoted amount). The END USER pays shipping on-chain; you are never billed for it. The item ships only once that payment lands. The card isn’t burned until the item ships, so nothing leaves the wallet yet. Only the holder can send these (CardOS can’t do this one for them). Supply purchase_id OR token_id (token_id alone works for cards you distributed yourself). CardOS runs no KYC/AML, so screening your end user is your responsibility.
POST /api/v1/mystery/redemption/prepare money These inputs are shared across all docs pages, so an id entered here carries over.
{
"shipping_address": {
"name": "Demo Buyer",
"street1": "1 Market St",
"city": "San Francisco",
"state": "CA",
"zip": "94105",
"country": "US"
},
"idempotency_key": "demo-redeem-0-single"
}Not run yet. Press Run to make a live call against https://service.rip.fun (through this demo's server-side proxy; the API key never reaches the browser).
curl -X POST 'https://service.rip.fun/api/v1/mystery/redemption/prepare' \
-H 'X-API-Key: rip_…' \
-H 'Content-Type: application/json' \
-d '{"shipping_address":{"name":"Demo Buyer","street1":"1 Market St","city":"San Francisco","state":"CA","zip":"94105","country":"US"},"idempotency_key":"demo-redeem-0-single"}' | Field | Type | Required | Description |
|---|---|---|---|
purchase_id | number | — | The fulfilled purchase holding the item (supply this OR token_id) |
token_id | string | — | On-chain token id (token-first; supply this OR purchase_id; also disambiguates a multi-item purchase) |
item_type | string | — | "CARD" | "GRADED_CARD" | "PACKET" | "SEALED_PRODUCT", to disambiguate a token number that exists as more than one asset (raw Card #N vs GradedCard slab #N) |
idempotency_key | string | — | Replay-safe; an Idempotency-Key header is also accepted |
shipping_payer | string | — | "end_user" is the only valid value (and the default) — the holder pays the quoted shipping on-chain; partner-billed shipping is not offered |
shipping_address.name | string | yes | Recipient full name |
shipping_address.street1 | string | yes | Street line 1 (`street2` optional) |
shipping_address.city | string | yes | City |
shipping_address.state | string | — | State / region |
shipping_address.zip | string | yes | Postal code |
shipping_address.country | string | yes | ISO country code, e.g. `US` (`phone`, `email` optional) |
data)| Field | Description |
|---|---|
redemption_id / status | PREPARED, meaning the transaction is ready to send |
shipping_quote | Snapshotted cheapest rate (same shape as /quote) |
shipping_payer / shipping_payment | always "end_user" — the holder pays the quoted shipping on-chain (you are never billed). shipping_payment echoes the signed quote: payer, processor, total_usdc/micros, expiration_time, provider_order_id |
expires_at | how long the returned transactions (and the signed shipping quote) stay valid (default 24 h); EXPIRED is retryable with a new idempotency_key |
unsigned.chain_id / unsigned.calls[] | the transactions the END USER sends from the wallet holding the card, in order: kind "burn" (flags the card for redemption), "erc20-approve" (USDC → shipping processor; its own userop under account abstraction), "shipping-payment" (payShipping with the signed quote — must run after the burn). The card burns when the item ships |
| Status | Code | When |
|---|---|---|
| 400 | purchase_or_token_required | neither purchase_id nor token_id supplied |
| 409 | not_fulfilled | purchase path: purchase not revealed yet |
| 409 | not_burnable | token unindexed / burned / not in a redeemable state, or already queued |
| 409 | not_owner | token left the holder wallet, and the holder must be the burn signer |
| 404 | token_not_found | token-first: no CardOS item for that token |
| 409 | ambiguous_token | token-first: id is both a raw and a graded card, so pass item_type ("CARD" or "GRADED_CARD") or use purchase_id |
| 409 | item_type_mismatch | item_type contradicts what the token actually is |
| 409 | redemption_exists | re-preparing after the burn already started |
| 400 | invalid_address | Shippo cannot validate the address |
| 400 | invalid_shipping_payer | shipping_payer set to anything other than "end_user" |
| 503 | shipping_signer_unavailable | the shipping quote signer is temporarily unauthorized on-chain — retry later |
See Errors for the response envelope and the full code list.