Vaulting API

Everything you need to integrate your inventory and fulfillment with the CardOS warehouse. Every raw card you intake gets a unique_id; from there you can sweep your inventory, quote and commit shipments, transfer custody without a shipment, withdraw cards, submit declared values, and reconcile invoices, SLA metrics, exceptions and service credits — each endpoint with the exact request and response shapes, so you can build against it with confidence.

Quickstart

Your account manager issues an X-API-Key bound to your account. From there it's four calls to a shipped order:

# 1. Verify your key.
curl https://api.getcardos.com/api/v1/info \
  -H "X-API-Key: $RIP_API_KEY"

# 2. List your inventory.
curl "https://api.getcardos.com/api/v1/cards?limit=5" \
  -H "X-API-Key: $RIP_API_KEY"

# 3. Ship your first order: quote rates, pick one, commit.
#    An order can carry one card or many — unique_ids is always an array.
curl -X POST https://api.getcardos.com/api/v1/shipping-quote \
  -H "X-API-Key: $RIP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "unique_ids": ["CARD-RIP…"], "address": { … } }'

# 4. Commit with one of the returned rate_ids. This purchases the
#    shipping label — expect it to take a few seconds.
curl -X POST https://api.getcardos.com/api/v1/orders \
  -H "X-API-Key: $RIP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "order_id": 123, "rate_id": "rate_abc" }'

Base URLs

EnvironmentOriginNotes
Sandbox (staging)https://staging-service.rip.funWhat the "Try it" runners in these docs call
Productionhttps://api.getcardos.com

All endpoints live under the /api/v1 base path. Every request except GET /health must include an X-API-Key header — a tenant-scoped key, not a mystery-partner key. A non-tenant key (or a key missing a required scope) returns 403. The demo key wired into the "Try it" runners is a mystery key, so paste your own tenant key in the sidebar to run anything here.

Scopes

RequirementEndpoints
Tenant key, no extra scopeshipping-quote, orders (create / list / get / cancel), cards (list / get)
Tenant key + read:inventorywithdrawals (list / get), card transfers, integration-status, declared-values (list), invoices, account, reports, exceptions, SLA, service-credits (list), activity log
Tenant key + write:transfertransfer card
Tenant key + write:withdrawalrequest withdrawal
Tenant key + write:declared_valuesubmit declared values
Tenant key + write:service_creditrequest service credit

Conventions

  • Response envelope. Every success is { "success": true, "data": … }. List endpoints place collections under named keys (data.orders, data.cards, data.invoices, …); some include a pagination sibling with { limit, offset, has_more }.
  • Errors. Error responses carry success: false, a short message and a human-readable error. Do not parse error strings — branch on the status code and, where present, code. Several 409 conflicts also carry data with the conflicting resource's current state. 429 / 503 come from shared infrastructure and swap the roles (error holds a fixed label); treat both the same way — back off and retry.
  • Idempotency. The three write endpoints (transfer, withdrawal, declared values) accept an idempotency token (idempotency_key / submission_key, max 128 chars) — a replay returns the original record with the same 201, not a 409. Use them on every write. Orders are safe differently: re-quoting supersedes your own uncommitted quote, and commit retries are always safe because every failure leaves the order in PENDING_PAYMENT with nothing applied.
  • Dates and amounts. All timestamps are ISO 8601 strings in UTC; all monetary amounts are integer cents (or basis points where noted) — never floats. Business-day math (ship_by_at, sla_due_at) runs on warehouse local time (US Central), though the returned values are still UTC timestamps.
  • The card unique_id. Every raw card is assigned an identifier prefixed CARD-RIP, up to 22 characters. Treat it as an opaque string — it is the canonical identifier across the entire API and never changes. Graded slabs are out of scope for v1 and are not returned or accepted by any endpoint here.
  • Rate limits. 60 requests / minute per API key (fixed window; /health exempt), with X-RateLimit-* headers on every response and a Retry-After on 429. Reads additionally share a 20-request concurrency pool — exhausting it returns 503.

What happens after a write

  • Activity log. Transfers, withdrawal requests and declared-value submissions are recorded to the activity log. Order activity is not in that feed — poll GET /orders/:id for fulfillment and tracking state.
  • Integration issues. If any tenant write fails unexpectedly (a 500), an integration issue is opened automatically and surfaces at GET /integration-status, tracked against the response window in your agreement. You don't need to report these.
  • Email notifications. Declared-value submissions and decisions, exception notices and scheduled-maintenance windows are emailed to the notice address on your account (readable at GET /account).

Recommended patterns

  • Sweep inventory with ?since, not ?offset. Keyset pagination is drift-free under concurrent inserts and isn't bounded by the 10,000-row offset cap.
  • Send an idempotency token on every write. Network timeouts are indistinguishable from failures; a token is what makes the retry safe.
  • Read rates from GET /account rather than hardcoding them. Fees and thresholds are per-account and may be adjusted under your agreement.
  • Drain the activity feed before rotating a key. The log is scoped to the API key that made each write, so a new key starts with an empty history.
  • Trust our timestamps over the client clock (sla_due_at, generated_at, computed_at); business-day deadlines are derived on warehouse local time.

Endpoints

Support

For integration questions or anything in this reference, contact your account manager or email support@rip.fun. For legal or contract questions, copy legal@rip.fun.