Vendor API keys with scoped access and one-time secret display.
Outbound webhook payload format for operational alerting.
External API Reference
Version v1 for vendor integrations.
All timestamps use ISO-8601 UTC format. Breaking changes will only occur in new API versions (for example, /v2), and existing versions remain stable.
Quick Start (60 seconds)
- Base URL:
https://orderengine.red/api/external/v1 - Auth header:
Authorization: Bearer vek_<prefix>_<secret> - First call:
curl -X GET "https://orderengine.red/api/external/v1/purchase-orders?limit=10" \ -H "Authorization: Bearer vek_<prefix>_<secret>" \ -H "Accept: application/json"
- Operational events and delivery behavior: Webhook docs
Authentication
Use either header format below.
Authorization: Bearer vek_<prefix>_<secret> x-api-key: vek_<prefix>_<secret>
curl -X GET "https://orderengine.red/api/external/v1/catalog/products" \ -H "Authorization: Bearer vek_<prefix>_<secret>"
curl -X GET "https://orderengine.red/api/external/v1/velocity/summary" \ -H "x-api-key: vek_<prefix>_<secret>"
Rate Limits
- Requests are limited per API key using a rolling 60-second window.
- Default sustained limit:
240 requests / minute. - Limit is configurable via
EXTERNAL_API_RATE_LIMIT_PER_MINUTE. 429responses includeRetry-After: 60.
Integration Flow
- Authenticate with vendor API key.
- Fetch catalog and velocity context for read-only operational visibility.
- Use purchase-order endpoints to read/reissue as needed.
- Respond to purchase orders with explicit acknowledgment actions (`accepted`, `rejected`, etc.).
- Publish route-day readiness and delivery scheduling via fulfillment updates.
- Use velocity summary for read-only sales intelligence.
- Treat planning recommendations as internal OrderEngine snapshots approved by store teams.
- Consume operational events via Webhooks.
- Example webhook events:
vendor_api_threshold_breach,purchase_order_status_changed,catalog_availability_changed,restock_threshold_reached,out_of_stock_warning,over_stock_warning.
Recommended Sync + Webhook Pattern
- Bootstrap once using `GET /purchase-orders`, `GET /catalog/products`, and `GET /velocity/summary` with full pagination.
- Persist an `updatedSince` watermark using the max observed `updatedAt` in each successful sync window.
- Process webhook events idempotently for near-real-time updates.
- Use polling as reconciliation for missed/delayed webhook deliveries, not as the primary event stream.
- On cursor failure or invalid cursor token, restart from your last durable `updatedSince` watermark.
# Catalog incremental sync loop (example)
cursor=""
updatedSince="2026-03-12T00:00:00.000Z"
while true; do
resp=$(curl -sS -G "https://orderengine.red/api/external/v1/catalog/products" \
-H "Authorization: Bearer vek_<prefix>_<secret>" \
--data-urlencode "limit=250" \
--data-urlencode "updatedSince=${updatedSince}" \
--data-urlencode "cursor=${cursor}")
# Process resp.items idempotently
hasMore=$(echo "$resp" | jq -r '.hasMore')
nextCursor=$(echo "$resp" | jq -r '.nextCursor // ""')
[ "$hasMore" = "true" ] || break
cursor="$nextCursor"
doneResponse Conventions
- For list endpoints,
countmeans the number of items returned in this page. - List responses generally use top-level arrays (for example,
itemsorstores). - Detail responses may wrap a single resource key (for example,
order).
Core Schemas
Purchase Order
{
"id": "po_123",
"orderNumber": "PO-1001",
"status": "submitted",
"subtotal": 1234.56,
"currentRevision": {
"id": "por_1",
"revisionNumber": 2,
"status": "SENT"
}
}Product (Catalog Item)
{
"availability": {
"isAvailableForOrder": true,
"availableUnits": 240,
"availableCases": 24,
"minOrderCaseQty": 1,
"orderMultiple": 1,
"availabilityReason": null
},
"vendorProductId": "vp_1",
"productId": "prod_1",
"vendorSku": "VEN-123",
"productSku": "SKU-123",
"productName": "Blueberry Gummies",
"brand": "Example",
"category": "edible",
"unitPrice": 9.5,
"casePrice": 95,
"unitsPerCase": 10
}Velocity Summary
{
"vendor": { "id": "vendor_123", "name": "Vendor Name" },
"averageVelocity": 2.5,
"totalUnitsSold": 1200,
"topMovers": [ ... ],
"slowMovers": [ ... ],
"reorderCandidates": [ ... ]
}Error Response
{
"error": {
"message": "Forbidden: missing required scopes",
"code": "MISSING_SCOPE"
},
"requestId": "req_123"
}Status Enums
Purchase Order Status
draftsubmittedacknowledgedconfirmedscheduledout_for_deliverydeliveredpartially_receivedreceivedcancelled
Revision Status
REVIEW_REQUIREDREADY_TO_SENDSENTPARTIALLY_SENTSUPERSEDEDCANCELLED
Purchase Order Transition Matrix
External write endpoints enforce lifecycle guards. Invalid transitions return 409 INVALID_ORDER_STATE.
| API Trigger | Accepted Input | Target Status | Notes |
|---|---|---|---|
POST /purchase-orders/:id/respond | accepted or partially_accepted | acknowledged | Blocked for received, cancelled, delivered, and out_for_delivery. |
POST /purchase-orders/:id/respond | rejected or needs_revision | submitted | Used for explicit non-acceptance/revision workflows. |
PATCH /purchase-orders/:id/fulfillment | scheduled or ready_for_route | scheduled | Planning statuses normalize to top-level scheduled. |
PATCH /purchase-orders/:id/fulfillment | out_for_delivery | out_for_delivery | Route execution state. |
PATCH /purchase-orders/:id/fulfillment | delivered | delivered | Delivery completion state. |
PATCH /purchase-orders/:id/fulfillment | unscheduled or hold | No top-level change | Writes fulfillment metadata without forcing a lifecycle advance. |
POST /purchase-orders/:id/mark-delivered | n/a | delivered | Typically valid from out_for_delivery; guard enforced server-side. |
POST /purchase-orders/:id/mark-received | partial=false | received | Final receipt confirmation. |
POST /purchase-orders/:id/mark-received | partial=true | partially_received | Requires exact current-revision receivedItems; quantity-free partial receipts are rejected. |
Document Enums
Document Type
VENDOR_FACING: vendor-facing purchase order document exposed by external document endpoints.INTERNAL_SPLIT: internal split document type used by internal workflows, not returned by external document endpoints.
Document Status
ACTIVE: current document version for the revision.SUPERSEDED: previous document version retained for history/audit.
Endpoints
GET /api/external/v1/purchase-orders
Lists purchase orders visible to the authenticated vendor key.
Required scope: vendor:orders:read
Query Parameters
| Name | Type | Required | Notes |
|---|---|---|---|
status | string | no | Exact status filter. |
limit | number | no | Default 50, min 1, max 100. |
cursor | string | no | Opaque cursor token from previous response. |
createdSince | ISO-8601 UTC timestamp | no | Only return orders with `createdAt >= createdSince`. |
updatedSince | ISO-8601 UTC timestamp | no | Only return orders with `updatedAt >= updatedSince`. |
Sample Request
GET https://orderengine.red/api/external/v1/purchase-orders Authorization: Bearer vek_<prefix>_<secret>
Sample Response
{
"vendorId": "vendor_123",
"items": [
{
"id": "po_123",
"orderNumber": "PO-1001",
"status": "submitted",
"subtotal": 1234.56,
"emailSentAt": "2026-03-11T10:00:00.000Z",
"createdAt": "2026-03-11T09:00:00.000Z",
"updatedAt": "2026-03-11T10:00:00.000Z",
"currentRevision": {
"id": "por_1",
"revisionNumber": 2,
"status": "SENT",
"createdAt": "2026-03-11T09:30:00.000Z",
"updatedAt": "2026-03-11T10:00:00.000Z"
}
}
],
"limit": 50,
"cursor": null,
"nextCursor": "MjAyNi0wMy0xMVQwOTowMDowMC4wMDBafHBvXzEyMw",
"hasMore": true,
"createdSince": "2026-03-01T00:00:00.000Z",
"updatedSince": "2026-03-12T00:00:00.000Z",
"count": 1
}Error Example
{
"error": {
"message": "Unauthorized: API key required",
"code": "UNAUTHORIZED"
},
"requestId": "req_123"
}Behavior Notes
- Sorted server-side by newest `createdAt` then `id` descending.
- Cursor pagination is supported via `cursor` and `nextCursor` with newest-first ordering.
- Operational changes are delivered via webhooks. Polling endpoints should only be used for reconciliation or recovery scenarios.
- `count` is the number of items returned in this response page, not a total historical count.
- `createdSince` and `updatedSince` support incremental sync windows and can be combined.
GET /api/external/v1/purchase-orders/:id
Returns full order detail including current revision items, delivery plan, and active documents.
Required scope: vendor:orders:read
Query Parameters
None.
Sample Request
GET https://orderengine.red/api/external/v1/purchase-orders/:id Authorization: Bearer vek_<prefix>_<secret>
Sample Response
{
"order": {
"id": "po_123",
"vendorId": "vendor_123",
"status": "submitted",
"currentRevision": {
"items": [ ... ],
"deliveryPlan": [ ... ],
"documents": [ ... ],
"vendorResponses": [
{
"id": "sendlog_1",
"action": "accepted",
"notes": "Can fulfill on next route day",
"respondedBy": "vendor_123",
"respondedAt": "2026-03-12T03:05:28.827Z"
}
],
"fulfillmentUpdates": [
{
"id": "sendlog_2",
"status": "scheduled",
"plannedDeliveryDate": "2026-03-13",
"deliveryWindow": { "start": "09:00", "end": "12:00" },
"routeCode": "north-route-a",
"notes": "First stop on Friday run",
"updatedBy": "vendor-api-key:key_123",
"updatedAt": "2026-03-12T04:05:28.827Z"
}
],
"receivingUpdates": [
{
"id": "sendlog_4",
"status": "received",
"partial": false,
"receiverName": "Dock Manager",
"receivedAt": "2026-03-12T11:30:00.000Z",
"notes": "All good",
"discrepancySummary": null,
"receivedItems": [
{ "revisionItemId": "revision_item_123", "receivedUnits": 6 }
],
"orderedUnits": 6,
"receivedUnitsAfterReceipt": 6,
"updatedBy": "vendor-api-key:key_123",
"updatedAt": "2026-03-12T11:30:00.000Z"
}
],
"statusHistory": [
{
"id": "sendlog_3",
"previousStatus": "submitted",
"newStatus": "acknowledged",
"reason": "vendor_response",
"action": "accepted",
"fulfillmentStatus": null,
"partial": null,
"receiverName": null,
"receivedAt": null,
"discrepancySummary": null,
"notes": "Can fulfill on next route day",
"changedBy": "vendor-api-key:key_123",
"changedAt": "2026-03-12T03:05:28.827Z"
}
]
}
}
}Error Example
{
"error": {
"message": "Purchase order not found",
"code": "PURCHASE_ORDER_NOT_FOUND"
},
"requestId": "req_123"
}Behavior Notes
- Tenant isolation is enforced by API key vendor principal.
- Cross-vendor or unknown order returns `404`.
POST /api/external/v1/purchase-orders/:id/reissue
Creates a new purchase order revision through the scoped vendor reissue command.
Required scope: vendor:orders:write OR vendor:orders:reissue:write
Query Parameters
None.
Sample Request
POST https://orderengine.red/api/external/v1/purchase-orders/:id/reissue
Authorization: Bearer vek_<prefix>_<secret>
Idempotency-Key: 8c7d8a7e-3d61-4f42-a4a8-1fba12f8d7fd
Content-Type: application/json
{
"editReason": "Adjust quantities after stock recount",
"notes": "Updated after vendor confirmation",
"itemUpdates": [
{
"revisionItemId": "poi_revision_1",
"units": 12,
"unitPrice": 99.5
}
],
"deliveryPlan": [
{
"deliveryEndpointId": "dep_1",
"productId": "prod_123",
"allocatedUnits": 12
}
]
}Sample Response
{
"purchaseOrder": {
"id": "po_123",
"status": "submitted",
"currentRevisionId": "por_3"
},
"revision": {
"id": "por_3",
"revisionNumber": 3,
"status": "REVIEW_REQUIRED"
}
}Error Example
{
"error": {
"message": "editReason is required for reissue",
"code": "VALIDATION_ERROR"
},
"requestId": "req_123"
}Behavior Notes
- Synchronous API call: returns when revision creation flow completes.
- Supports `Idempotency-Key`; same key + same payload replays stored response.
- Same key + different payload returns `409`.
- Delivery endpoint IDs must be active and scoped to the current purchase order stores.
- Created revisions and send logs record `vendor-api-key:<keyId>` as the actor/source.
- Successful responses mirror the vendor reissue flow; errors are normalized to the external API error envelope.
- No explicit lifecycle-state gate at the external route layer; validation occurs in the reissue command.
POST /api/external/v1/purchase-orders/:id/respond
Records vendor acknowledgment/response for a purchase order and updates top-level order status.
Required scope: vendor:orders:write OR vendor:orders:respond:write
Query Parameters
None.
Sample Request
POST https://orderengine.red/api/external/v1/purchase-orders/:id/respond
Authorization: Bearer vek_<prefix>_<secret>
Idempotency-Key: 8c7d8a7e-3d61-4f42-a4a8-1fba12f8d7fd
Content-Type: application/json
{
"action": "accepted",
"notes": "Can fulfill on next route day"
}Sample Response
{
"order": {
"id": "po_123",
"status": "acknowledged",
"updatedAt": "2026-03-12T03:05:28.827Z"
},
"response": {
"action": "accepted",
"notes": "Can fulfill on next route day",
"respondedAt": "2026-03-12T03:05:28.827Z",
"respondedBy": "vendor_123",
"responseLogId": "sendlog_123",
"statusChangeLogId": "sendlog_124"
}
}Error Example
{
"error": {
"message": "action is required and must be one of: accepted, partially_accepted, rejected, needs_revision",
"code": "VALIDATION_ERROR"
},
"requestId": "req_123"
}Behavior Notes
- Supports `Idempotency-Key`; same key + same payload replays stored response.
- Same key + different payload returns `409`.
- Actions: `accepted | partially_accepted | rejected | needs_revision`.
- `accepted` and `partially_accepted` map order status to `acknowledged`; `rejected` and `needs_revision` map to `submitted`.
- Responses are blocked for terminal or delivery-execution states (`received`, `cancelled`, `delivered`, `out_for_delivery`).
PATCH /api/external/v1/purchase-orders/:id/fulfillment
Records delivery planning state (schedule/route/hold readiness) for a purchase order.
Required scope: vendor:orders:write OR vendor:orders:fulfillment:write
Query Parameters
None.
Sample Request
PATCH https://orderengine.red/api/external/v1/purchase-orders/:id/fulfillment
Authorization: Bearer vek_<prefix>_<secret>
Idempotency-Key: 8c7d8a7e-3d61-4f42-a4a8-1fba12f8d7fd
Content-Type: application/json
{
"status": "scheduled",
"plannedDeliveryDate": "2026-03-13",
"deliveryWindow": { "start": "09:00", "end": "12:00" },
"routeCode": "north-route-a",
"notes": "First stop on Friday run"
}Sample Response
{
"order": {
"id": "po_123",
"status": "scheduled",
"updatedAt": "2026-03-12T04:05:28.827Z"
},
"fulfillment": {
"status": "scheduled",
"plannedDeliveryDate": "2026-03-13",
"deliveryWindow": { "start": "09:00", "end": "12:00" },
"routeCode": "north-route-a",
"notes": "First stop on Friday run",
"updatedAt": "2026-03-12T04:05:28.827Z",
"updatedBy": "vendor_123",
"fulfillmentLogId": "sendlog_124",
"statusChangeLogId": "sendlog_125"
}
}Error Example
{
"error": {
"message": "status is required and must be one of: unscheduled, scheduled, ready_for_route, out_for_delivery, delivered, hold",
"code": "VALIDATION_ERROR"
},
"requestId": "req_123"
}Behavior Notes
- Supports `Idempotency-Key`; same key + same payload replays stored response.
- Same key + different payload returns `409`.
- Statuses: `unscheduled | scheduled | ready_for_route | out_for_delivery | delivered | hold`.
- `plannedDeliveryDate` must use `YYYY-MM-DD`; delivery windows use 24h `HH:mm` with `start < end`.
- Status progression maps to order lifecycle (`scheduled`, `out_for_delivery`, `delivered`) with transition guards.
POST /api/external/v1/purchase-orders/:id/mark-delivered
Marks an order as delivered after drop completion.
Required scope: vendor:orders:write OR vendor:orders:receive:write
Query Parameters
None.
Sample Request
POST https://orderengine.red/api/external/v1/purchase-orders/:id/mark-delivered
Authorization: Bearer vek_<prefix>_<secret>
Idempotency-Key: 8c7d8a7e-3d61-4f42-a4a8-1fba12f8d7fd
Content-Type: application/json
{
"deliveredAt": "2026-03-12T09:00:00.000Z",
"notes": "Delivered on route A"
}Sample Response
{
"order": {
"id": "po_123",
"status": "delivered",
"updatedAt": "2026-03-12T09:00:00.000Z"
},
"delivery": {
"deliveredAt": "2026-03-12T09:00:00.000Z",
"notes": "Delivered on route A",
"updatedAt": "2026-03-12T09:00:00.000Z",
"updatedBy": "vendor_123",
"deliveryLogId": "sendlog_200",
"statusChangeLogId": "sendlog_201"
}
}Error Example
{
"error": {
"message": "Cannot transition purchase order from 'submitted' to 'delivered'",
"code": "INVALID_ORDER_STATE"
},
"requestId": "req_123"
}Behavior Notes
- Supports `Idempotency-Key`; same key + same payload replays stored response.
- Transition is guarded and typically requires order to be `out_for_delivery` first.
- Emits `purchase_order_status_changed` webhook when status transitions.
POST /api/external/v1/purchase-orders/:id/mark-received
Marks an order as received or partially received with receipt evidence.
Required scope: vendor:orders:write OR vendor:orders:receive:write
Query Parameters
None.
Sample Request
POST https://orderengine.red/api/external/v1/purchase-orders/:id/mark-received
Authorization: Bearer vek_<prefix>_<secret>
Idempotency-Key: 8c7d8a7e-3d61-4f42-a4a8-1fba12f8d7fd
Content-Type: application/json
{
"partial": false,
"receiverName": "Dock Manager",
"receivedAt": "2026-03-12T11:30:00.000Z",
"notes": "All good",
"discrepancySummary": null,
"receivedItems": [
{ "revisionItemId": "revision_item_123", "receivedUnits": 6 }
]
}Sample Response
{
"order": {
"id": "po_123",
"status": "received",
"updatedAt": "2026-03-12T11:30:00.000Z"
},
"receipt": {
"partial": false,
"receiverName": "Dock Manager",
"receivedAt": "2026-03-12T11:30:00.000Z",
"notes": "All good",
"discrepancySummary": null,
"receivedItems": [
{ "revisionItemId": "revision_item_123", "receivedUnits": 6 }
],
"orderedUnits": 6,
"receivedUnitsAfterReceipt": 6,
"updatedAt": "2026-03-12T11:30:00.000Z",
"updatedBy": "vendor_123",
"receiptLogId": "sendlog_202",
"statusChangeLogId": "sendlog_203"
}
}Error Example
{
"error": {
"message": "Cannot transition purchase order from 'scheduled' to 'received'",
"code": "INVALID_ORDER_STATE"
},
"requestId": "req_123"
}Behavior Notes
- Supports both full receipt (`received`) and partial receipt (`partially_received`) via `partial` flag.
- Partial receipts require exact current-revision item IDs and positive received-unit quantities; full receipts default to all remaining units.
- Captures receiver metadata and discrepancy summary for auditability.
- Use this endpoint only if your integration is the receiving system of record; otherwise keep `vendor:orders:receive:write` ungranted and treat receipt as internal/store-side.
- Emits `purchase_order_status_changed` webhook when status transitions.
GET /api/external/v1/purchase-orders/:id/documents
Returns document metadata for the order's current revision with download links.
Required scope: vendor:orders:read OR vendor:orders:documents:read
Query Parameters
| Name | Type | Required | Notes |
|---|---|---|---|
includeInactive | boolean | no | When true, includes superseded/inactive docs. |
Sample Request
GET https://orderengine.red/api/external/v1/purchase-orders/:id/documents Authorization: Bearer vek_<prefix>_<secret>
Sample Response
{
"orderId": "po_123",
"currentRevisionId": "por_3",
"includeInactive": false,
"count": 1,
"items": [
{
"id": "podoc_1",
"revisionId": "por_3",
"type": "VENDOR_FACING",
"status": "ACTIVE",
"fileName": "PO-1001-vendor.pdf",
"generatedAt": "2026-03-12T03:05:28.827Z",
"downloadUrl": "/api/external/v1/purchase-orders/po_123/documents/podoc_1/download"
}
]
}Error Example
{
"error": {
"message": "Purchase order not found",
"code": "PURCHASE_ORDER_NOT_FOUND"
},
"requestId": "req_123"
}Behavior Notes
- Default response includes only `ACTIVE` documents.
- Download links are external API paths and require API key auth.
- Document metadata is scoped to the order's current revision.
GET /api/external/v1/purchase-orders/:id/documents/:documentId/download
Downloads a purchase order document as PDF.
Required scope: vendor:orders:read OR vendor:orders:documents:read
Query Parameters
| Name | Type | Required | Notes |
|---|---|---|---|
includeInactive | boolean | no | When true, allows superseded/inactive docs. |
Sample Request
GET https://orderengine.red/api/external/v1/purchase-orders/:id/documents/:documentId/download Authorization: Bearer vek_<prefix>_<secret>
Sample Response
Binary PDF response (Content-Type: application/pdf)
Error Example
{
"error": {
"message": "Purchase order document not found",
"code": "DOCUMENT_NOT_FOUND"
},
"requestId": "req_123"
}Behavior Notes
- Returns `application/pdf` with attachment disposition.
- Document access is constrained to vendor + purchase order scope.
GET /api/external/v1/catalog/products
Returns vendor product catalog rows with product metadata and effective pricing.
Required scope: vendor:catalog:read
Query Parameters
| Name | Type | Required | Notes |
|---|---|---|---|
q | string | no | Case-insensitive search over SKU/name/brand/category. |
includeInactive | boolean | no | Default false. |
limit | number | no | Default 100, min 1, max 250. |
cursor | string | no | Opaque cursor token from previous response. |
createdSince | ISO-8601 UTC timestamp | no | Only return rows with `createdAt >= createdSince`. |
updatedSince | ISO-8601 UTC timestamp | no | Only return rows with `updatedAt >= updatedSince`. |
Sample Request
GET https://orderengine.red/api/external/v1/catalog/products Authorization: Bearer vek_<prefix>_<secret>
Sample Response
{
"vendorId": "vendor_123",
"count": 1,
"limit": 100,
"cursor": null,
"nextCursor": "MjAyNi0wMy0xMVQwOTowMDowMC4wMDBafHZwXzE",
"hasMore": true,
"createdSince": "2026-03-01T00:00:00.000Z",
"updatedSince": "2026-03-10T00:00:00.000Z",
"query": "gummy",
"includeInactive": false,
"items": [
{
"availability": {
"isAvailableForOrder": true,
"availableUnits": 240,
"availableCases": 24,
"minOrderCaseQty": 1,
"orderMultiple": 1,
"availabilityReason": null
},
"vendorProductId": "vp_1",
"productId": "prod_1",
"vendorSku": "VEN-123",
"productSku": "SKU-123",
"productName": "Blueberry Gummies",
"brand": "Example",
"category": "edible",
"unitPrice": 9.5,
"casePrice": 95,
"unitsPerCase": 10
}
]
}Error Example
{
"error": {
"message": "Forbidden: missing required scopes",
"code": "MISSING_SCOPE"
},
"missingScopes": ["vendor:catalog:read"],
"requestId": "req_123"
}Behavior Notes
- Server-side sort is by newest `updatedAt` then `id` descending.
- Cursor pagination is supported via `cursor` and `nextCursor`.
- Continue pagination while `hasMore` is `true`, always passing prior `nextCursor` as the next request `cursor`.
- `count` is the number of items returned in this response page.
- Availability constraints are returned under `availability` for each catalog row.
GET /api/external/v1/velocity/summary
Returns velocity summary for the authenticated vendor (top movers, slow movers, reorder candidates).
Required scope: vendor:velocity:read
Query Parameters
| Name | Type | Required | Notes |
|---|---|---|---|
dateRange | 7d | 14d | 30d | 90d | no | Default 30d. |
storeIds | csv | no | Optional store filters. |
categories | csv | no | Optional category filters. |
brands | csv | no | Optional brand filters. |
search | string | no | Name/SKU/brand search. |
onlyActive | boolean | no | Default true. |
inStockOnly | boolean | no | Default false. |
outliersOnly | boolean | no | Default false. |
Sample Request
GET https://orderengine.red/api/external/v1/velocity/summary Authorization: Bearer vek_<prefix>_<secret>
Sample Response
{
"vendor": {
"id": "vendor_123",
"name": "Vendor Name"
},
"averageVelocity": 2.5,
"totalUnitsSold": 1200,
"topMovers": [ ... ],
"slowMovers": [ ... ],
"reorderCandidates": [ ... ]
}Error Example
{
"error": {
"message": "Vendor not found in reporting scope",
"code": "VENDOR_NOT_FOUND"
},
"requestId": "req_123"
}Behavior Notes
- `vendorIds` input is ignored; vendor scope is forced from API key principal.
- Useful for reorder planning; operational events remain in Webhooks docs.
Global Error Statuses
Error examples use { error: { message, code } }. Responses include x-request-id header.
All responses include header x-request-id. Provide this value when contacting support.
401: Missing/invalid API key.403: Valid key but missing scope.404: Resource missing in vendor scope.409: Idempotency conflict (same key, different payload).429: Per-key rate limit exceeded.500: Internal server failure.