Send a prize

POST /api/v1/sends sends:create

You hold prize inventory with CardOS — a specific card set aside for first place, a shelf of pre-opened prizes for everyone who paid to enter. A send delivers one of those to a wallet. The prize is HELD, never fulfilled for you: the token lands in the winner's wallet and stops there, and redeeming it for the physical item is their decision, later. Returns 202 — delivery is one or more on-chain transactions and is asynchronous; take send.fulfilled / send.failed or poll GET /sends/:send_id. Whether an item is minted to the winner or transferred from the CardOS server wallet is decided per item, not requested.

A sealed product (CONTAINER) is TRANSFER-only. Minting a container needs a registered on-chain product type and a warehouse serial, which is an intake operation — a container that is not already minted comes back in skipped[] as container_not_minted rather than being silently minted.

buyback_eligible is not a database flag. The sell-back contract allows a sale only when the on-chain window names the seller, and a transferred prize's window still names whoever the card was first distributed to — so CardOS re-opens the window on chain. A sealed product records unsupported_asset_type (containers have no sell-back window), and a card with no price group records no_oracle_group. If buyback_registered_at is null, that item cannot be sold back.

If EVERY item is skipped the call is 409 no_sendable_items and your Idempotency-Key is NOT burned — fix the list and retry with the same key.

Try it POST /api/v1/sends money

These inputs are shared across all docs pages, so an id entered here carries over.

request body
object · 3 keys
{
  "wallet_address": "0x0000000000000000000000000000000000000000",
  "items": [
    {
      "unique_id": "CARD-EXAMPLE-1"
    }
  ],
  "reference": "docs-example"
}
response

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 (tracks the inputs above)
curl -X POST 'https://service.rip.fun/api/v1/sends' \
  -H 'X-API-Key: rip_…' \
  -H 'Idempotency-Key: 0fd76539-86ba-41ab-9658-458a417f042f' \
  -H 'Content-Type: application/json' \
  -d '{"wallet_address":"0x0000000000000000000000000000000000000000","items":[{"unique_id":"CARD-EXAMPLE-1"}],"reference":"docs-example"}'

Request fields

FieldTypeRequiredDescription
Idempotency-KeyheaderyesYour unique id for this prize — replays return the original send instead of sending it twice
wallet_addressstringyesThe winner's wallet. The prize is minted or transferred to it and stays there
itemsarrayyesOne to fifty assets, each by ONE id: { "unique_id": "CARD-…" | "GRADED-…" | "SEALED-…" } or { "container_token_id": "777" } for a sealed product named by its on-chain id. A bare string is treated as a unique_id
referencestringYour own handle for the send (a tournament id, a placement), ≤255 chars, echoed back on reads and in the webhooks
metadataobjectOpaque to CardOS; returned unchanged
buyback_eligiblebooleanRe-open the on-chain sell-back window in the WINNER's name once each item lands. Without it a transferred prize cannot be sold back — see the notes

Response fields (data)

FieldDescription
send_id / statusThe send, and in_progress → complete | complete_with_errors
items[]Per item: unique_id, asset_type (CARD | GRADED | CONTAINER), action (MINT | TRANSFER — decided, not requested), status (PENDING → SENDING → SENT | FAILED), token_id, contract_address, tx_hash, error
items[].buyback_registered_at / buyback_errorWhether the sell-back window was re-opened in the winner's name, or why not
skipped[]Assets refused at the door with the reason (burned, listed, already_queued, not_held_by_server_wallet, container_not_minted) — never a silent drop
sent_count / failed_count / item_countTotals, filled in as the send lands

Errors

StatusCodeWhen
400missing_idempotency_keyno Idempotency-Key header (or idempotency_key body field)
400invalid_wallet_addresswallet_address missing or not an address
400no_items / too_many_itemsitems empty, or more than 50
400invalid_iteman item carrying both ids, neither id, or a non-numeric container_token_id
404item_not_founda unique_id or container_token_id that is not a CardOS asset
409ambiguous_itema unique_id that matches more than one asset table
409idempotency_mismatchthe key was already used for a different wallet_address
409no_sendable_itemsevery item was skipped — the reasons are in the message; the key is not burned

See Errors for the response envelope and the full code list.

Flow

  1. Partner: POST /api/v1/sends with Idempotency-Key + wallet_address + items → 202, per-item PENDING
  2. rip.fun: mints or transfers each item on chain, and (when asked) re-opens the sell-back window in the winner's name
  3. Partner: take send.fulfilled — or send.failed, which also covers a PARTIAL send; read items[] to see which landed
  4. End user: holds the prize. GET /wallets/:address/holdings says whether it can be redeemed or sold back
  5. End user (later, optional): redeems it through POST /mystery/redemption/quote → prepare → submit