Orders & Parcels (v2)

With the Tracking API v2, your OMS, WMS or ERP sends orders and parcels to Baback. We track each parcel with its carrier, notify the customer and show the parcel on the tracking page.

How it works

  1. Push the order with POST /public/v2/tracking/orders.
  2. Push each parcel shipped for this order with POST /public/v2/tracking/parcels, referencing the order by its externalOrderId. Tracking starts right away.

An order must be pushed before its parcels: a parcel referencing an unknown order is refused with 422 ORDER_NOT_PUSHED.

You can send the same call twice. If the order (same externalOrderId) or the parcel (same externalOrderId and trackingNumber) already exists, you get it back with 200 OK and nothing changes. A new one returns 201 Created. So after a timeout or a network error, just send it again. The API never updates an existing order or parcel.

Authentication

Each shop creates its token in its Baback Tracking dashboard, under Settings › API (shop owners and admins only), with the tracking:write scope to send orders and parcels, and tracking:read to list parcels and follow batch imports. The token starts with bb2_ and tells us which shop the call is for. If you work with several shops, keep one token per shop and use the matching one on each call.

Authorization: Bearer bb2_…
HTTP codeCause
401 UnauthorizedMissing, malformed or invalid token
403 ForbiddenThe token lacks the scope required by the route

Rate limiting

RoutesLimitWindow
Single-item endpoints, GET /parcels, GET /batch/:jobId300 requests60 seconds
POST /orders/batch, POST /parcels/batch2 requests12 seconds

Limits apply per token and per route. Going over returns 429 Too Many Requests with a Retry-After header, in seconds. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. The batch quota (BATCH_SHOP_QUOTA_EXCEEDED, see Batch imports) has no Retry-After: wait for one of your jobs to finish.


POST/public/v2/tracking/orders

Push an order

Creates the order. Its parcels are attached to it later. On the tracking page, the customer finds the order with its orderReference plus their email or zip code.

Unknown fields are ignored.

Required attributes

  • Name
    externalOrderId
    Type
    string
    Description

    Your identifier of the order, unique in the shop (max 255 characters). Parcels reference the order by it.

  • Name
    orderReference
    Type
    string
    Description

    The order number the customer knows (e.g. 1042), exactly as they will type it on the tracking page (max 255 characters).

  • Name
    orderCreatedAt
    Type
    string
    Description

    When the customer placed the order: ISO 8601 date-time with its offset (e.g. 2026-11-12T14:30:00Z or 2026-11-12T15:30:00+01:00).

  • Name
    currency
    Type
    string
    Description

    ISO 4217 currency code (e.g. EUR).

  • Name
    totalAmount
    Type
    number
    Description

    Order total, 0 or more.

  • Name
    customerEmail
    Type
    string
    Description

    Customer email. Tracking notifications are sent to it.

  • Name
    shippingAddress
    Type
    Address
    Description

    Shipping address. See Address.

  • Name
    lineItems
    Type
    LineItem[]
    Description

    From 1 to 250 items. See Line item.

Optional attributes

  • Name
    customerLocale
    Type
    string | null
    Description

    Customer language, e.g. fr, en, pt-BR. Sets the language of the notifications.

  • Name
    channel
    Type
    string | null
    Description

    online or marketplace.

  • Name
    billingAddress
    Type
    Address | null
    Description

    Billing address. See Address.

Request

POST
/public/v2/tracking/orders
curl https://api2.baback.co/public/v2/tracking/orders \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "externalOrderId": "ORD-123456",
    "orderReference": "1042",
    "orderCreatedAt": "2026-11-12T14:30:00Z",
    "currency": "EUR",
    "totalAmount": 89.9,
    "customerEmail": "jane@example.com",
    "customerLocale": "fr",
    "channel": "online",
    "shippingAddress": {
      "firstName": "Jane",
      "lastName": "Doe",
      "address1": "5 avenue des Champs-Élysées",
      "city": "Paris",
      "zip": "75008",
      "countryCode": "FR",
      "phone": "+33698765432"
    },
    "lineItems": [
      {
        "name": "T-shirt Acme",
        "quantity": 2,
        "sku": "TSHIRT-M",
        "price": 29.9,
        "imageUrl": "https://cdn.example.com/tshirt.jpg"
      }
    ]
  }'

