End-to-end flows

The three multi-party sequences in the API — who calls what, who signs what, and which webhooks fire. Every step links to the endpoint page where you can run it live.

1. Non-custodial purchase

The end-user pays from their own wallet; rip.fun never touches their funds.

Trying this on the sandbox? Fund your test wallet first — see Get testnet funds (Base Sepolia).

  1. Partner: POST /mystery/purchase/prepare with the user's wallet_address + tier_id → unsigned USDC-approve + purchase calldata (calls[]). Creates no rows.
  2. End user: signs + broadcasts calls[0] (USDC approve — skippable if the allowance already suffices) then calls[1] (purchase) from their own wallet.
  3. Partner: POST /mystery/purchase/submit with the tx hash (+ the VRF request_id decoded from the receipt logs) so settlement can link the reveal.
  4. rip.fun: VRF reveals the items. Poll GET /mystery/purchase/:id until FULFILLED, or consume the purchase.fulfilled webhook. The revealed NFTs belong to the user's wallet.

The custodial variant collapses steps 1–3 into a single POST /mystery/purchase (credits debited, a rip.fun relayer signs; Idempotency-Key required).

2. Physical redemption

Ship a revealed card to the end-user. The burn is signed by the user (same prepare → sign → submit pattern as the purchase), and the NFT only finalizes its burn when the item is physically dispatched — "burn on dispatch".

  1. Partner (optional): POST /mystery/redemption/quote at checkout to show the live shipping cost. Creates no rows.
  2. Partner: POST /mystery/redemption/prepare with the shipping address (+ idempotency_key) — validates the address, snapshots the cheapest rate, runs KYC.
  3. If KYC is required: send the end user to kyc.kyc_url (Veriff), then re-call prepare with the same key once approved to receive the calldata.
  4. End user: signs + broadcasts unsigned.calls (initiateBurn) from the wallet holding the NFT.
  5. Partner: POST /mystery/redemption/submit with { redemption_id, tx_hash }BURN_SUBMITTED.
  6. rip.fun: the warehouse ships the item. Track via GET /mystery/redemption/:purchase_id or redemption.updated webhooks: IN_FULFILLMENTCOMPLETED, with the burn finalizing on dispatch.

3. Buyback → pool wallet → monthly billing

Offer the end-user instant liquidity on a pull; the bought-back NFT is forwarded to your pool wallet and the USDC rip.fun fronted is invoiced to you monthly.

  1. Partner: POST /mystery/buyback/:purchase_id — rip.fun system-signs a marketplace offer (default 85% of card value; check the would-be price first with GET /mystery/price). The path segment accepts a purchase id or an on-chain token id, so you can buy back any rip.fun card by token id even if the pull didn't happen through this API.
  2. End user (holder): accepts the offer from their wallet on the marketplace and receives USDC net of the marketplace fee → buyback.confirmed webhook.
  3. rip.fun: a worker forwards the NFT to your active pool walletbuyback.card_transferred webhook. If no pool wallet is set you get a one-time buyback.transfer_held and the transfer retries every 15 minutes until you PUT /mystery/pool-wallet; after 10 failed attempts it goes terminal with buyback.transfer_failed.
  4. Billing: the USDC rip.fun fronted to the holder is invoiced to you monthly — whether or not the NFT transfer succeeded. Your offer volume shows up in GET /mystery/stats.