Integrate Authiflow
Authiflow is an independent product-verification layer between your shop and your customer. You connect once, flag the orders that need verification, ship them to the authentication center, and receive the verdict back on your own webhook. This guide has everything you need to integrate yourself — no help from us required.
Introduction
An order flagged with verification_required is sent to Authiflow. Instead of shipping straight to the customer, the item goes to the authentication center first. Our team inspects it and returns a verdict — passed, failed or needs review. Authiflow's only job is to give you an accurate, authenticated verdict; you decide what happens next in your own store.
The integration is a small set of JSON webhooks secured with a per-shop key pair. There is no SDK to install and no library to maintain — any language that can make an HTTPS request works.
How it works
- 1. Submit — you push a verification order to Authiflow. It lands as
incoming. The response contains the center address (ship_to). - 2. Ship to center — you send the product to the authentication center (not the customer) and optionally push the shipping status so the board follows it live.
- 3. Verify — the item is inspected at the center, within 2 working days.
- 4. Verdict — Authiflow POSTs the outcome to your feedback webhook. On a Pass it includes a link to an authenticity certificate.
- 5. Onward — you release the order to the customer (Pass) or handle a return (Fail). You are in control of fulfilment.
Getting started
- 1. Create an account at /register. You immediately receive a
publicKeyandsecretKey. - 2. Your account is reviewed and approved by Authiflow. Until it is approved your keys return
403 Account pending approval. - 3. On the Integration page, set your feedback webhook URL + secret, your pickup address and your return address.
- 4. Start submitting orders (below) and handle the feedback webhook.
Keep your secretKey and feedbackSecret server-side only. You can rotate the key pair any time from the Integration page.
Authentication
Every inbound endpoint is authenticated with HTTP Basic auth using your key pair:
Authorization: Basic base64("<publicKey>:<secretKey>")The Shopify ingestion endpoint is the one exception — Shopify's built-in webhooks can't send custom headers, so it also accepts the secret via the X-Api-Key header (preferred) or a ?token=<secretKey> query parameter.
Submit orders
POST /api/webhooks/orders
Submit an order that needs verification. Only verification_required: true is ingested. Idempotent on order_number — resubmitting the same order is safe.
POST https://authiflow.com/api/webhooks/orders
Authorization: Basic base64("<publicKey>:<secretKey>")
Content-Type: application/json
{
"order_number": "10234", // required — your order id, used everywhere
"verification_required": true, // required — only true is ingested
"customer_name": "Jane Doe",
"customer_email": "jane@example.com",
"address_line1": "Keizersgracht 1",
"address_line2": "",
"postal_code": "1015 CJ",
"city": "Amsterdam",
"country": "Netherlands",
"product_name": "Air Jordan 1 High OG Chicago",
"sku": "555088-134",
"size": "43",
"product_category": "sneakers",
"image_url": "https://yourshop.com/img/aj1.jpg",
"seller_name": "Your Shop",
"tracking_number": "3SABCD1234567", // optional — your inbound label (shop → center)
"tracking_url": "https://tracking.example.com/3SABCD1234567"
}Response — 201 Created (or 200 if it already existed)
{
"ok": true,
"id": "clx8f...",
"created": true,
"ship_to": {
"name": "Authiflow Authentication Center",
"address_line1": "Voltastraat 51",
"postal_code": "3335 KK",
"city": "Zwijndrecht",
"country": "Nederland",
"country_code": "NL"
}
}If verification_required is not true, the order is ignored and you get { "ok": true, "skipped": true }. Send the shipment to the returned ship_to address — this is the core of the guarantee: the item is at the center, not with the customer, until it passes.
Shopify ingestion
POST /api/webhooks/shopify
Accepts a native Shopify order payload. Only orders tagged authiflow, verification, verification_required or verify are ingested — everything else is skipped. See the Shopify guide below for the full setup.
POST https://authiflow.com/api/webhooks/shopify
X-Api-Key: <secretKey> // preferred — or ?token=<secretKey>
Content-Type: application/json
<the Shopify order payload>Response is the same shape as /api/webhooks/orders (with ship_to). Customer, address and line items are mapped from Shopify's payload automatically.
Shipping status
POST /api/webhooks/status
Push the shipping milestones so the board follows the parcel live. Two inbound milestones: shipped (label scanned / en route to the center) and received(delivered at the center → starts the 2 working-day verification SLA).
POST https://authiflow.com/api/webhooks/status
Authorization: Basic base64("<publicKey>:<secretKey>")
Content-Type: application/json
{
"order_number": "10234", // required
"status": "shipped", // required — "shipped" | "received"
"tracking_number": "3SABCD1234567", // optional
"tracking_url": "https://...", // optional
"occurred_at": "2026-07-01T10:00:00+02:00" // optional — real milestone time (SLA start)
}After a decision, the same endpoint records the outbound leg: send shipped once the parcel to the customer (after a Pass) or back to you (after a Fail) is really scanned — this advances the order to shipped_to_customer / returned_to_seller. Idempotent; an unknown order returns 404.
Cancellations & refunds
If an order is refunded or cancelled on your side before it reaches the center, push status: "cancelled" (also accepted: refunded, refund_processing) to the same endpoint — the order is then removed from Authiflow. This only works while the order is still incoming or shipped; once the item is at the verification center you get { ok: true, removed: false } back and we resolve the refund together.
POST https://authiflow.com/api/webhooks/status
Authorization: Basic base64("<publicKey>:<secretKey>")
Content-Type: application/json
{ "order_number": "10234", "status": "cancelled" }
// while incoming/shipped: { "ok": true, "status": "cancelled", "removed": true }
// already at/past the center: { "ok": true, "removed": false, "reason": "..." }Shipping labels
POST /api/webhooks/label · multipart/form-data
Upload the customer label (after a Pass) or the return label (after a Fail) as a PDF so the center can print it. Optional tracking fields attach an informative track & trace to the card.
POST https://authiflow.com/api/webhooks/label
Authorization: Basic base64("<publicKey>:<secretKey>")
Content-Type: multipart/form-data
order_number = 10234
label_type = customer // "customer" (after Pass) or "return" (after Fail)
label = <the label as a PDF file>
tracking_number = 3SABCD1234567 // optional, informative
tracking_url = https://... // optionalThe file must be a real PDF (415 otherwise). Re-uploading for the same order overwrites the previous label. An unknown order returns 404.
Center address
GET /api/center · public
The authentication center address as machine-readable JSON, if you want to generate the inbound label yourself. No authentication needed.
GET https://authiflow.com/api/center
{
"authentication_center": {
"name": "Authiflow Authentication Center",
"address_line1": "Voltastraat 51",
"postal_code": "3335 KK",
"city": "Zwijndrecht",
"country": "Nederland",
"country_code": "NL"
}
}Feedback webhook
This is how you receive the verdict. On every status change, Authiflow POSTs to the feedback URL you set on the Integration page, signed with your feedbackSecret as a Bearer token. Verify that token, then act on status.
POST <your feedbackUrl>
Authorization: Bearer <feedbackSecret>
Content-Type: application/json
{
"order_number": "10234",
"status": "passed", // the Authiflow status — match on this
"verification_status": "passed", // mapped external code (optional to use)
"status_label": "Passed",
"tracking_number": "3SABCD1234567",
"carrier_status": "Delivered at authentication center",
"fail_reason": null, // set when status = failed
"certificate_url": "https://authiflow.com/api/certificate/clx..?t=..", // present on a Pass
"source": "authiflow"
}Respond with any 2xx. On a Pass, use certificate_urlin your customer email — it's a public, token-protected link to the authenticity certificate. If your endpoint was down, an order's current status can be re-sent from the dashboard.
Status reference
| status | Meaning |
|---|---|
| incoming | Order received, awaiting shipment to the center. |
| shipped | Inbound label scanned / en route to the center. |
| in_verification | Delivered at the center; 2 working-day SLA running. |
| passed | Verified authentic; certificate available. |
| failed | Did not pass; fail_reason is set. |
| needs_review | Extra check needed before a final verdict. |
| shipped_to_customer | After a Pass, dispatched to the customer. |
| returned_to_seller | After a Fail, dispatched back to you. |
Shipping & labels
There are three shipping legs:
- Inbound (you → center): ship the product to the
ship_toaddress before it reaches the customer. You can make this label yourself, or let Authiflow generate it from your pickup address. - Customer (→ customer, after a Pass): your own original label. Upload it via
/api/webhooks/label(label_type=customer), or dispatch from your own system. - Return (center → you, after a Fail): upload a return label (
label_type=return); otherwise a printable label to your configured return address is used.
Guide: Shopify
The simplest way to let customers choose verification is an add-on product plus Shopify Flow — no app development.
- 1. Create a service product "Premium Verification" (price = your fee; not a physical product, no inventory; SKU
PREMIUM-VERIFY). - 2. Let customers add it — a product/cart button (Cart AJAX
/cart/add.js) or a free add-on app. - 3. Flow A — on order created, if a line item SKU equals
PREMIUM-VERIFY: add tagauthiflow, action Hold fulfillment order, and an HTTP POST tohttps://authiflow.com/api/webhooks/shopifywith headerX-Api-Key: <secretKey>. - 4. Flow B — on your feedback webhook with
status = passed: Release fulfillment hold. Onfailed, keep it held and refund/return. - 5. Ship the item to the center (a side-channel label, separate from Shopify's held fulfillment).
The fulfillment hold is placed by your Flow; Authiflow provides the verdict that releases it.
Guide: custom website
Three calls and a contract:
- 1. On checkout of a verification order,
POST /api/webhooks/orderswithverification_required: trueand the customer/product fields. - 2. Ship to the returned
ship_toaddress — never to the customer yet. Optionally push/api/webhooks/statusmilestones. - 3. On your feedback webhook:
status = passed→ release to the customer (addcertificate_urlto the email); anything else → hold/refund/return.
Errors
| Code | Meaning |
|---|---|
| 200 / 201 | Success. 201 when an order is created, 200 when it already existed. |
| 400 | Invalid body or a missing required field. |
| 401 | Missing or invalid API keys. |
| 403 | Account pending approval — keys are valid but not yet activated. |
| 404 | Unknown order_number (status / label). Submit the order first. |
| 413 / 415 | Label too large / not a PDF. |
Go-live checklist
- Account approved by Authiflow (keys return
200, not403). - Feedback URL + secret set; your endpoint verifies the Bearer token and returns
2xx. - Pickup address + return address set on the Integration page.
- Orders submit with
verification_required: trueand land asincoming. - You ship to
ship_to, not the customer, and pushshipped/received. - Your system reacts to
passed/failed/needs_reviewfrom the feedback webhook. - (Shopify) Flow A holds fulfillment on the tag; Flow B releases it only on
passed.
Questions during integration? Reach us at support@authiflow.com.