Install

Five stacks, one gate.

Cleared sits between checkout and the carrier. It mounts as a checkout step where the platform allows one and as a post-checkout hold where it does not, and it never touches your payment flow.

Where it runs
A checkout step, or a hold on the order after checkout.
What it writes
Two attributes on the order: a status and a record id.
What fulfillment gets
An adult-signature flag and the statutory sentence for the label.

Platforms

Where the gate mounts.

The install differs in where the platform lets the gate interrupt the buyer. Everything after that — classification, notice, verification, address match, label — is the same code on every platform.

  • Shopify

    Checkout step on Plus
    Where the gate mounts
    On Plus, a checkout UI extension runs the gate before payment. On standard Shopify the checkout is closed, so the gate runs as a post-checkout hold: the order is captured, then held until the buyer finishes verification from a link in the confirmation email.
    What Cleared writes back
    Two order attributes. Staff see them on the order page; Flow can route on them.
    cleared_statuscleared_record_id
    Fulfillment
    ShipStation reads the status as a tag, or EasyPost sets delivery_confirmation to ADULT_SIGNATURE at label creation.
    Install effort
    About a week, including a test order in a development store.
  • WooCommerce

    Checkout step
    Where the gate mounts
    The gate renders as a checkout block above the payment section and blocks submission until the evaluation clears, using woocommerce_checkout_process.
    What Cleared writes back
    Two order meta keys, readable from the order admin and the REST API.
    _cleared_status_cleared_record_id
    Fulfillment
    The signature flag is set on whichever label plugin the store already uses; EasyPost is supported directly.
    Install effort
    Two to three days. One plugin, one filter.
  • BigCommerce

    Post-checkout hold
    Where the gate mounts
    Cleared subscribes to store/order/created. The order is created as normal and held in Awaiting Fulfillment until the buyer completes the gate.
    What Cleared writes back
    Two custom order fields, plus a note on the order timeline.
    cleared_statuscleared_record_id
    Fulfillment
    ShipStation through the BigCommerce connector; the adult-signature flag rides on the order tag.
    Install effort
    About a week.
  • Magento / Adobe Commerce

    Checkout step
    Where the gate mounts
    A React checkout step rendered before payment, mounted into the existing checkout bundle. Nothing else in the checkout moves.
    What Cleared writes back
    Two attributes on sales_order, so the existing fulfillment queries keep working unchanged.
    cleared_statuscleared_record_id
    Fulfillment
    The attributes drive the USPS Priority label; adult signature is added at label creation.
    Install effort
    Estimated two weeks. This is the path costed for Seekins Precision.
  • Custom (Next.js, React Router, headless)

    Either
    Where the gate mounts
    A route before payment, or a server-side hold after it, whichever fits the order model you already have.
    What Cleared writes back
    Whatever your order model calls them. The record id is the only field Cleared needs back.
    cleared_statuscleared_record_id
    Fulfillment
    EasyPost or ShipStation called directly from the record.
    Install effort
    Hand-tailored by us. Scoped after a read of your checkout.

API

Three calls and a webhook.

A custom checkout can do everything the adapters do. Calls are server-to-server with a bearer key; the browser never sees it. The base URL is https://api.cleared.example/v1.

POST /v1/evaluate

Classify a cart for a destination. Returns the outcome, one classified line per SKU with its basis and reason, and the requirements the gate will raise. Call it as the cart changes; it is pure and cheap.

Pick a cart

Two gas-gun parts under Seekins policy. The gate applies and the six requirements come back with their cites.

Request

json
POST /api/evaluate
Content-Type: application/json

{
  "lines": [
    {
      "sku": "0010530053 - F",
      "qty": 1
    },
    {
      "sku": "low_pro_adj_gas_blk_config",
      "qty": 1
    }
  ],
  "shipTo": {
    "name": "Connor Callison",
    "line1": "2200 Harbor Ave",
    "city": "Eureka",
    "state": "CA",
    "zip": "95501"
  },
  "accountType": "consumer"
}

Response

from this build
json
{
  "outcome": "gate",
  "jurisdiction": "CA",
  "lines": [
    {
      "sku": "0010530053 - F",
      "name": "NOXs Rail System",
      "class": "gate",
      "basis": "policy",
      "reason": "Conservative default: AR-pattern parts run through the gate until each SKU is reviewed."
    },
    {
      "sku": "low_pro_adj_gas_blk_config",
      "name": "Low Profile Adjustable Gas Block",
      "class": "gate",
      "basis": "policy",
      "reason": "Conservative default: AR-pattern parts run through the gate until each SKU is reviewed."
    }
  ],
  "requirements": [
    {
      "id": "notice",
      "label": "Statutory notice",
      "statute": "§3273.51(e)(1)(A)"
    },
    {
      "id": "attestation",
      "label": "Written attestation",
      "statute": "§3273.51(e)(1)(B)"
    },
    {
      "id": "id_verification",
      "label": "Identity and age verification",
      "statute": "§3273.51(e)(1)(C)"
    },
    {
      "id": "address_match",
      "label": "Delivery address matches the ID",
      "statute": "§3273.51(e)(3)(B)"
    },
    {
      "id": "label",
      "label": "Statutory sentence on the label",
      "statute": "§3273.51(e)(3)(A)"
    },
    {
      "id": "adult_signature",
      "label": "Adult signature on delivery",
      "statute": "§3273.51(e)(3)(C)"
    }
  ],
  "fflLines": []
}

