> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orderprotection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Partner Integration Quickstart

> End-to-end walkthrough for partners building on top of OrderProtection — authenticate, create A/B cohorts with their own pricing and widget appearance, and point OrderProtection's widget at them.

This guide is for **partners who run experimentation or checkout optimization on a merchant's store** — for example, an A/B-testing platform that wants protection pricing and presentation to vary per test cohort.

<Warning>
  OrderProtection **always renders the protection offer through its own surfaces** — in Shopify checkout, that's the OrderProtection `checkout-widget` extension. Partners do not build their own protection UI. What you get instead is full configuration control: everything the widget renders (copy, styling, pricing, auto-select behavior, geo rules) is driven by the cohort configs you create through this API.
</Warning>

By the end you'll be able to:

1. Authenticate against the OrderProtection API.
2. Create A/B-test cohorts ("variants"), each with its own pricing and widget appearance.
3. Point OrderProtection's checkout extension at a cohort per checkout.
4. Consume order and claim events as they happen.

<Note>
  If you're a merchant integrating OrderProtection directly into your own storefront, see the [API integration guide](/guides/how-api-integration-works) instead. This page is specifically for **third-party partners** building on top of OrderProtection.
</Note>

## How it fits together

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant Partner as Partner backend
    participant OP as OrderProtection API
    participant Ext as OP checkout extension
    participant Shopper as Shopper (in checkout)

    Note over Partner,OP: One-time setup (per store)
    Partner->>OP: POST /v1/oauth/token (client_credentials + store_id)
    OP-->>Partner: access_token (op_at_...)
    Partner->>OP: POST /v2/settings/context {name}
    OP-->>Partner: context created (id)
    Partner->>OP: POST .../context/:id/pricing (variantKey "cohort-a")
    Partner->>OP: POST /v2/widget/context/:id/config (variantKey "cohort-a")
    Note over Ext: Block settings bind each checkout to a cohort<br/>(Application ID + variant keys)

    Note over Shopper,Ext: Per-shopper render
    Shopper->>Ext: Loads checkout
    Ext->>OP: GET /v2/quote/insurance/partner/:appId?key=cohort-a
    Ext->>OP: GET /v2/widget/config/partner/:appId?key=cohort-a
    OP-->>Ext: Cohort pricing + widget config
    Ext-->>Shopper: Renders the protection offer

    Note over Partner,OP: Post-purchase
    OP->>Partner: webhook: protection/added, claim/created
    Partner->>OP: GET /v1/orders/{id} (as needed)
```

## Step 1 — Register your OAuth app

Create an app in the OrderProtection dashboard and capture the `client_id` and `client_secret`. See [Creating an app](/developer/creating-an-app) for the full walkthrough.

When you declare scopes, request at minimum:

* `store:read` — read merchant settings and list your contexts
* `partner-context:update` — create and update your partner contexts, cohort price sets, and cohort widget configs
* `quote:read` — call `POST /v2/quote`
* `widget:checkout:read` / `widget:checkout:update` — read and write checkout widget configs
* `pricing:shipping-insurance:read` / `pricing:shipping-insurance:update` — read and write cohort pricing

Add `order:read` / `claim:read` if you consume order and claim data. See the [Scopes reference](/developer/scopes) for the full list.

<Warning>
  The `pricing:*` scopes are **admin-gated** — requesting them routes your app (even a private one) through OrderProtection review, and it **cannot be installed or mint tokens until approved**. For a quick test app, either omit the `pricing:*` scopes and add them later, or ask your OrderProtection contact to approve the app right after you create it. `403 "App is not installed on this store"` on the token endpoint is the usual symptom of an app stuck in review or not yet installed.
</Warning>

## Step 2 — Get an access token

Partners authenticate machine-to-machine with the [client credentials flow](/developer/authentication#client-credentials-flow): your app must be **installed on the target store** first — see [Installing Your App](/developer/installing-your-app) for both install paths (marketplace UI and the automatable install API) — and you mint one token per store.

```bash theme={null}
curl -X POST https://api.production.orderprotection.com/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "op_app_...",
    "client_secret": "op_secret_...",
    "store_id": "<store id>"
  }'
