Public API Order Hub — Orders & Order Lines Guide

How to manage orders and their line items on the Retraced platform via the Public API.

The Order Hub exposes orders and their line items:

  1. Orders (/api/v2/orders) — the commercial document: order number, buyer, supplier, dates, status, and its line items.
  2. Order lines (/api/v2/order-lines) — the line items on an order (which style, how much, in what unit), exposed read-only (GET only).

An order line only ever exists as part of an order, so all line writes happen through the order: create lines nested in POST /orders, and add/change/remove them later with PATCH /orders/:id. Deleting an order deletes its lines. You read lines back via the GET /order-lines endpoints.

Migration note: the previous POST / PATCH / DELETE /api/v2/order-lines endpoints have been removed. Manage lines via the order endpoints described below. The GET line endpoints are unchanged.

Setup

# Base URL
BASE_URL="https://publicapi.retraced.com/api/v2"

# Authentication — use your company API key
API_KEY="your-company-api-key"

All examples use curl. The API key is passed via the companyapikey header. Every operation is scoped to the company the API key belongs to — you can only see and manage your own orders.


Orders

Create an order

curl -X POST "$BASE_URL/orders" \
  -H "companyapikey: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "orderNumber": "PO-2026-0042",
    "status": "IN_PROGRESS",
    "orderSubType": "STANDARD",
    "source": "ERP",
    "tags": ["priority"],
    "buyerCompanyId": "<buyer-company-id>",
    "supplierCompanyId": "<supplier-company-id>",
    "receiverCompanyId": "<receiver-company-id>",
    "vendorCompanyId": "<vendor-company-id>",
    "factory": "<factory-company-id>",
    "buyerFacilityProcess": "Quality inspection",
    "supplierFacilityProcess": "Weaving",
    "receiverFacilityProcess": "Washing & finishing",
    "orderDate": "2026-07-01",
    "deliveryDate": "2026-09-15",
    "agreedDeliveryDate": "2026-09-10",
    "expectedShippingDate": "2026-08-28",
    "shippingDate": "2026-08-30",
    "expectedDeliveryDate": "2026-09-15",
    "shipmentReference": "SHIP-2026-0042",
    "internalResponsiblePersons": ["<user-id-or-email>"],
    "season": "FW26",
    "counterpartyOrderNumberRef": "WW-SO-2026-118",
    "lines": [
      {
        "orderLineNumber": "PO-2026-0042-PACKAGING",
        "styleId": "<style-id>",
        "quantity": 300,
        "unit": "PIECES",
        "secondaryQuantity": 120.5,
        "secondaryUnit": "KILOGRAM"
      }
    ]
  }'

Only orderNumber, buyerCompanyId and supplierCompanyId are required — every other field can be omitted. Nested lines are created atomically with the order and are returned in the create response (and on GET /orders/:id), each carrying its server-assigned id and lineNo.

Request body fields:

Field Type Required Notes
orderNumber string yes 1–255 characters (exact match — no trimming or case folding). Must be unique within your company for the same order type — a duplicate returns 400 with code order_number_already_existing.
lines array no Nested order lines, created atomically with the order (a failing line rolls the whole request back). Each entry takes the per-line fields minus id. May be omitted or empty; lines can also be added later via PATCH /orders/:id.
buyerCompanyId string yes Company ID of the buyer (max 36 chars).
supplierCompanyId string yes Company ID of the supplier (max 36 chars).
orderSubType enum no STANDARD, REPEAT, COMMIT, SAMPLE or EXTRACTION_SPLIT.
status enum no IN_PROGRESS, IN_REVIEW or COMPLETED.
tags string[] no Free-form tags.
source string no Where the order originated (max 255 chars).
receiverCompanyId / vendorCompanyId / factory string no Additional party company IDs (max 36 chars each).
buyerFacilityProcess / supplierFacilityProcess / receiverFacilityProcess string no Facility process references (max 255 chars each).
orderDate, deliveryDate, agreedDeliveryDate, expectedShippingDate, shippingDate, expectedDeliveryDate, actualDeliveryDate date no ISO calendar date, YYYY-MM-DD.
shipmentReference string no Max 255 chars.
internalResponsiblePersons string[] no Email addresses or user IDs of users in your company — the server resolves each email to a user ID before saving. An unknown email/ID returns 404 (responsible_person_not_found).
internalResponsiblePerson string no Deprecated — use internalResponsiblePersons. Accepts a single email/user ID, auto-mapped to a one-element internalResponsiblePersons. Do not send both fields (400). An empty string is rejected with 400.
season string no e.g. FW26.
counterpartyOrderNumberRef string no Your counterparty's own order number reference.

orderType is computed by the server — you never send it. It is derived from how the buyer/supplier relate to your (authenticated) company: you are the buyer → PURCHASE_ORDER, you are the supplier → SALES_ORDER, you are both → INTERNAL_ORDER.