Response: 201 Created

{
  "id": "3f1c2a9e-8b4d-4c1e-9a7f-2d5e6b8c0a11",
  "externalOrderId": "ORD-123456",
  "orderReference": "1042",
  "orderCreatedAt": "2026-11-12T14:30:00.000Z",
  "currency": "EUR",
  "totalAmount": 89.9,
  "channel": "online",
  "lineItems": [
    {
      "name": "T-shirt Acme",
      "quantity": 2,
      "sku": "TSHIRT-M",
      "price": 29.9,
      "imageUrl": "https://cdn.example.com/tshirt.jpg"
    }
  ]
}

POST/public/v2/tracking/parcels

Push a parcel

Creates a parcel and starts tracking it with its carrier. Push its order first.

Unknown fields are ignored.

Required attributes

  • Name
    trackingNumber
    Type
    string
    Description

    Carrier tracking number (max 100 characters).

  • Name
    carrierCode
    Type
    string
    Description

    Carrier code. See Carrier codes.

  • Name
    externalOrderId
    Type
    string
    Description

    The externalOrderId of the order this parcel ships (max 255 characters).

  • Name
    customerEmail
    Type
    string
    Description

    Customer email. Tracking notifications are sent to it.

  • Name
    destination
    Type
    Address
    Description

    Delivery address. For a pickup-point delivery, the address of the pickup point. See Address.

  • Name
    lineItems
    Type
    LineItem[]
    Description

    The products in this parcel, from 1 to 250. See Line item.

Optional attributes

  • Name
    carrierProductCode
    Type
    string | null
    Description

    Baback code of the carrier service, e.g. livraison-domicile or point-retrait for Colissimo. It must belong to carrierCode, otherwise 422 CARRIER_PRODUCT_UNKNOWN. We recommend leaving it out and sending shippingLine: Baback then finds the service from the shipping method, using the shop's settings.

  • Name
    shippingLine
    Type
    object | null
    Description

    The shipping method chosen by the customer: code and title, both optional strings (e.g. { "code": "colissimo_relay", "title": "Colissimo pickup point" }).

  • Name
    customerLocale
    Type
    string | null
    Description

    Customer language, e.g. fr, en, pt-BR. When left out, the parcel takes the order's, then the shop's default language.

  • Name
    channel
    Type
    string | null
    Description

    online or marketplace. When left out, the parcel takes the order's.

In a parcel, a line item also accepts priceCurrency, plus shopPrice and shopPriceCurrency (the same unit price in the shop currency, always together).

Request

POST
/public/v2/tracking/parcels
curl https://api2.baback.co/public/v2/tracking/parcels \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "trackingNumber": "8C12345678901",
    "carrierCode": "colissimo",
    "externalOrderId": "ORD-123456",
    "customerEmail": "jane@example.com",
    "customerLocale": "fr",
    "destination": {
      "firstName": "Jane",
      "lastName": "Doe",
      "address1": "5 avenue des Champs-Élysées",
      "city": "Paris",
      "zip": "75008",
      "countryCode": "FR"
    },
    "lineItems": [
      { "name": "T-shirt Acme", "quantity": 2, "sku": "TSHIRT-M", "price": 29.9 }
    ],
    "shippingLine": { "code": "colissimo_home", "title": "Colissimo home delivery" }
  }'

Response: 201 Created