```

From here, every API call uses:

```bash theme={null}
Authorization: Bearer op_at_...
```

## Step 3 — Create your partner context

A **partner context** is your installation's container on a store — one per (store, app) pair. Your A/B cohorts hang off it (Steps 4 and 5), keyed by a `variantKey` you choose. The context also holds optional sparse overrides on the merchant's default settings: anything you don't override is inherited.

```bash theme={null}
curl -X POST https://api.production.orderprotection.com/v2/settings/context \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "My Platform"}'
```

Authenticated `/v2` responses are wrapped in a standard envelope — the new context's `id` is at `data.id`. You'll use it in Steps 4 and 5. Creating a second context on the same store returns `409 Conflict` — fetch the existing one with `GET /v2/settings/context`. See [Partner contexts](/developer/endpoints#partner-contexts) for the full CRUD reference.

## Step 4 — Create a price set per cohort

Each cohort gets its own pricing, keyed by your `variantKey`:

```bash theme={null}
curl -X POST https://api.production.orderprotection.com/v2/settings/context/{contextId}/pricing \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "SHIPPING",
    "variantKey": "cohort-a",
    "automaticallyAddToCart": true,
    "rules": [
      { "min": 0,   "max": 100,     "terms": { "customer": { "amount": 0.99, "type": "fixed" } } },
      { "min": 101, "max": 1000000, "terms": { "customer": { "amount": 3,    "type": "percentage" } } }
    ]
  }'
```

* `variantKey` must match `^[a-zA-Z0-9_.:-]{1,64}$` and is **immutable** — to repoint a cohort, delete the rule set and create a new one.
* One rule set per `(variantKey, type)`. `min`/`max` are cart-subtotal bounds; `terms.customer`/`terms.brand` take `{"amount", "type"}` where `type` is `fixed` or `percentage`.
* On the header-based v1 read path, a cohort with no partner price set falls back to the merchant's default pricing. The path-based partner endpoints the checkout extension uses return `404` instead — the extension treats that as "no cohort" and renders the store default.

<Tip>
  Setting `"noOp": true` on a rule set keeps the cohort resolvable but tells the renderer to stand down — the checkout extension hides the protection offer and removes any protection line for that cohort. Use it as a control arm or to pause a cohort without deleting it. See [Cohort pricing](/developer/endpoints#cohort-pricing) for the full reference.
</Tip>

## Step 5 — Create a widget config per cohort

The widget config controls what the checkout extension renders for the cohort — copy, styling, and layout:

```bash theme={null}
curl -X POST https://api.production.orderprotection.com/v2/widget/context/{contextId}/config \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{
    "variantKey": "cohort-a",
    "type": "CHECKOUT",
    "status": "ACTIVE",
    "name": "Cohort A",
    "config": {
      "isV2": true,
      "titleText": "Package Protection",
      "titleTextBold": true,
      "infoText": "Protect your order against loss, theft, or damage in transit.",
      "showDisclaimerText": true,
      "disclaimerTextOn": "Your order is protected.",
      "disclaimerTextOff": "Your order will not be protected.",
      "backgroundColor": "#FFFFFF",
      "showBorder": true,
      "borderStyle": "solid",
      "borderWidth": "1",
      "borderRadius": "8"
    }
  }'