Response (200):

{
  "metadata": { "success": true },
  "data": {
    "id": "order_01KWHF7TD318JZA3KM9A9E9979",
    "forCompanyId": "<your-company-id>",
    "orderNumber": "PO-2026-0042",
    "orderType": "PURCHASE_ORDER",
    "orderSubType": "STANDARD",
    "status": "IN_PROGRESS",
    "tags": ["priority"],
    "source": "ERP",
    "buyerCompanyId": "<buyer-company-id>",
    "supplierCompanyId": "<supplier-company-id>",
    "receiverCompanyId": "<receiver-company-id>",
    "vendorCompanyId": "<vendor-company-id>",
    "factory": "<factory-company-id>",
    "buyerFacilityProcess": "Quality inspection",
    "supplierFacilityProcess": "Weaving",
    "receiverFacilityProcess": "Washing & finishing",
    "orderDate": "2026-07-01",
    "deliveryDate": "2026-09-15",
    "agreedDeliveryDate": "2026-09-10",
    "expectedShippingDate": "2026-08-28",
    "shippingDate": "2026-08-30",
    "expectedDeliveryDate": "2026-09-15",
    "actualDeliveryDate": null,
    "shipmentReference": "SHIP-2026-0042",
    "internalResponsiblePersons": ["<user-id>"],
    "internalResponsiblePerson": "<user-id>",
    "season": "FW26",
    "counterpartyOrderNumberRef": "WW-SO-2026-118",
    "isArchived": false,
    "tracingStatus": null,
    "createdAt": "2026-07-02T10:30:00.000Z",
    "createdByApiKeyId": "<api-key-id>",
    "updatedAt": "2026-07-02T10:30:00.000Z",
    "lineCount": 1,
    "lines": [
      {
        "id": "ordline_01KWHF7XAY4Q74CAVXYAPJ6FJV",
        "orderLineNumber": "PO-2026-0042-PACKAGING",
        "lineNo": 1,
        "styleId": "<style-id>",
        "quantity": 300,
        "unit": "PIECES",
        "secondaryQuantity": 120.5,
        "secondaryUnit": "KILOGRAM",
        "tracingReflectionOrderId": null,
        "tracingOrderRequestedAt": null
      }
    ]
  }
}

(Response trimmed — every order also carries full createdBy* / updatedBy* audit fields. Fields you never sent come back as null; tracingStatus is system-computed and read-only.)

Store data.id — you need it to manage order lines and for later updates. Order ids are server-generated with an order_ prefix (order lines use ordline_); treat them as opaque strings.

The party fields (who's who)

An order carries up to five company references. Only buyer and supplier are required and enforced (your company must be one of them); the rest are optional descriptive parties. How brands typically use them:

Field Typically represents
buyerCompanyId The company placing the order.
supplierCompanyId The company receiving the order — the agent or supplier on the other side of it.
receiverCompanyId Who takes delivery of the goods. Defaults to the buyer when omitted.
vendorCompanyId An intermediary between the agent and the factory, when one is involved.
factory The company / site where the goods are actually manufactured.

The *FacilityProcess fields (buyerFacilityProcess, supplierFacilityProcess, receiverFacilityProcess) are free-text labels for the process each party performs — they are descriptive, not validated against a list.

These are conventions, not rules the platform enforces. Retraced only checks that your company is the buyer or supplier and that the receiver pair is supplied together (see Create an order); it assigns no other meaning to these fields.

Order status

status (IN_PROGRESS, IN_REVIEW, COMPLETED) is not tied to any Retraced workflow — the platform never acts on it or transitions it for you. Use it to carry whatever state your own process needs.

Date fields

Business dates (orderDate, agreedDeliveryDate, deliveryDate, …) are calendar dates in YYYY-MM-DD with no time or timezone, stored and returned verbatim; createdAt / updatedAt are ISO 8601 UTC timestamps set by the server. See Dates & time for the full rules.

Archiving vs. deleting

An order can be archived (reversible) or deleted (permanent) — they are different:

List orders

curl "$BASE_URL/orders?page=1&limit=20&sort=updatedAt&order=DESC&status=IN_PROGRESS" \
  -H "companyapikey: $API_KEY"

Query parameters:

Parameter Type Default Notes
page number 1 1-based page number.
limit number 20 Page size, 1–100.
sort enum updatedAt updatedAt, createdAt, orderNumber, orderDate or status.
order enum desc ASC or DESC.
type string Filter by computed order type, e.g. PURCHASE_ORDER.
supplier / buyer string Filter by supplier / buyer company ID.
status string Filter by status.
tag string Filter by a single tag.
orderNumber string Filter by order number.
isArchived true | false Filter archived / non-archived orders.
updatedAfterUnixMs / updatedBeforeUnixMs number Unix timestamps in milliseconds; useful for incremental syncs.

Deleted orders are physically removed and never returned.

Response (200):

{
  "metadata": {
    "success": true,
    "pagination": { "page": 1, "limit": 20, "total": 42, "totalPages": 3 }
  },
  "data": [ { "id": "order_01KWHF7TD318JZA3KM9A9E9979", "orderNumber": "PO-2026-0042", "...": "..." } ]
}

Fetch, update, delete

# Fetch one order
curl "$BASE_URL/orders/<order-id>" -H "companyapikey: $API_KEY"

# Partial update — send only the fields you want to change
curl -X PATCH "$BASE_URL/orders/<order-id>" \
  -H "companyapikey: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "COMPLETED", "actualDeliveryDate": "2026-09-12" }'

# Delete (hard — also deletes the order's lines)
curl -X DELETE "$BASE_URL/orders/<order-id>" -H "companyapikey: $API_KEY"

Update an order's lines

Send a lines array on PATCH /orders/:id to declaratively full-sync the order's lines — the array is the desired final set:

Omitting lines entirely leaves the order's lines untouched. Because omission means deletion, always send the complete current set of lines you want to keep — fetch them first via GET /order-lines?orderId=....

curl -X PATCH "$BASE_URL/orders/<order-id>" \
  -H "companyapikey: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "IN_REVIEW",
    "lines": [
      { "id": "ordline_01KWHF7XAY4Q74CAVXYAPJ6FJV", "quantity": 1750 },
      { "id": "ordline_01KWHF7YSW1A1R34E1DMEHMAK5", "secondaryQuantity": null },
      { "styleId": "<style-id>", "quantity": 250, "unit": "PIECES" }
    ]
  }'

