API

Orders API

`POST /api/orders/sync` is the order intake endpoint for the core EntryGo protocol.

Use it to submit or refresh the account-scoped order records that planning will consume later. The response returns EntryGo order IDs. Those IDs, not your external order references, are what POST /api/exports/plan expects.

Machine-readable contract:

Related docs:

#Before you call this endpoint

Order sync is not product creation.

Each line item references an existing EntryGo productId, so the expected flow is:

  1. create or sync products first
  2. call POST /api/orders/sync
  3. store the returned EntryGo order IDs
  4. pass those order IDs into export planning

#Authentication

Send a bearer API key:

http
Authorization: Bearer <api-key>

Rules:

  • accountId in the body must match the authenticated account scope
  • missing or invalid keys return 401 INVALID_API_KEY
  • mismatched accountId returns 403 INVALID_ACCOUNT_SCOPE

#POST /api/orders/sync

#Purpose

Sync one or more orders into EntryGo for later export planning.

The current implementation:

  • upserts orders by externalId within the authenticated account
  • recalculates order value from line items
  • replaces synced line items on update
  • returns the stable order representation that planning expects downstream

#Request body

Top-level fields:

Field Type Required Description
accountId string yes EntryGo account ID
items array yes Orders to create or update
idempotencyKey string no Optional body-level idempotency key

Per order in items:

Field Type Required Description
externalId string yes Your source-system order identifier
destinationCountry string yes Two-letter country code
destinationRegion string no Region or state
destinationPostalCode string no Postal code
items array yes Line items
metadata object no Source metadata preserved with the order

Per line item:

Field Type Required Description
productId string yes Existing EntryGo product ID
quantity number yes Quantity for this product
unitValueUsd number yes Unit value in USD

Header:

Header Required Description
Idempotency-Key no Preferred place for idempotency on retriable writes

If both the header and body idempotencyKey are present, the header wins.

#JSON request example

json
{
  "accountId": "acc_123",
  "items": [
    {
      "externalId": "wms-order-1001",
      "destinationCountry": "US",
      "destinationRegion": "CA",
      "destinationPostalCode": "94105",
      "items": [
        {
          "productId": "prod_hoodie_001",
          "quantity": 2,
          "unitValueUsd": 110
        },
        {
          "productId": "prod_cap_002",
          "quantity": 1,
          "unitValueUsd": 35
        }
      ],
      "metadata": {
        "source": "warehouse-wms",
        "wave": "wave-17"
      }
    }
  ]
}

#cURL example

bash
curl -X POST http://localhost:3000/api/orders/sync \
  -H "authorization: Bearer shpbndl_live_..." \
  -H "content-type: application/json" \
  -H "idempotency-key: orders-sync-acc-123-001" \
  -d '{
    "accountId": "acc_123",
    "items": [
      {
        "externalId": "wms-order-1001",
        "destinationCountry": "US",
        "destinationRegion": "CA",
        "destinationPostalCode": "94105",
        "items": [
          {
            "productId": "prod_hoodie_001",
            "quantity": 2,
            "unitValueUsd": 110
          },
          {
            "productId": "prod_cap_002",
            "quantity": 1,
            "unitValueUsd": 35
          }
        ],
        "metadata": {
          "source": "warehouse-wms",
          "wave": "wave-17"
        }
      }
    ]
  }'

#Success response

The stable public response shape is:

Field Type Description
data array Synced EntryGo order records
data[].id string EntryGo order ID to use in planning
data[].accountId string Account scope
data[].externalId string Original source order reference
data[].destinationCountry string Destination country
data[].destinationRegion string or null Destination region
data[].destinationPostalCode string or null Destination postal code
data[].totalValueUsd number Calculated total order value
data[].items array Normalized line items

#JSON response example

json
{
  "data": [
    {
      "id": "ord_123",
      "accountId": "acc_123",
      "externalId": "wms-order-1001",
      "destinationCountry": "US",
      "destinationRegion": "CA",
      "destinationPostalCode": "94105",
      "totalValueUsd": 255,
      "items": [
        {
          "productId": "prod_hoodie_001",
          "quantity": 2,
          "unitValueUsd": 110
        },
        {
          "productId": "prod_cap_002",
          "quantity": 1,
          "unitValueUsd": 35
        }
      ]
    }
  ]
}

#Error response example

Validation failure:

json
{
  "errorCode": "VALIDATION_ERROR",
  "message": "Request validation failed.",
  "field": "items.0.items.0.productId",
  "details": {
    "issues": [
      {
        "path": "items.0.items.0.productId",
        "message": "Required",
        "code": "invalid_type"
      }
    ]
  }
}

Auth scope failure:

json
{
  "errorCode": "INVALID_ACCOUNT_SCOPE",
  "message": "Payload accountId does not match API key scope.",
  "details": {
    "apiKeyAccountId": "acc_123",
    "payloadAccountId": "acc_999"
  }
}

#Behavioral notes

#Idempotency

  • Use Idempotency-Key for retriable sync operations.
  • Reuse the same key only for the same logical write.
  • If the client times out after sending the request, retry with the same key first.

#Intake expectations

  • Planning expects EntryGo order IDs from this response.
  • Do not plan with only your external order references.
  • Keep a local mapping from externalId to EntryGo id.

#Stable contract vs internal detail

The documented contract is the stable subset shown above. Do not build against undocumented nested persistence fields.

#Common errors

Status errorCode Meaning What to do
400 INVALID_REQUEST Body is not valid JSON Fix serialization and resend
400 VALIDATION_ERROR JSON shape is invalid Correct fields before retrying
401 INVALID_API_KEY Missing or invalid API key Fix auth before retrying
403 INVALID_ACCOUNT_SCOPE accountId does not match key scope Use the right key or payload

#Notes for AI agents and automation clients

  • Treat POST /api/orders/sync as the source of truth for EntryGo order IDs.
  • Persist the returned id values and use those in later planning calls.
  • On ambiguous write outcomes, retry with the same idempotency key before inventing new orders.
  • Branch on errorCode, not only the human-readable message.