Skip to main content

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.

This page lists every endpoint your app can call with an OAuth access token. Each entry includes the route, the scopes it requires, the request shape, and the response shape.
Routes documented here are versioned under /v2. The /v1 quote endpoint remains available for the public widget and is documented at the end of this page; everything else under /v1 is dashboard-only and not part of the partner surface.
All requests must include a Bearer access token from the OAuth flow:
Authorization: Bearer op_at_...

Base URL

https://api.production.orderprotection.com

At a glance

ResourceRoutesRequired scopes
Partner contextsPOST/GET/PATCH/DELETE /v2/settings/contextread_store, write_settings
Merchant settingsGET/PUT /v2/settingsread_store, write_settings (+ write_store_credit_settings for store-credit fields)
Pricing rulesGET /v2/pricing/rules, PUT /v2/pricing/rules/:idper ruleset type — see below
QuotePOST /v2/quoteread_quotes
Widget configGET /v2/widget/config, PUT /v2/widget/config/:idper widget type — see below
Public widget readGET /v1/quote/insurancenone (public; uses cohort headers)

Partner contexts

A partner context is a partner-owned cohort of settings overrides. The OP backend stores sparse overrides keyed by (storeId, applicationId, variantKey). At read time, partner overrides are layered over the merchant’s default settings — fields you don’t override are inherited from the merchant. Pricing rules are layered the same way: if the partner has no pricing rules attached, the merchant’s rules are used. This is the primitive that powers parallel partner A/B testing without disturbing the merchant’s defaults.

Create a context

POST /v2/settings/context
Required scope: write_settings Request body:
FieldTypeRequiredDescription
variantKeystringYesStable identifier for the cohort. Must match ^[a-zA-Z0-9_.:-]{1,64}$. Use the same value when reading on the public widget path.
namestringYesHuman label, 1–128 chars. Shown in dashboards.
Example:
curl -X POST https://api.production.orderprotection.com/v2/settings/context \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{"variantKey": "experiment_a", "name": "Variant A — auto-add on"}'
Response 201 Created:
{
  "id": "cmokjb8bq000663gkhjp5ppoj",
  "applicationId": "app_ghi012",
  "variantKey": "experiment_a",
  "name": "Variant A — auto-add on",
  "createdAt": "2026-04-28T18:22:11.000Z",
  "updatedAt": null
}

List your contexts

GET /v2/settings/context
Required scope: read_store Returns only the contexts owned by the calling OAuth app for this store. Response 200 OK:
[
  {
    "id": "cmokjb8bq000663gkhjp5ppoj",
    "applicationId": "app_ghi012",
    "variantKey": "experiment_a",
    "name": "Variant A — auto-add on",
    "createdAt": "2026-04-28T18:22:11.000Z",
    "updatedAt": null
  }
]

Get a context (with merged settings)

GET /v2/settings/context/:id
Required scope: read_store Returns the context metadata plus the resolved settings and pricing rules — the same view a shopper assigned to this cohort would see. Merchant defaults are layered first; partner overrides for non-null fields are layered on top. Response 200 OK:
{
  "id": "cmokjb8bq000663gkhjp5ppoj",
  "applicationId": "app_ghi012",
  "variantKey": "experiment_a",
  "name": "Variant A — auto-add on",
  "createdAt": "2026-04-28T18:22:11.000Z",
  "updatedAt": "2026-04-28T18:24:02.000Z",
  "resolvedSettings": {
    "enableCancelAfterPurchase": true,
    "cancelAfterPurchaseDurationSeconds": 86400,
    "sendConfirmationEmail": true,
    "offerStoreCreditOnOpPurchase": false,
    "storeCreditType": null,
    "storeCreditBonus": null,
    "storeCreditBonusType": null,
    "storeCreditMaxPercentage": null,
    "..." : "all merchant GeneralSetting fields"
  },
  "resolvedPricingRules": [
    {
      "id": "rs_xxx",
      "type": "SHIPPING",
      "automaticallyAddToCart": true,
      "autoAddStateBlockList": [],
      "autoAddCountryBlockList": [],
      "rules": [
        { "id": "pr_a", "minValue": 0, "maxValue": 50, "...": "..." }
      ]
    }
  ]
}
This endpoint does not consult the OAuth-app installation off-switch. The OAuth gate already authorises the calling app to read its own context. The off-switch only fires on the public widget read path.

Update a context