{
  "id": "8d2e4f6a-1b3c-4d5e-8f90-a1b2c3d4e5f6",
  "shopId": "shop_1",
  "externalOrderId": "ORD-123456",
  "orderReference": "1042",
  "trackingNumber": "8C12345678901",
  "trackingNumbers": ["8C12345678901"],
  "carrierCode": "colissimo",
  "carrierProductCode": "livraison-domicile",
  "lastStatus": "NONE",
  "carrierLastStatus": null,
  "estimatedDeliveryDateWindow": null,
  "deliveryDate": null,
  "collectedAt": null,
  "endDepositDate": null,
  "destination": {
    "firstName": "Jane",
    "lastName": "Doe",
    "name": "Jane Doe",
    "company": "",
    "address1": "5 avenue des Champs-Élysées",
    "address2": null,
    "city": "Paris",
    "zip": "75008",
    "province": "",
    "provinceCode": "",
    "country": "FR",
    "countryCode": "FR",
    "phone": "",
    "latitude": null,
    "longitude": null,
    "isPickupPoint": null
  },
  "lineItems": [
    {
      "lineItemId": null,
      "name": "T-shirt Acme",
      "imageUrl": "",
      "sku": "TSHIRT-M",
      "quantity": 2,
      "price": 29.9,
      "priceCurrency": null,
      "shopPrice": null,
      "shopPriceCurrency": null,
      "productId": null,
      "metadata": null
    }
  ],
  "events": [
    {
      "status": "NONE",
      "createdAt": 1794493800000,
      "label": "Parcel created (public API)",
      "isNotificationSkipped": false,
      "notificationSkippedReason": null,
      "notifications": []
    }
  ],
  "createdAt": 1794493800000,
  "updatedAt": 1794493800000
}

Response: 422 Unprocessable Entity

{
  "message": "Order \"ORD-123456\" is unknown to this shop: push it to POST /public/v2/tracking/orders first",
  "code": "ORDER_NOT_PUSHED",
  "statusCode": 422,
  "timestamp": "2026-11-12T14:30:00.000Z"
}

GET/public/v2/tracking/parcels

List parcels

Lists the parcels created since a date, oldest first. Use it to check that nothing is missing: compare with what you sent, and send again whatever is not there. Needs the tracking:read scope.

Query parameters

  • Name
    since
    Type
    string
    Description

    Required. A date (2026-11-01, midnight UTC) or a date-time with its offset.

  • Name
    externalOrderId
    Type
    string
    Description

    Only the parcels of this order.

  • Name
    trackingNumber
    Type
    string
    Description

    Only the parcels with this tracking number.

  • Name
    limit
    Type
    number
    Description

    Page size, from 1 to 250. Default 100.

  • Name
    cursor
    Type
    string
    Description

    The nextCursor of the previous page. Treat it as an opaque string.

The response holds data (parcels, same shape as above) and nextCursor, null on the last page. A parcel is dated a few seconds before it is saved, so start each run a little before the end of the previous one.

Request

GET
/public/v2/tracking/parcels
curl "https://api2.baback.co/public/v2/tracking/parcels?since=2026-11-01&limit=100" \
  -H "Authorization: Bearer {token}"

Response: 200 OK

{
  "data": [{ "id": "8d2e4f6a-1b3c-4d5e-8f90-a1b2c3d4e5f6", "trackingNumber": "8C12345678901", "...": "..." }],
  "nextCursor": "3f1c2a9e-8b4d-4c1e-9a7f-2d5e6b8c0a11"
}

Batch imports

To import past orders and parcels, send them in batches of up to 500 with POST /public/v2/tracking/orders/batch and POST /public/v2/tracking/parcels/batch. We process them in the background. The API answers 202 Accepted with a jobId. Call GET /public/v2/tracking/batch/:jobId until its status is completed or failed.

POST /public/v2/tracking/orders/batch

{
  "orders": [{ "externalOrderId": "ORD-000001", "...": "same fields as a single order" }],
  "skipNotifications": true
}

GET /public/v2/tracking/batch/:jobId

