Base URLs
- Production:
https://api.ordercore.ai - Demo:
https://demo-api.ordercore.ai
Authentication
Send your API key on every request:
X-API-Key: <your_key>- or
Authorization: Bearer <your_key>
curl -H "X-API-Key: oc_live_..." https://api.ordercore.ai/v1/account/auth
Idempotency
For create operations include:
- Header:
Idempotency-Key - or body field:
idempotency_key
Pagination
List endpoints accept page and per_page (default 20, max 100).
Create your first order (First Success)
Use this same flow everywhere (docs, tutorial, and get-started):
- Get API key:
GET /health - Create your first order:
POST /v1/onboarding/demo-data - Confirm order → trigger webhook:
POST /v1/orders
After this flow you will have:
- a real order in the system
- a working API call
- a clear go/no-go decision
Built for real systems:
- idempotent order creation
- retry-safe APIs
- webhook-driven integrations
No store, no UI, no checkout flow needed. Just API.
oc_live_... API key for this flow — it arrives with the 3-day trial, or request a first key without checkout.export API_KEY="oc_live_..."
# 1) Get API key + health preflight
curl -sS https://api.ordercore.ai/health
# 2) Create your first order
SEED_JSON="$(curl -sS -X POST https://api.ordercore.ai/v1/onboarding/demo-data \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{}')"
# 3) Confirm order → trigger webhook
CUSTOMER_ID="$(printf '%s' "$SEED_JSON" | jq -r '.sample_customer_id // empty')"
SKU_ID="$(printf '%s' "$SEED_JSON" | jq -r '.sample_order_item.sku_id // empty')"
test -n "$CUSTOMER_ID" || { echo "No sample_customer_id returned by onboarding"; exit 1; }
test -n "$SKU_ID" || { echo "No sample_order_item.sku_id returned by onboarding"; exit 1; }
# 4) create first retry-safe order and verify webhook delivery
curl -sS -X POST https://api.ordercore.ai/v1/orders \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: first-order-001" \
-d "{\"customer_id\":\"$CUSTOMER_ID\",\"items\":[{\"sku_id\":\"$SKU_ID\",\"quantity\":1}]}"
jq for onboarding response parsing.Endpoints
GET /health – status
GET /direct-ai/manifest – public direct AI checkout manifest (commercial + technical entry points)
GET /direct-ai/browser-config – public browser-safe checkout config (Stripe publishable key when configured)
/ai-integrations – public AI integrations hub with OpenAI, Claude, Gemini, DeepSeek, and Grok packs plus free-tier and billing model summary
GET /integrations/catalog – public add-ons catalog (connectors, UCP compatibility summary)
GET /integrations/shopify/status – public Shopify install diagnostics (non-sensitive)
POST /v1/account/checkout-access-tokens – mint short-lived public checkout token
POST /v1/account/buyer-checkout-links – create branded buyer checkout link scoped to one SKU + quantity, with optional merchant_reference_id, success_url, and cancel_url (merchant_reference_id: max 128 chars, allowed [a-zA-Z0-9._:-])
POST /v1/account/buyer-checkout-links/regenerate – mint a fresh branded buyer link from a previous buyer URL or token while keeping the same scope
POST /ucp/public/checkout/sessions/{session_id}/payment-intent – create Stripe PaymentIntent for buyer confirmation
GET /v1/products – list products (filters: status)
POST /v1/products – create product
GET /v1/products/{product_id} – product detail
PATCH /v1/products/{product_id} – update product
DELETE /v1/products/{product_id} – delete product
GET /v1/skus/{skuCode} – SKU detail
GET /v1/inventory – list inventory (filters: sku_id/sku_code, location_id)
POST /v1/inventory/adjust – adjust stock
POST /v1/inventory/reserve – reserve stock
POST /v1/inventory/release – release reserved stock
GET /v1/prices – list prices (filters: sku_id/sku_code, price_list_code, currency, customer_id, quantity, valid_now, active_only)
GET /v1/orders – list orders
GET /v1/orders/lookup?merchant_reference_id=... – lookup latest checkout session and order by merchant reference
GET /v1/orders/{order_id} – order detail
GET /v1/orders/{order_id}/trace – tenant-safe order, status event, and webhook delivery timeline
GET /v1/account/auth – verify authenticated tenant and key context (auth mode, scopes, rate limit). Response includes api_key_scopes (always an array), rate_limit_per_minute, and key expiry metadata (api_key_expires_at, api_key_expires_in_days, api_key_expiry_status) when the key has expiry.
GET /v1/account/status – tenant plan and key status
GET /v1/account/usage – monthly usage and quota projection
GET /v1/account/readiness – go-live checklist for key access + TTL stability, catalog/inventory, active checkout.completed endpoint, successful delivery without recent abandoned webhook failures, and order flow
POST /v1/onboarding/catalog-csv – import a starter catalog, prices, and inventory without Shopify or another connector
GET /v1/integrations/shopify/status – Shopify integration status for current tenant
GET /v1/integrations/shopify/stores – connected Shopify stores
GET /v1/integrations/shopify/sync-logs – latest Shopify-origin order sync events
GET /v1/integrations/shopify/webhook-events – webhook processing events (filters: status, shop_domain)
Transaction Trace
Use an order UUID or order number to inspect the lifecycle of one agent purchase. The response combines order creation, status changes, webhook attempts, response status, and delivery duration without returning webhook payloads or response bodies.
curl -sS "https://api.ordercore.ai/v1/orders/OC-2026-0001/trace" \
-H "X-API-Key: oc_live_xxx"
{
"trace_version": "2026-07-15",
"order_id": "6c98...",
"order_number": "OC-2026-0001",
"order_status": "confirmed",
"summary": {
"event_count": 3,
"state_changes": 1,
"webhook_deliveries": 1,
"webhook_failures": 0,
"webhook_retries": 0
},
"timeline": [
{"type": "order", "label": "order.created", "status": "pending"},
{"type": "order_event", "label": "order.confirmed", "status": "confirmed"},
{"type": "webhook", "label": "checkout.completed", "status": "success", "attempt": 1}
]
}
Create Order
POST /v1/orders
{
"customer_id": "cust_123",
"items": [
{"sku_id": "sku_123", "quantity": 2}
],
"idempotency_key": "your-idempotency-key"
}
{
"id": "order_...",
"status": "pending",
"created_at": "2026-02-09T12:34:56Z",
"order_number": "OC-000123"
}
Public Direct Checkout Reference
Preferred direct-AI buyer flow is tokenized public checkout with Stripe PaymentIntent confirmation:
POST /v1/account/checkout-access-tokensPOST /ucp/public/checkout/sessionsPUT /ucp/public/checkout/sessions/{session_id}POST /ucp/public/checkout/sessions/{session_id}/payment-intent- Confirm
client_secretin Stripe.js / Payment Element POST /ucp/public/checkout/sessions/{session_id}/completewithpayment_data.payment_intent_id
scripts/public_checkout_flow.sh. It runs token issuance, public session setup, and PaymentIntent creation, then prints the final complete call to use after client-side confirmation.
Branded buyer page: /direct-ai-buyer-checkout
Browser-side operator reference: /direct-ai-reference-client
Browser config endpoint: https://api.ordercore.ai/direct-ai/browser-config
Scoped buyer link behavior: one branded buyer link creates at most one checkout session; reopening the same link resumes that session instead of minting a new one until checkout is completed. After completion, the same link returns 410 buyer_link_consumed. If you pass email, the link is locked to that buyer email. Every link also carries a signed merchant_reference_id for lead-to-order correlation.
{
"sku_id": "sku_123",
"quantity": 1,
"currency": "USD",
"merchant_reference_id": "lead-123",
"email": "buyer@example.com",
"success_url": "https://merchant.example/thank-you",
"cancel_url": "https://merchant.example/cart",
"full_name": "Jane Doe"
}
scripts/ordercore_merchant_helper.py, scripts/ordercore_merchant_helper.mjs, and scripts/ordercore_merchant_sdk.mjs. Python and Node CLIs now expose the same command-spec and machine-readable help shape. The SDK exports the same operations for direct import into merchant services.
Create flow: python3 scripts/ordercore_merchant_helper.py buyer-link-create --sku-id sku_123 --url-only
CSV row flow: python3 scripts/ordercore_merchant_helper.py buyer-link-create --catalog-csv ./catalog.csv --from-csv-row 1 --url-only
Batch flow: python3 scripts/ordercore_merchant_helper.py buyer-links-batch-from-csv --catalog-csv ./catalog.csv --start-row 1 --end-row 10 --output csv
Regenerate flow: python3 scripts/ordercore_merchant_helper.py buyer-link-regenerate --buyer-checkout-url https://ordercore.ai/direct-ai-buyer-checkout?token=... --url-only
Lookup flow: python3 scripts/ordercore_merchant_helper.py orders-lookup --merchant-reference-id lead-123 --output csv
Polling-safe lookup: python3 scripts/ordercore_merchant_helper.py orders-lookup --merchant-reference-id lead-123 --allow-missing
Auth preflight: python3 scripts/ordercore_merchant_helper.py account-auth --output json
Readiness preflight: python3 scripts/ordercore_merchant_helper.py account-readiness --output json
Go-live preflight: python3 scripts/ordercore_merchant_helper.py go-live-preflight --event-type checkout.completed --window-hours 24 --output json
Webhook ops: python3 scripts/ordercore_merchant_helper.py webhook-endpoints-list
Webhook smoke: python3 scripts/ordercore_merchant_helper.py webhook-smoke-trigger --mode retryable
Bootstrap wizard: bash scripts/ordercore_quick_setup.sh
Connector wizard: bash scripts/ordercore_connector_quick_setup.sh --platform shopify
Public path chooser: /get-started
Python JSON help: python3 scripts/ordercore_merchant_helper.py help --command webhook-metrics --format json
Node variant: node scripts/ordercore_merchant_helper.mjs webhook-metrics --event-type checkout.completed --window-hours 24 --output csv
Node readiness preflight: node scripts/ordercore_merchant_helper.mjs account-readiness --output json
Node go-live preflight: node scripts/ordercore_merchant_helper.mjs go-live-preflight --event-type checkout.completed --window-hours 24 --output json
Node JSON help: node scripts/ordercore_merchant_helper.mjs help --command webhook-metrics --format json
Merchant snippets
curl -sS -X POST https://api.ordercore.ai/v1/account/buyer-checkout-links \
-H "X-API-Key: oc_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"sku_id": "sku_123",
"quantity": 1,
"currency": "USD",
"merchant_reference_id": "lead-123",
"email": "buyer@example.com",
"success_url": "https://merchant.example/thank-you",
"cancel_url": "https://merchant.example/cart"
}'
const response = await fetch("https://api.ordercore.ai/v1/account/buyer-checkout-links", {
method: "POST",
headers: {
"X-API-Key": process.env.ORDERCORE_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
sku_id: "sku_123",
quantity: 1,
currency: "USD",
merchant_reference_id: "lead-123",
email: "buyer@example.com",
success_url: "https://merchant.example/thank-you",
cancel_url: "https://merchant.example/cart"
})
});
const data = await response.json();
console.log(data.buyer_checkout_url);
payload := strings.NewReader(`{"sku_id":"sku_123","quantity":1,"currency":"USD","merchant_reference_id":"lead-123","email":"buyer@example.com","success_url":"https://merchant.example/thank-you","cancel_url":"https://merchant.example/cart"}`)
req, _ := http.NewRequest(http.MethodPost, "https://api.ordercore.ai/v1/account/buyer-checkout-links", payload)
req.Header.Set("X-API-Key", os.Getenv("ORDERCORE_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var body struct {
BuyerCheckoutURL string `json:"buyer_checkout_url"`
}
json.NewDecoder(resp.Body).Decode(&body)
fmt.Println(body.BuyerCheckoutURL)
curl -sS -X POST https://api.ordercore.ai/v1/account/buyer-checkout-links/regenerate \
-H "X-API-Key: oc_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"buyer_checkout_url": "https://ordercore.ai/direct-ai-buyer-checkout?token=...",
"ttl_minutes": 15
}'
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py buyer-link-regenerate \
--buyer-checkout-url "https://ordercore.ai/direct-ai-buyer-checkout?token=..." \
--url-only
{
"payment_data": {
"handler_id": "card",
"payment_intent_id": "pi_12345"
}
}
curl -sS "https://api.ordercore.ai/v1/orders/lookup?merchant_reference_id=lead-123" \
-H "X-API-Key: oc_live_xxx"
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py orders-lookup \
--merchant-reference-id lead-123 \
--output csv
python3 scripts/ordercore_merchant_helper.py help --format json
python3 scripts/ordercore_merchant_helper.py help \
--command webhook-metrics \
--format json
ORDERCORE_API_KEY=oc_live_xxx \
node scripts/ordercore_merchant_helper.mjs orders-lookup \
--merchant-reference-id lead-123 \
--allow-missing \
--output jsonl
node scripts/ordercore_merchant_helper.mjs help --format json
node scripts/ordercore_merchant_helper.mjs help \
--command webhook-metrics \
--format json
import { ordersLookup, webhookMetrics, resolveApiKey } from "./scripts/ordercore_merchant_sdk.mjs";
const apiKey = resolveApiKey({ env: process.env });
const lookup = await ordersLookup({
apiKey,
merchantReferenceId: "lead-123",
allowMissing: true,
});
const metrics = await webhookMetrics({
apiKey,
eventType: "checkout.completed",
windowHours: 24,
});
console.log({ lookup, metrics });
Use --allow-missing when your merchant workflow polls before checkout or order creation exists yet. In that mode the helper prints {"status":"not_found"} and exits successfully.
Webhook Endpoint Ops
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-endpoints-list
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-endpoints-create \
--url https://example.com/webhooks/ordercore \
--events checkout.completed
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-endpoints-delete \
--endpoint-id 123e4567-e89b-12d3-a456-426614174000
Delete is a deactivation operation. Delivery history stays queryable after endpoint retirement.
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-deliveries-list \
--event-type checkout.completed \
--limit 10
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-deliveries-list \
--event-type checkout.completed \
--limit 10 \
--output jsonl
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-metrics \
--event-type checkout.completed \
--window-hours 24
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-metrics \
--event-type checkout.completed \
--window-hours 24 \
--output csv
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-smoke-trigger \
--mode standard
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py webhook-smoke-trigger \
--mode retryable
Catalog CSV Import
Use POST /v1/onboarding/catalog-csv when you want a self-serve starting catalog without Shopify, WooCommerce, or another platform connector.
Required CSV headers:
product_namesku_code
Optional headers:
product_descriptionproduct_external_idorproduct_refsku_nameunit_priceorpricequantity_on_handorstock_qty
curl -sS -X POST https://api.ordercore.ai/v1/onboarding/catalog-csv \
-H "X-API-Key: oc_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"currency": "USD",
"price_list_code": "IMPORT",
"location_code": "IMPORT-WH",
"location_name": "Import Warehouse",
"csv": "product_name,sku_code,unit_price,quantity_on_hand\nStarter Pack,STARTER-1,49.00,10"
}'
{
"status": "ok",
"currency": "USD",
"price_list_code": "IMPORT",
"location_code": "IMPORT-WH",
"imported_rows": 1,
"sample_order_item": {
"sku_id": "sku_...",
"quantity": 1
},
"created_or_updated": {
"products": 1,
"skus": 1,
"prices": 1,
"inventory_rows": 1,
"price_lists": 1,
"locations": 1
}
}
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py catalog-csv-import \
--csv-file ./catalog.csv \
--price-list-code IMPORT \
--location-code IMPORT-WH
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py buyer-link-create \
--catalog-csv ./catalog.csv \
--from-csv-row 1 \
--url-only
ORDERCORE_API_KEY=oc_live_xxx \
python3 scripts/ordercore_merchant_helper.py buyer-links-batch-from-csv \
--catalog-csv ./catalog.csv \
--start-row 1 \
--end-row 10 \
--merchant-reference-prefix launch-20260316 \
--output csv
Order actions
POST /v1/orders/{order_id}/confirm – confirm order
POST /v1/orders/{order_id}/cancel – cancel order
{
"reason": "customer request",
"metadata": {"source": "support"}
}
Webhooks (Outbound)
Manage tenant webhook endpoints:
GET /v1/webhooks/endpointsPOST /v1/webhooks/endpointsDELETE /v1/webhooks/endpoints/{endpoint_id}GET /v1/webhooks/deliveriesGET /v1/webhooks/metrics
{
"url": "https://example.com/webhooks/ordercore",
"events": ["checkout.completed"]
}
checkout.completed (event names are normalized to lowercase).DELETE /v1/webhooks/endpoints/{endpoint_id} now deactivates the endpoint instead of erasing it. Delivery history and metrics stay available for ops and support after an endpoint is retired.
Every delivery includes these headers:
X-OrderCore-Event– event name such ascheckout.completedX-OrderCore-Delivery-ID– unique delivery identifierX-OrderCore-Signature–sha256=+ hex HMAC of the raw request body using your endpoint secret
Production delivery is no longer single-shot. Retryable failures stay pending and are retried automatically with capped backoff. Non-retryable 4xx failures move to failed; exhausted retries move to abandoned.
GET /v1/webhooks/deliveries now returns attempt and next_retry_at so support can see whether a delivery is still scheduled for retry.
GET /v1/webhooks/metrics?event_type=checkout.completed&window_hours=24 returns tenant-scoped success rate, pending count, abandoned count, and p95 delivery latency for the selected window.
Verify the signature against the raw, unparsed request body before accepting the event.
// Node.js
import crypto from "node:crypto";
function verifyOrderCoreSignature(rawBody, signatureHeader, endpointSecret) {
const expected = "sha256=" + crypto
.createHmac("sha256", endpointSecret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader || "", "utf8"),
);
}
// Go
func verifyOrderCoreSignature(rawBody []byte, signatureHeader, endpointSecret string) bool {
mac := hmac.New(sha256.New, []byte(endpointSecret))
mac.Write(rawBody)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signatureHeader))
}
Production smoke coverage now includes a synthetic checkout.completed delivery via ./scripts/smoke_checkout_completed_webhook.sh and a fail-first retry verification via ./scripts/smoke_checkout_completed_retry_worker.sh.
UCP (Experimental)
Discovery: GET /ucp/.well-known/ucp
Checkout sessions:
POST /ucp/checkout/sessionsPUT /ucp/checkout/sessions/{session_id}POST /ucp/checkout/sessions/{session_id}/complete
Errors
{"error":"unauthorized","message":"Missing API key"}
{"error":"unauthorized","message":"API key expired","auth_reason":"expired_api_key"}
{"error":"rate_limited","message":"Too many requests"}
{"error":"not_implemented","message":"This endpoint is not yet implemented"}
Rate limits
Default: 1000 requests/minute per API key (best-effort).