PATCH /v2/settings/context/:id
Required scope: write_settings (+ write_store_credit_settings if any store-credit field is present) Every field is optional. Sparse semantics: fields you omit stay inherited from the merchant; fields you send become partner overrides for this cohort. Pass an explicit value to override; pass null is not supported on this endpoint — use DELETE to drop the cohort entirely. Request body:
FieldTypeDescription
namestringNew cohort label (1–128 chars).
enableCancelAfterPurchasebooleanOverride the cancel-after-purchase toggle for this cohort.
cancelAfterPurchaseDurationSecondsnumberOverride the cancel-after-purchase window (seconds, ≥ 0).
sendConfirmationEmailbooleanOverride the confirmation-email toggle.
sendSmsUpdatesbooleanOverride the SMS-updates toggle.
offerStoreCreditOnOpPurchasebooleanToggle store credit. Requires write_store_credit_settings.
storeCreditTypeenumOne of the StoreCreditType values. Requires write_store_credit_settings.
storeCreditBonusnumberBonus amount (≥ 0). Requires write_store_credit_settings.
storeCreditBonusTypeenumOne of the CalcMethod values (flat, percentage). Requires write_store_credit_settings.
storeCreditMaxPercentagenumberCap (0–100). Requires write_store_credit_settings.
Example:
curl -X PATCH https://api.production.orderprotection.com/v2/settings/context/cmokjb8bq000663gkhjp5ppoj \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{"enableCancelAfterPurchase": true, "cancelAfterPurchaseDurationSeconds": 86400}'
Response 200 OK: Same shape as GET /v2/settings/context/:id.

Delete a context

DELETE /v2/settings/context/:id
Required scope: write_settings Soft-deletes the context. Future shopper traffic with the same variantKey falls back to merchant defaults at the resolver. Response 200 OK:
{ "ok": true }

Merchant settings

The merchant’s default GeneralSetting. Writes attribute the change to your OAuth application so dashboards can surface “last edited by app X” attribution.
Writing to /v2/settings modifies the merchant’s defaults — it affects every shopper that doesn’t fall into a partner cohort. Most parallel-A/B-test workflows should write to PATCH /v2/settings/context/:id instead, leaving the merchant’s defaults untouched.

Get merchant settings

GET /v2/settings
Required scope: read_store Response 200 OK:
{
  "enableCancelAfterPurchase": true,
  "cancelAfterPurchaseDurationSeconds": 86400,
  "sendConfirmationEmail": true,
  "storeCreditType": null,
  "storeCreditBonus": null,
  "storeCreditBonusType": null,
  "storeCreditMaxPercentage": null,
  "offerStoreCreditOnOpPurchase": false,
  "updatedByApplicationId": "app_ghi012",
  "updatedAt": "2026-04-28T18:24:02.000Z"
}
updatedByApplicationId reflects the OAuth application that last wrote via this endpoint, or null if the most recent write was made through the OP dashboard.

Update merchant settings

PUT /v2/settings
Required scope: write_settings (+ write_store_credit_settings for store-credit fields) Request body:
FieldTypeDescription
enableCancelAfterPurchaseboolean
cancelAfterPurchaseDurationSecondsnumber
sendConfirmationEmailboolean
offerStoreCreditOnOpPurchasebooleanRequires write_store_credit_settings.
storeCreditTypeenumRequires write_store_credit_settings.
storeCreditBonusnumber(≥ 0) Requires write_store_credit_settings.
storeCreditBonusTypeenumflat or percentage. Requires write_store_credit_settings.
storeCreditMaxPercentagenumber0–100. Requires write_store_credit_settings.
Response 200 OK: Same shape as GET /v2/settings.

Pricing rules

Per-ruleset-type scopes. A token with only read_shipping_insurance_pricing will see only SHIPPING rulesets; the others are silently filtered out (not 403’d) so a single token can be used for multiple resource types without surfacing access errors.
TypeRead scopeWrite scope
SHIPPINGread_shipping_insurance_pricingwrite_shipping_insurance_pricing
EXTENDED_WARRANTYread_extended_warranty_pricingwrite_extended_warranty_pricing
All pricing scopes are admin-gated — see Scopes → Price Settings. Private apps cannot use them; public apps must be reviewed and approved by OrderProtection.

List pricing rules

GET /v2/pricing/rules
Required scope: any of the per-type read scopes above. The response includes only the rulesets you have a matching read scope for. Response 200 OK:
[
  {
    "id": "rs_abc",
    "type": "SHIPPING",
    "automaticallyAddToCart": true,
    "autoAddStateBlockList": ["CA", "NY"],
    "autoAddCountryBlockList": [],
    "rules": [
      { "id": "pr_x", "minValue": 0, "maxValue": 50, "...": "..." }
    ],
    "updatedByApplicationId": "app_ghi012"
  }
]

Update a ruleset

PUT /v2/pricing/rules/:id
Required scope: matching write scope for the ruleset’s type. Passing an id whose type you don’t have a write scope for returns 404 (existence is hidden). Request body:
FieldTypeDescription
automaticallyAddToCartbooleanToggle auto-add for this ruleset.
rulesarrayReplacement list of price rules. Omit to leave existing rules unchanged.
autoAddStateBlockListstring[]ISO 3166-2 region codes (2 letters). Cap 100. Empty array = no blocking; omitted = preserve existing.
autoAddCountryBlockListstring[]ISO 3166-1 alpha-2 codes (2 letters). Cap 100. Same null/empty semantics as above.
Each rule:
{
  "id": "pr_x",            // optional — omit to create a new rule
  "min": 0,
  "max": 50,
  "terms": {
    "paidBy": "customer",   // optional
    "operator": "AND",      // optional, "AND" | "OR"
    "customer": { "amount": 2.99, "type": "flat" },
    "brand":    { "amount": 0,    "type": "flat" }
  }
}
type is one of flat or percentage. Both customer and brand are optional but at least one is typically present. Example:
curl -X PUT https://api.production.orderprotection.com/v2/pricing/rules/rs_abc \
  -H "Authorization: Bearer op_at_..." \
  -H "Content-Type: application/json" \
  -d '{
    "automaticallyAddToCart": true,
    "autoAddCountryBlockList": ["CA"]
  }'
