Quickstart

Go from zero to your first protected purchase. This guide takes you from minting API keys to a confirmed protection plan you can see in your dashboard — either by embedding the browser widget or by calling the REST API directly.

Document marker: CLAIMFUL_QUICKSTART_SENTINEL

Every request in this guide runs against the base URL https://api.claimful.ai/api/v1.

1. Get your API keys

Sign in to your merchant dashboard and open Account → API Keys (/merchant/api-keys). Generate a key and copy the secret — it is shown once and never re-displayed.

Two independent key families exist, and each is minted separately for test and live environments:

| Key | Prefix | Where it runs | Purpose | | --- | --- | --- | --- | | Publishable | wk_test_… / wk_live_… | Browser (public) | Authenticates the embedded widget's quote/confirm/decline calls. Safe to ship in page HTML. | | Secret | mch_test_… / mch_live_… | Your server only | Authenticates server-side REST calls. Never send a mch_ key from the browser. |

Start in test mode: a wk_test_ / mch_test_ pair keeps every quote and protected purchase isolated from live traffic. Swap the test keys for live keys — and nothing else — when you go to production.

2. Embed the widget (or make your first REST quote)

Pick the path that matches your integration. Storefronts embed the declarative widget; headless and server-to-server integrations call REST.

Option A — Embed the widget

Paste this snippet into your checkout page, just before the closing </body> tag. Both data-merchant-id and data-publishable-key are required — a missing publishable key hides the widget rather than blocking checkout.

<script src="https://widget.claimful.ai/v1.20260601/widget.js"
        integrity="sha384-KVy7W+9O0dxQuL9JTLt1f6/zgffj5mVJNVxIwO+99d3c7SeRQub1ExDBLpXmsOtI" crossorigin="anonymous" async></script>
<claimful-widget
  data-merchant-id="YOUR_MERCHANT_ID"
  data-publishable-key="wk_test_xxxxxxxx.yyyyyyyy"
  data-order-amount-cents="20000"
></claimful-widget>

Replace YOUR_MERCHANT_ID and the wk_test_… publishable key with the values from your dashboard, and swap the integrity hash for the published SRI hash of your pinned widget version (ADR 0031). The widget fetches the offer, renders the protection option, and dispatches the five lifecycle events documented in Widget Events. Skip to step 4 to verify the result.

Option B — Request a quote over REST

Send a secret mch_ key as a bearer token. The offer endpoint takes a snake_case body and requires an Idempotency-Key header (any stable ^[A-Za-z0-9_-]{16,255}$ string — a UUID works):

curl -sS https://api.claimful.ai/api/v1/offers/quote \
  -H "Authorization: Bearer mch_test_xxxxxxxx.yyyyyyyy" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "order_amount_cents": 20000,
    "order_id": "order_1234"
  }'

order_amount_cents is the only required field. Omit protection_program_id to use your default active program, or pass its UUID to pin a specific one.

The response body is camelCase, and the raw quote token comes back in the X-Claimful-Quote-Token response header — never in the JSON body (ADR 0038):

HTTP/1.1 201 Created
X-Claimful-Quote-Token: 4f3c…64-hex-chars

{
  "quoteId": "q_0R4X…",
  "fee": 1200,
  "currency": "USD",
  "freeLookDays": 2,
  "reasons": ["…"],
  "expiresAt": "2026-07-07T12:15:00+00:00"
}

Capture both quoteId (from the body) and the X-Claimful-Quote-Token header — you need them to confirm.

3. Confirm the protection plan

When the customer opts in, confirm the quote. The outer credential fields stay camelCase (quoteId, quoteToken), but every confirm request now also requires a versioned, snake_case order_context object describing the binding order (merchant order id, purchase time, covered amount/currency, and the event/participant facts a later claim needs). A missing or malformed order_context fails closed with a 422 order_context_invalid response before any protection is created.

curl -sS https://api.claimful.ai/api/v1/offers/confirm \
  -H "Authorization: Bearer mch_test_xxxxxxxx.yyyyyyyy" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "quoteId": "q_0R4X…",
    "quoteToken": "4f3c…value from the X-Claimful-Quote-Token header",
    "order_context": {
      "schema_version": "2026-07-01",
      "order": {
        "id": "order_8842",
        "purchased_at": "2026-07-10T14:18:00Z",
        "currency": "USD",
        "covered_amount_cents": 84200
      },
      "participants": { "mode": "unnamed" }
    }
  }'

The official SDKs pass the confirm payload through verbatim, so the same order_context field applies there:

$client->offers->confirm([
    'quoteId' => $offer['quoteId'],
    'quoteToken' => '<value from X-Claimful-Quote-Token header>',
    'order_context' => [
        'schema_version' => '2026-07-01',
        'order' => [
            'id' => 'order_8842',
            'purchased_at' => '2026-07-10T14:18:00Z',
            'currency' => 'USD',
            'covered_amount_cents' => 84200,
        ],
        'participants' => ['mode' => 'unnamed'],
    ],
], idempotencyKey: bin2hex(random_bytes(16)));

A successful confirm returns the frozen response envelope: protected_purchase_id, reference_number, status, protection_fee_cents, covered_amount_cents, currency, free_look_ends_at, filing_deadline_at, and — on a fresh live confirm only — customer_access_url.

A successful confirm returns your protection reference number in CLM-YYYY-XXXXXXXX format — include it in your order confirmation email (see the PHP / TypeScript SDK references, §"Confirmation email requirements").

4. See it in your dashboard

Back in your merchant dashboard, the new protected purchase appears in your Activity feed. Because you confirmed with a test key, it is stamped as a test-mode purchase and stays separate from live traffic — so you can rehearse the whole flow before flipping to live keys.

If nothing shows up, the usual culprits are: a wk_/mch_ key from the wrong environment, a snake_case confirm body (step 3), or a missing Idempotency-Key header.

5. Set up webhooks

Once the flow works, wire webhooks so your systems react to protection and refund events without polling. Register an endpoint under Account → Webhooks (/merchant/webhooks); the signing secret is revealed once at creation.

Every delivery is signed with an X-Claimful-Signature: t=<unix>,v1=<hex> header over the {timestamp}.{body} preimage, with a 300-second replay window (ADR 0009 §5). Verify it with the SDK helper rather than hand-rolling HMAC:

Next steps