This posts the request above to /api/evaluate in this app and prints what comes back.

POST /v1/verifications

Simulated

Start the identity and age check for a record and get back a hosted URL to send the buyer to.

Request

http
POST /v1/verifications
Authorization: Bearer sk_live_…
Content-Type: application/json

{
  "recordId": "rec_sim_8f21c4",
  "provider": "stripe_identity",
  "returnUrl": "https://store.example/checkout/cleared"
}

Response

json
{
  "id": "vs_sim_8f21c4d0",
  "status": "processing",
  "provider": "simulated",
  "hostedUrl": "https://verify.cleared.example/s/vs_sim_8f21c4d0",
  "expiresAt": "2026-01-22T18:41:00.000Z"
}

In this demo the provider is always “simulated” and the document never leaves the browser. In production this call opens Stripe Identity or Veriff and the document never touches the retailer’s servers.

GET /v1/records/:id

Read the durable record for one order: what was shown, what was attested, what was verified, what went on the label, and when. This is the object the console renders and the CSV export flattens.

json
{
  "id": "rec_sim_8f21c4",
  "orderId": "ord_sp24831",
  "createdAt": "2026-01-22T18:44:12.000Z",
  "jurisdiction": "CA",
  "skus": [
    "0010530053 - F",
    "low_pro_adj_gas_blk_config"
  ],
  "outcome": "gate",
  "status": "cleared",
  "noticeVersion": "ca-ab1263-2026-01",
  "attestation": {
    "at": "2026-01-22T18:42:39.000Z",
    "ip": "203.0.113.24",
    "initials": "JE"
  },
  "verification": {
    "status": "verified",
    "sessionId": "vs_sim_8f21c4d0",
    "provider": "simulated",
    "firstName": "Connor",
    "lastName": "Callison",
    "dob": "1991-04-12",
    "age": 34
  },
  "addressMatch": {
    "matched": true,
    "normalizedShipTo": {
      "name": "JORDAN ELLIS",
      "line1": "2200 HARBOR AVE",
      "city": "EUREKA",
      "state": "CA",
      "zip": "95501"
    },
    "normalizedId": {
      "name": "JORDAN ELLIS",
      "line1": "2200 HARBOR AVE",
      "city": "EUREKA",
      "state": "CA",
      "zip": "95501"
    },
    "mismatches": []
  },
  "carrier": {
    "service": "USPS Priority Mail",
    "adultSignature": true,
    "labelText": "Signature and proof of identification of person aged 18 years or older required for delivery."
  },
  "timeline": [
    {
      "at": "2026-01-22T18:41:02.000Z",
      "event": "Evaluated",
      "detail": "2 lines, gate required"
    },
    {
      "at": "2026-01-22T18:41:44.000Z",
      "event": "Notice shown",
      "detail": "ca-ab1263-2026-01"
    },
    {
      "at": "2026-01-22T18:42:39.000Z",
      "event": "Attested",
      "detail": "JE"
    },
    {
      "at": "2026-01-22T18:43:30.000Z",
      "event": "Identity verified",
      "detail": "Age 34"
    },
    {
      "at": "2026-01-22T18:43:58.000Z",
      "event": "Address matched"
    },
    {
      "at": "2026-01-22T18:44:12.000Z",
      "event": "Cleared",
      "detail": "Adult signature required"
    }
  ]
}

Webhooks

Cleared posts to your endpoint as an order moves. Each delivery is signed; retries back off for 24 hours.

Webhook events Cleared sends.
EventSent when
evaluation.completedA cart has been classified. Carries the outcome and the line classes.
verification.completedThe identity and age check finished, passed or failed.
order.clearedEvery requirement in the retailer’s policy is recorded as satisfied.
order.heldThe address did not match the ID, or a step was abandoned.
order.blockedThe order cannot be completed to this destination.
order.routed_to_dealerThe shipment goes to a licensed dealer instead of the buyer.
record.createdThe compliance record is durable and exportable.
http
POST https://store.example/webhooks/cleared
Cleared-Signature: t=1769107452,v1=…

{
  "id": "evt_sim_31a9",
  "type": "order.cleared",
  "createdAt": "2026-01-22T18:44:12.000Z",
  "data": {
    "orderId": "ord_sp24831",
    "recordId": "rec_sim_8f21c4",
    "status": "cleared",
    "outcome": "gate",
    "adultSignature": true
  }
}

Next

See the whole thing run on a real catalog.

The Seekins workspace has 79 products classified under California rules and ten scenarios that each run end to end through the gate.