{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "itemsCount": 500,
  "processedCount": 500,
  "failedCount": 1,
  "createdAt": "2026-11-12T14:30:00.000Z",
  "startedAt": "2026-11-12T14:30:01.000Z",
  "completedAt": "2026-11-12T14:31:10.000Z",
  "errors": [
    { "index": 42, "externalId": "ORD-000043", "code": "ORDER_NOT_PUSHED", "error": "…" }
  ]
}
  • Import orders before parcels, as for single calls.
  • skipNotifications: true marks the items as history. Orders trigger no "order created" email, SMS or webhook. For parcels, nothing notifies the customer during the first 24 hours, and past carrier events, delay alerts and reminders never do. A new carrier event more than 24 hours after the import notifies as usual. It also applies to parcels that already exist in Baback. You can't undo it, so only use it for parcels already delivered, never for parcels still on their way.
  • We check the whole batch before accepting it. If one item is invalid, the batch is refused with 400 and nothing is imported. Once accepted, each item succeeds or fails on its own. Failures are listed in errors (the first 100).
  • BATCH_ITEM_TIMEOUT means we don't know if the item was created. Send it again: a duplicate is never created.
  • Limits: 500 items and 5,000 line items per batch, 3 MB body, 5 batch jobs pending or running per shop (429 BATCH_SHOP_QUOTA_EXCEEDED beyond). A finished job stays readable for up to 24 hours (7 days if it failed), and may be removed sooner during heavy imports. After that, GET /batch/:jobId returns 404: read the result as soon as the job is finished.

Address

  • Name
    firstName
    Type
    string
    Description
    Required.
  • Name
    lastName
    Type
    string
    Description
    Required.
  • Name
    address1
    Type
    string
    Description
    Required.
  • Name
    city
    Type
    string
    Description
    Required.
  • Name
    zip
    Type
    string
    Description
    Required.
  • Name
    countryCode
    Type
    string
    Description
    Required. ISO 3166-1 alpha-2 (e.g. FR). Alpha-3 codes and country names are accepted and converted.
  • Name
    company
    Type
    string | null
    Description
    Optional.
  • Name
    address2
    Type
    string | null
    Description
    Optional.
  • Name
    province
    Type
    string | null
    Description
    Optional.
  • Name
    provinceCode
    Type
    string | null
    Description
    Optional.
  • Name
    phone
    Type
    string | null
    Description
    Optional.

Line item

  • Name
    name
    Type
    string
    Description
    Required. Product name (max 500 characters).
  • Name
    quantity
    Type
    number
    Description
    Required. Integer, 1 or more.
  • Name
    sku
    Type
    string | null
    Description
    Optional (max 100 characters).
  • Name
    price
    Type
    number | null
    Description
    Optional. Unit price paid.
  • Name
    imageUrl
    Type
    string | null
    Description
    Optional. http(s) URL of the product image (max 2048 characters), shown on the tracking page.

Carrier codes

colissimo, chronopost, dhl, ups, gls, mondial-relay, fedex, global-e, bpost, dpd, dpd-uk, tnt, canadapost, geodis, brt, colis-prive, seur, hermes, hermes-de, hermes-uk, swiss-post, postnl, sending, poste-italiane.

Tracking statuses

The lastStatus and events[].status values are listed on the Parcels page.


Error handling

HTTP codeCause
400 Bad RequestInvalid body, query or jobId: the response lists each faulty field
401 UnauthorizedMissing or invalid token
403 ForbiddenThe token lacks the required scope
404 Not FoundBatch job unknown, expired, or belonging to another shop
413 Payload Too LargeBody too large (3 MB for a batch)
422 Unprocessable EntityORDER_NOT_PUSHED: the parcel's order was never pushed. CARRIER_PRODUCT_UNKNOWN: carrierProductCode does not belong to the carrier. It can also mean the carrier is not enabled for the shop (see Carrier codes)
429 Too Many RequestsRate limit exceeded, or BATCH_SHOP_QUOTA_EXCEEDED
500 Internal Server ErrorError on our side. Try again later

Response: 400 Bad Request

{
  "message": "Validation failed",
  "errors": [
    { "path": "shippingAddress.countryCode", "message": "Expected an ISO 3166-1 alpha-2 country code, e.g. FR" }
  ]
}