Response 200 OK: Array containing the updated ruleset, same shape as GET /v2/pricing/rules.
ISO codes are normalised to upper case server-side, so "ca" and "CA" are equivalent on writes. Reads always return uppercase.

Quote

A stateless protection quote computation. Use this to preview the customer/brand split for a given subtotal before writing it into a cart.

Generate a quote

POST /v2/quote
Required scope: read_quotes Request body:
FieldTypeRequiredDescription
orderTotalnumberOne of thesePre-computed subtotal (no need to send line items).
lineItemsarrayOne of theseLine items; the server computes the subtotal, stripping non-shippable items for SHIPPING quotes. Cap 500.
policyTypeenumNoSHIPPING (default) or EXTENDED_WARRANTY.
currencystringNoISO currency code; informational only.
durationstringIf EXTENDED_WARRANTYISO 8601 year duration, e.g. "P3Y". Required for warranty quotes; rejected on shipping quotes.
Each line item:
{
  "price": 19.99,
  "quantity": 1,
  "isShippable": true,
  "id": "li_x",          // optional
  "productType": "shoes" // optional
}
Either orderTotal or lineItems must be present (not both). Example:
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"}'
Response 200 OK:
{
  "customer": 1.99,
  "brand": 0,
  "fundedBy": "customer",
  "operator": null,
  "pricingModel": "FLAT"
}

Widget config

Per-widget-type scopes. As with pricing, a narrow token only sees the widget types it can read; the rest are silently filtered.
TypeRead scopeWrite scope
CHECKOUTread_widget_checkoutwrite_widget_checkout
CARTread_widget_cartwrite_widget_cart
INFO_MODALread_widget_info_modalwrite_widget_info_modal

List widget configs

GET /v2/widget/config
Required scope: any of the per-type read scopes. Response 200 OK:
[
  {
    "id": "wc_abc",
    "type": "CART",
    "status": "ACTIVE",
    "variant": null,
    "config": { "...": "schemaless — defined by the renderer" },
    "customizationValues": { "...": "schemaless" },
    "updatedAt": "2026-04-28T18:24:02.000Z",
    "updatedByApplicationId": "app_ghi012"
  }
]

Update a widget config

PUT /v2/widget/config/:id
Required scope: matching write scope for the widget’s type. As with pricing, an id whose type you can’t write returns 404 — existence and scope are not distinguishable. Request body:
FieldTypeRequiredDescription
configobjectYesThe widget configuration object. Schemaless — the renderer validates on read.
statusenumNoOne of the WidgetStatus values.
customizationsobjectNoSchemaless customization values.
Response 200 OK: Same shape as a single entry in GET /v2/widget/config.

Public widget read (with cohort)

The shopper-facing widget read path (GET /v1/quote/insurance) is unauthenticated, but it accepts two optional headers that route the read to a partner context. This is how a partner-controlled cart-attribute or shopper-segmenter on the merchant’s storefront can serve different settings + pricing per shopper.
HeaderDescription
x-op-partner-app-idYour OAuth application ID (Application.id).
x-op-partner-variantThe variantKey of the partner context to apply.
Both headers must match ^[a-zA-Z0-9_.:-]{1,64}$. If either is missing, malformed, or the indicated context doesn’t exist for this store, the response silently falls back to merchant defaults — public widget reads must never crash a checkout. The off-switch fires when the OAuth app has been uninstalled (or never installed) on the store: in that case the cohort headers are ignored and the merchant’s defaults are returned. App install / uninstall events propagate within seconds via Kafka, so deliberate revocations take effect immediately rather than waiting for cache TTL.
curl -G https://api.production.orderprotection.com/v1/quote/insurance \
  --data-urlencode "store_url=example.myshopify.com" \
  --data-urlencode "country=US" \
  -H "x-op-partner-app-id: app_ghi012" \
  -H "x-op-partner-variant: experiment_a"
The response shape is unchanged from the existing /v1/quote/insurance documentation; only the resolved settings + pricing differ when a valid cohort is supplied.

Error responses

Standard JSON error envelope (same as the rest of the OrderProtection API):
{
  "statusCode": 403,
  "message": "Insufficient OAuth scopes",
  "error": "Forbidden"
}
CodeCommon cause on these endpoints
400Malformed body, validation failure, or admin-gated scope missing on a store-credit field.
401Missing, expired, or revoked access token.
403Token missing the required scope. On endpoints where existence is hidden (pricing, widget), this surfaces as 404 instead.
404Resource doesn’t exist, isn’t owned by your app (partner contexts), or you lack the matching per-type scope (pricing, widget).
429Rate limit exceeded.

Last verified against monolog d32a10bba.