```

* As with pricing: one config per `(variantKey, type)`, and `variantKey`/`type` are immutable after create.
* `config` is validated against a strict schema — unknown fields are rejected with `400`. See [Cohort widget configs](/developer/endpoints#cohort-widget-configs) for the field reference.
* Write your configuration to `config` only. Responses also include `customizationValues`, a read-only legacy mirror of `config` — don't send it back.

## Step 6 — Point each checkout at a cohort

Rendering is done by OrderProtection's `checkout-widget` extension, which is installed on the merchant's store by OrderProtection. There are two ways to bind a checkout to a cohort — both start from the **Application ID** block setting in the Shopify checkout editor (your OAuth `Application.id`, a cuid like `cmpn5in6p000484flmfk9ns4d` — not your `op_app_...` client\_id):

* **Static** — fill the **Price Set Variant Key** and **Widget Config Variant Key** block settings with the `variantKey`s from Steps 4 and 5. Every session on that checkout gets that cohort. The two keys are independent, so you can pin pricing and appearance separately. Good for debugging a cohort; per-cohort testing this way means switching block settings or checkout profiles.
* **Runtime** — leave both variant-key fields **empty** and have your own checkout extension write the cohort per session via two cart attributes, `_op_price_variant` and `_op_widget_variant`, once your allocation runs. The widget renders nothing until they arrive, then fetches and renders that cohort — and since cart attributes become note attributes on the resulting order, the cohort keys show up in order payloads and webhooks for your per-order test attribution. The widget also reports back per session via `_op_rendered` / `_op_not_rendered_reason`, so you can verify each impression landed. This is the mode built for mid-session A/B allocation. Full contract: [Runtime cohort binding](/developer/checkout-extension#runtime-cohort-binding-cart-attributes) and the [impression signal](/developer/checkout-extension#impression-signal-write-back).

## Step 7 — Verify a cohort

The same public endpoints the extension calls are handy for verifying what a cohort resolves to — no auth required:

```bash theme={null}
curl -G https://api.production.orderprotection.com/v2/quote/insurance/partner/{applicationId} \
  --data-urlencode "key=cohort-a" \
  --data-urlencode "store_url=example.myshopify.com" \
  --data-urlencode "country=US"

curl -G https://api.production.orderprotection.com/v2/widget/config/partner/{applicationId} \
  --data-urlencode "key=cohort-a" \
  --data-urlencode "store_url=example.myshopify.com"
```

Responses are cached for about an hour, but writes through the partner API invalidate the cache immediately.

For a server-side price check on an arbitrary cart, use the stateless [`POST /v2/quote`](/developer/endpoints#quote):

```bash theme={null}
curl -X POST https://api.production.orderprotection.com/v2/quote \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{"orderTotal": 49.99, "policyType": "SHIPPING"}'
```

## Step 8 — Consume order and claim events

When a shopper buys protection on the merchant's storefront, the order flows into OrderProtection through the merchant's existing platform integration (Shopify, BigCommerce, etc.). **You do not push orders to OrderProtection** — we already have them.

To stay in sync, you can either:

* **Read on demand** via the v1 [Orders](/api-reference/orders/get-all-orders) and [Claims](/api-reference/claims/get-claims) APIs (requires `order:read` / `claim:read`).
* **Subscribe to webhooks** — `protection/added`, `protection/removed`, `claim/created`, `claim/approved`, `claim/denied`, `message/created`. See [Webhooks](/developer/webhooks) and the [event reference](/webhooks/introduction).

<Note>
  Order data is owned by the merchant. Your access depends on the merchant having installed your app and granted the relevant scopes — there is no way to read orders for a store that hasn't installed you.
</Note>

## Testing

* **The OrderProtection Shopify app is not in the Shopify App Store.** It's distributed as a custom app per store — OrderProtection creates, deploys, and sends an install link for each store, including partner dev stores. Contact your OrderProtection engineering contact to get the extension provisioned on a development store.
* **There is no partner-facing staging environment.** The deployed extension talks to the production API, so the test path is a development store against production — isolated to that store's data.
* Once provisioned, the [verification endpoints](#step-7-verify-a-cohort) above let you confirm cohort resolution before touching a checkout.

## Where to go next

<CardGroup cols={2}>
  <Card title="Checkout Extension" icon="cart-shopping" href="/developer/checkout-extension">
    Wire the extension's block settings to your cohorts and see exactly what it fetches.
  </Card>

  <Card title="Partner endpoints reference" icon="key" href="/developer/endpoints">
    Full schema reference for every `/v2` partner endpoint, including request/response shapes and scope requirements.
  </Card>

  <Card title="Authentication" icon="lock" href="/developer/authentication">
    OAuth flows, client credentials, and refresh tokens.
  </Card>

  <Card title="Scopes" icon="shield-halved" href="/developer/scopes">
    Full list of scopes, including admin-gated pricing scopes.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.