In the example the first line is updated, the second clears its secondary quantity (which also clears secondaryUnit), a third line is created, and any other existing line is deleted. The order's scalar fields and its lines are reconciled atomically — if any line fails (e.g. a duplicate orderLineNumber, 409), the whole PATCH rolls back. A bare { "id": "..." } entry keeps that line unchanged (its audit fields are not touched). Fetch the resulting lines with GET /order-lines?orderId=....

See the order line fields for the accepted per-line properties.


Order lines (read-only)

Order lines are created, updated, and deleted only through their parent order (see Create an order and Update an order's lines). Over the Public API they are exposed read-only.

Order line fields

The per-line object used inside a create/update lines array:

Field Type Required Notes
id string on update The line's ordline_ id. Present → update that line; absent → create a new line.
styleId string on create ID of a style owned by your company (max 36 chars), else 404. Required when creating (no id).
quantity number on create Positive; stored with 2 decimal places. Required when creating.
unit enum on create Unit of measure for quantity — one of the unit values below (e.g. PIECES, KILOGRAM, METRE). Required when creating.
orderLineNumber string no 1–255 chars. Must be unique within the order. If omitted on create, auto-generated as {orderNumber}-{orderType}-L{lineNo} (e.g. PO-2026-0042-PURCHASE_ORDER-L1).
secondaryQuantity number | null no Optional second measurement (positive, 2 decimal places). Always a weight in kilograms. Send null on update to clear it.
secondaryUnit enum | null no Always KILOGRAM — the only accepted value. You can omit it: whenever a secondaryQuantity is set the server sets secondaryUnit to KILOGRAM, and clearing the quantity clears the unit too.

lineNo is assigned by the server (1, 2, 3, … per order) and never accepted as input. New lines continue numbering after the order's existing lines. An orderLineNumber that already exists on the order — or that appears twice in one request — returns 409 with code order_not_unique, and the whole write rolls back.

Unit values

unit accepts the unit enum below. Any other value is rejected with 400.

Group Values
Count / textile PIECES, PAIR, PERCENTAGE, DENIER, JUTE, ENGLISH_COUNT, METRIC_COUNT, WORSTED_COUNT, TEX
Weight / mass MILLIGRAM, GRAM, KILOGRAM, METRIC_TON, POUNDS, OUNCE, STONE, SHORT_TON, LONG_TON, HUNDREDWEIGHT, SHORT_HUNDREDWEIGHT, LONG_HUNDREDWEIGHT, DRAM, GRAIN, PENNYWEIGHT, SCRUPLE, GRAM_PER_SQUARE_METER, GRAM_PER_SQUARE_FOOT, GRAM_PER_SQUARE_YARD, OUNCE_PER_SQUARE_YARD
Length MILLIMETRE, CENTIMETRE, DECIMETRE, METRE, INCH, FOOT, YARD, MILE, NAUTICAL_MILE, FURLONG, ROD, FATHOM
Area SQUARE_CENTIMETRE, SQUARE_DECIMETRE, SQUARE_METRE, SQUARE_INCH, SQUARE_FEET, SQUARE_YARD, SQUARE_ROD, SQUARE_MILE, ACRE
Volume MILLILITRE, CENTILITRE, LITRE, CUBIC_DECIMETRE, CUBIC_METRE, CUBIC_INCH, CUBIC_FOOT, CUBIC_YARD, GALLON, QUART, PINT, GILL, FLUID_OUNCE, FLUID_DRAM, MINIM, BUSHEL, PECK, CORD, ACRE_FOOT
Other KILOWATT_HOUR, MOUND

List order lines

# Lines of one order
curl "$BASE_URL/order-lines?orderId=<order-id>&page=1&limit=20" \
  -H "companyapikey: $API_KEY"

# All lines across all your orders (omit orderId)
curl "$BASE_URL/order-lines?page=1&limit=100" -H "companyapikey: $API_KEY"

Pagination works exactly like orders (page 1-based, limit 1–100 default 20, same metadata.pagination envelope). Lines of deleted orders are never returned.

Each line additionally carries two read-only tracing fields — tracingReflectionOrderId (the tracing order this line is reflected into, or null) and tracingOrderRequestedAt (null until tracing is requested) — plus an embedded order summary object (id, orderNumber, orderType, buyerCompanyId, supplierCompanyId, orderDate, updatedAt, updatedByUserName, tracingStatus, tags, source, season). The order object is populated on the list endpoint and is null on GET /order-lines/:lineId.

Fetch a single line

curl "$BASE_URL/order-lines/<line-id>" -H "companyapikey: $API_KEY"

Returns the line (with full audit fields), or 404 when the line does not exist, belongs to another company, or its parent order has been deleted.


End-to-end example

# 1. Create the order together with its two lines — one atomic request
ORDER_ID=$(curl -s -X POST "$BASE_URL/orders" \
  -H "companyapikey: $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "orderNumber": "PO-2026-0042",
    "buyerCompanyId": "<buyer-company-id>",
    "supplierCompanyId": "<supplier-company-id>",
    "lines": [
      {"styleId": "<style-id-1>", "quantity": 1500, "unit": "PIECES"},
      {"styleId": "<style-id-2>", "quantity": 800, "unit": "PIECES"}
    ]
  }' | jq -r '.data.id')

# 2. Read the order's current lines (you need their ids to keep them on the next PATCH)
LINES=$(curl -s "$BASE_URL/order-lines?orderId=$ORDER_ID&limit=100" \
  -H "companyapikey: $API_KEY" | jq -c '[.data[] | {id}]')

# 3. Add a third line while keeping the existing two (full-sync PATCH)
curl -s -X PATCH "$BASE_URL/orders/$ORDER_ID" \
  -H "companyapikey: $API_KEY" -H "Content-Type: application/json" \
  -d "{\"lines\": $(echo "$LINES" | jq -c '. + [{"styleId": "<style-id-3>", "quantity": 250, "unit": "PIECES"}]')}"

# 4. List the order's lines again
curl -s "$BASE_URL/order-lines?orderId=$ORDER_ID" -H "companyapikey: $API_KEY"

Common errors

Status When How to fix
400 Validation failure: missing required field, unknown field, invalid enum value, malformed date (must be YYYY-MM-DD), non-positive quantity, or string too long. Check the field tables above; send only documented fields with valid values.
400 orderNumber already exists in your company for the same order type (code order_number_already_existing) — on create, or on PATCH when changing orderNumber or when a buyerCompanyId/supplierCompanyId change re-derives the order type into a colliding group. Use a different orderNumber. Deleting an order frees its number; archived orders still block reuse.
400 Your company is neither the buyer nor the supplier of the order (code order_owner_not_party), or you sent both internalResponsiblePerson and internalResponsiblePersons, or only one half of the receiver pair. Make your company a party to the order; send responsible persons via one field only; send both receiverCompanyId and receiverFacilityProcess or neither.
401 Missing or invalid companyapikey header. Check the header name (all lowercase) and the key value.
404 The order, line or style does not exist, belongs to another company, or the order has been deleted. Also returned (code responsible_person_not_found) when an entry in internalResponsiblePersons (or the deprecated internalResponsiblePerson) matches no user in your company, and (code invalid_company_id) when a buyerCompanyId/supplierCompanyId/receiverCompanyId/vendorCompanyId/factory is not a company you can reach. On a PATCH lines entry, a referenced line id that isn't on the order returns 404 (code order_line_not_found). Verify the ID; remember deleted orders (and their lines) are permanently removed.
409 orderLineNumber already exists on the same order (code order_not_unique) — when nested lines on create/PATCH carry a duplicate, or a create entry collides with an existing line. Use a different orderLineNumber, or omit it to let the server auto-number the line.