POSTXPOSTX/Developer Docs
v1
Public REST API โ€” v1

POSTX Shipping API

Programmatically create and manage next-day pallet and parcel consignments, retrieve shipping labels, and track deliveries in real time.

๐Ÿš€

Quick to integrate

A single POST creates a consignment and returns a print-ready shipping label in seconds.

๐Ÿ”’

Bearer token secured

Most endpoints require a JWT bearer token. Public tracking is the exception.

๐Ÿ“ฆ

Pallets & Parcels

Support for national and local next-day pallets, parcels, ADR (dangerous goods), and oversized loads.

Base URL

All API requests are made to the following base URL. Resource paths shown throughout this document (for example /consignments) are relative to it.

Base URL
https://api.postx.ai/v1/shipping

Getting started

Three steps to make your first consignment booking.

  1. 1

    Get your credentials

    Contact POSTX to receive your Client ID and Client Secret. Keep these private โ€” they grant full API access to your account.

  2. 2

    Obtain an access token

    Exchange your credentials for a JWT token using the token endpoint below.

  3. 3

    Create your first consignment

    Use the token in the Authorization header to POST a consignment. You will receive a reference ID and a Base64 shipping label.


Integration workflow

End to end, an integration touches five things: your credentials, a created consignment, its shipping label, its tracking link, and the POSTX platform for anything after booking.

  1. 1

    Authenticate

    Exchange your Client ID and Client Secret for a Bearer token. See Authentication.

  2. 2

    Create a consignment

    POST the booking. The response includes a reference ID and a Base64 shipping label. See Create Consignment.

  3. 3

    Retrieve the label

    Decode the label from the create response and print it. There is currently no separate endpoint to fetch it again later, so persist it on receipt.

  4. 4

    Track the delivery

    Call Tracking with the reference to get a tracking URL once the driver has been dispatched.

  5. 5

    Manage on the POSTX platform

    For anything after booking โ€” shipment history, label printing, delivery progress, billing and support โ€” use the POSTX platform. See POSTX platform.


Authentication

The POSTX API uses a Basic credential exchange. You Base64-encode your Client ID and Client Secret and pass them as a Basic Authorization header; the response is a JWT access token, which you then pass on every subsequent request as a Bearer token.

โ„น๏ธThis is not a full RFC 6749 OAuth 2.0 client credentials flow โ€” there is no grant_type parameter and no form-encoded body. Off-the-shelf OAuth 2.0 libraries will not work against it without a custom adapter.

1 โ€” Get an Access Token

POST
/oauth/token

Exchange client credentials for a JWT access token.

Encode your clientId:clientSecret in Base64 and pass it as a Basic Authorization header:

bash
curl -X POST https://api.postx.ai/v1/shipping/oauth/token \
  -H "Authorization: Basic $(echo -n 'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET' | base64)" \
  -H "Content-Type: application/json"

Response:

json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 86400
}

expires_in is in seconds. 86400 seconds = 24 hours โ€” access tokens are valid for 24 hours.

2 โ€” Use the Token

Include the token in every subsequent API request:

bash
curl -X POST https://api.postx.ai/v1/shipping/consignments \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
โš ๏ธTokens expire after 24 hours. Your integration should detect a 401 Unauthorized response and re-authenticate automatically.

Consignments

A consignment is a complete shipping job โ€” it includes pickup location, delivery location, timing, and one or more physical items (shipments). Upon creation, you receive a unique reference ID and a printable shipping label.

โ„น๏ธPaths below are relative to the base URL: https://api.postx.ai/v1/shipping.
POST
/consignments

Create a new consignment and receive a shipping label.

PUT
/consignments/:reference

Update an existing consignment (cancels original, creates new).

DELETE
/consignments/:reference

Cancel a consignment. A cancellation charge may apply.

GET
/capacity

Check available delivery capacity for a given date.

GET
/tracking/:reference

Get a live tracking URL for a consignment. Public โ€” no auth required.


Create Consignment

POST
/consignments

Create a new consignment. Returns a reference ID and a Base64-encoded PDF label.

Request body

FieldTypeDescription
collectionDateTimerequireddatetimeWhen to collect from the sender. Must not be in the past. See the note below the table for the expected format.
collectionAddressrequiredAddressFull pickup address including postcode.
collectionContactrequiredContactName, email, phone, and company of the sender.
collectionInstructionsstringOptional instructions for the driver at pickup.
collectionServiceTyperequiredenumCollection service type. See Service Types section.
collectionServicePricerequirednumberPrice charged for the collection leg (in pence).
deliveryDateTimerequireddatetimeWhen to deliver to the recipient. Must be after collectionDateTime.
deliveryAddressrequiredAddressFull delivery address including postcode.
deliveryContactrequiredContactName, email, phone, and company of the recipient.
deliveryInstructionsstringOptional instructions for the driver at delivery.
deliveryServiceTyperequiredenumDelivery service type window. See Service Types section.
deliveryServicePricerequirednumberPrice charged for the delivery leg (in pence).
shipmentsrequiredShipment[]Array of one or more items in this consignment. At least one is required.
carrierstringOptional carrier override. Defaults to POSTX.
โ„น๏ธcollectionDateTime and deliveryDateTime are Europe/London local time, e.g. 2026-09-01T09:00:00. Whether an explicit UTC offset is also accepted has not been confirmed.
โš ๏ธThere are no universal weekday or noon cut-off rules. Permitted booking days and cut-off times are set per account at contract and vary between customers. Book any time within your agreed windows.

Address object

FieldTypeDescription
addressLine1requiredstringFirst line of the address.
addressLine2stringSecond line (optional).
townrequiredstringTown or city.
countryrequiredstringFull country name, e.g. "United Kingdom".
countryCoderequiredstringLiteral "UK" is expected here. This is not the ISO 3166-1 alpha-2 code (which is "GB") โ€” send "UK" exactly as shown in the examples.
postcoderequiredstringUK postcode. Used to geocode the address.

Shipment object

FieldTypeDescription
referencerequiredstring | numberYour internal reference for this item.
productrequiredProductTypeThe product SKU. See Products section.
quantityrequiredintegerNumber of units.
weightPerProductrequirednumberWeight per unit in kilograms.
descriptionrequiredstringDescription of the goods.
adrrequiredbooleanTrue if the shipment contains dangerous goods (ADR). See the callout below.
valuePerProductrequirednumberDeclared value per unit in pence. Whether this drives insurance cover, a liability cap, or is informational only has not been confirmed โ€” contact dev@postx.ai before relying on it.
productPricerequirednumberPrice per unit in pence, multiplied by quantity to get the line total. See Pricing.
productOverweightPricerequirednumberOverweight surcharge per unit in pence, multiplied by quantity. 0 if not applicable. The weight or dimension threshold that triggers this surcharge is set per account rate card and agreed during onboarding โ€” check your contract rather than assuming a universal threshold.
heightPerProductrequirednumberHeight per unit in metres.
widthPerProductrequirednumberWidth per unit in metres.
lengthPerProductrequirednumberLength per unit in metres.
โš ๏ธDangerous goods (adr: true) โ€” pre-approval, and any UN number, class or packing group paperwork needed outside the API, are agreed with POSTX per contract during onboarding rather than determined by this field. Confirm your account's ADR process before booking dangerous-goods shipments.
โš ๏ธMaximum weight and dimension limits, per unit and per consignment โ€” including what qualifies for PALLET_NEXT_DAY_OVERSIZE โ€” are set per account contract and agreed during onboarding, not published as universal thresholds. Check your contract before booking unusually large or heavy items.

Pricing for this request

Price is determined by two things: the rate card attached to your account, and the service type you book. The rate card determines which service types are available to your account; the service type determines the price. All amounts on this page are in pence, GBP, net of VAT.

Four price fields are sent on every request: productPrice and productOverweightPrice per shipment, plus collectionServicePrice and deliveryServicePrice at the consignment level.

Two pricing modes exist, and they can be mixed within a single consignment:

  • POSTX rate card โ€” leave the line for POSTX to price from your agreed rate card. A price you send as a POSTX-rated line is checked against the rate card and corrected if it does not match.
  • Customer external price โ€” send your own hard-coded price for external comparison. This is recorded as given and is not corrected.

Worked example โ€” a two-unit line at 7500 pence per unit, plus service leg prices:

text
productPrice:               7500   (pence, per unit)
quantity:                       2
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Line total:                 15000   (7500 ร— 2)

+ collectionServicePrice:     500
+ deliveryServicePrice:       800
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Consignment total:          16300   (pence, net of VAT)

collectionServicePrice and deliveryServicePrice live on the consignment, not on each shipment โ€” they are charged once per consignment no matter how many entries are in shipments. A second shipment adds only its own line total:

text
Shipment 1 โ€” productPrice 7500 ร— quantity 2:      15000
Shipment 2 โ€” productPrice 3200 ร— quantity 1:       3200
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Shipment lines total:                              18200

+ collectionServicePrice (once, not per shipment):   500
+ deliveryServicePrice (once, not per shipment):     800
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Consignment total:                                 19500   (pence, net of VAT)

Example request

json
{
  "collectionDateTime": "2026-09-01T09:00:00",
  "collectionAddress": {
    "addressLine1": "10 Industrial Park",
    "addressLine2": "Unit 4",
    "town": "Birmingham",
    "country": "United Kingdom",
    "countryCode": "UK",
    "postcode": "B1 1AA"
  },
  "collectionContact": {
    "name": "Jane Smith",
    "email": "jane@acme.com",
    "contactNumber": "07700900000",
    "company": "Acme Ltd"
  },
  "collectionInstructions": "Ring bell on arrival",
  "collectionServiceType": "PALLET_NEXT_DAY_COLLECTION_STANDARD_ETA",
  "collectionServicePrice": 500,
  "deliveryDateTime": "2026-09-02T10:00:00",
  "deliveryAddress": {
    "addressLine1": "5 High Street",
    "addressLine2": "",
    "town": "London",
    "country": "United Kingdom",
    "countryCode": "UK",
    "postcode": "EC1A 1BB"
  },
  "deliveryContact": {
    "name": "John Doe",
    "email": "john@recipient.com",
    "contactNumber": "07700911111",
    "company": "Recipient Co"
  },
  "deliveryInstructions": "Pump truck required",
  "deliveryServiceType": "PALLET_NEXT_DAY_DELIVERY_AM",
  "deliveryServicePrice": 800,
  "shipments": [
    {
      "reference": 1032964,
      "product": "PALLET_NEXT_DAY_NATIONAL",
      "quantity": 2,
      "weightPerProduct": 221,
      "description": "Industrial equipment",
      "adr": false,
      "valuePerProduct": 350000,
      "productPrice": 7500,
      "productOverweightPrice": 0,
      "heightPerProduct": 1.2,
      "widthPerProduct": 1.0,
      "lengthPerProduct": 1.0
    }
  ]
}

Response

json
{
  "id": "AB12-XY34",
  "label": "JVBERi0xLjMKJeLjz9MKNSAwIG9iagol..."
}
โ„น๏ธThe label field is a Base64-encoded multi-page PDF. Decode it to get a print-ready shipping label โ€” one page per item in your shipment.
โš ๏ธPersist the Base64 label on receipt. There is currently no endpoint to retrieve it later โ€” see .

Update Consignment

PUT
/consignments/:reference

Update a consignment. The original is cancelled and a new one is created with the updated details.

The request body is identical to . The original consignment is automatically cancelled (no cancellation charge is applied) and a new consignment is created. A new shipping label is returned.

โš ๏ธYou cannot update a consignment that has already been routed to a driver (409 Conflict) or already cancelled (409 Conflict).
โš ๏ธPUT returns a new reference and a new label โ€” the original reference is no longer valid. Any label already printed against the original reference must be destroyed and reprinted using the new one. Tracking the old reference afterwards will show it as cancelled.

Response

json
{
  "id": "CD34-ZA56",
  "label": "JVBERi0xLjMKJeLjz9MKNSAwIG9iagol..."
}

Cancel Consignment

DELETE
/consignments/:reference

Cancel a consignment by its reference ID. A cancellation charge may apply.

Pass the consignment reference in the URL path:

bash
curl -X DELETE https://api.postx.ai/v1/shipping/consignments/AB12-XY34 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
โš ๏ธA cancellation charge may apply. The window runs 24 hours from the collection date. The charge itself is set per contract โ€” check your agreement for the exact amount.

Response

json
{
  "cancelled": "2026-09-01T08:45:00.000Z",
  "status": "CANCELLED"
}

Tracking

GET
/tracking/:reference

Retrieve a live tracking URL for a consignment. No authentication required.

This endpoint is publicly accessible โ€” no auth token is required. It returns a tracking URL that can be shared directly with recipients.

bash
curl https://api.postx.ai/v1/shipping/tracking/AB12-XY34

Response

json
{
  "trackingUrl": "https://tracking.kosmo.delivery/tracking/KSM-ABC123"
}
โ„น๏ธIf no tracking URL is available yet (driver not yet dispatched), trackingUrl will be null. This is the documented, expected case.
โš ๏ธWhat an unknown or invalid reference returns, and rate limiting for this public endpoint, are not yet documented. Treat both as unconfirmed until POSTX publishes them โ€” see .

Capacity

GET
/capacity

Check if delivery capacity is available for a given date and item type.

Query parameters

ParamTypeDescription
daterequiredISO 8601Delivery date to check. E.g. "2026-09-02".
typerequiredenum"pallets" or "parcels".
bash
curl "https://api.postx.ai/v1/shipping/capacity?date=2026-09-02&type=pallets" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

json
{
  "data": [
    { "slot": "AM", "available": 12, "total": 20 },
    { "slot": "PM", "available": 3,  "total": 20 }
  ]
}
โš ๏ธCapacity is reported at AM/PM granularity only. Timed delivery windows (0800_0900, 0900_1000, 1000_1100, CUSTOM_ETA) are not capacity-checked before booking.

Service Types

Service types control the collection and delivery time windows. All values below are next-day. Same-day service types do not exist yet โ€” see .

Collection service types

PALLET_NEXT_DAY_COLLECTION_STANDARD_ETAStandard pallet collection ETA.
PARCEL_NEXT_DAY_COLLECTION_STANDARD_ETAStandard parcel collection ETA.

Delivery service types

PALLET_NEXT_DAY_DELIVERY_STANDARD_ETAStandard pallet delivery.
PALLET_NEXT_DAY_DELIVERY_AMPallet delivery in the AM window.
PALLET_NEXT_DAY_DELIVERY_PMPallet delivery in the PM window.
PALLET_NEXT_DAY_DELIVERY_0800_0900Pallet delivery between 08:00โ€“09:00.
PALLET_NEXT_DAY_DELIVERY_0900_1000Pallet delivery between 09:00โ€“10:00.
PALLET_NEXT_DAY_DELIVERY_1000_1100Pallet delivery between 10:00โ€“11:00.
PALLET_NEXT_DAY_DELIVERY_CUSTOM_ETACustom delivery ETA (pallet).
PARCEL_NEXT_DAY_DELIVERY_STANDARD_ETAStandard parcel delivery.
PARCEL_NEXT_DAY_DELIVERY_AMParcel delivery in the AM window.
PARCEL_NEXT_DAY_DELIVERY_PMParcel delivery in the PM window.

Products & Pallets

The product field on each shipment specifies the type of item being transported. Weight brackets for parcels are automatically resolved server-side. Next-day products only โ€” same-day products do not exist yet, see .

ProductCategoryNotes
PALLET_NEXT_DAY_NATIONALPalletNational next-day pallet delivery.
PALLET_NEXT_DAY_LOCALPalletLocal next-day pallet delivery.
PALLET_NEXT_DAY_OVERSIZEPalletOversize pallet (non-standard dimensions).
PALLET_NEXT_DAY_RAIL_BUNDLEPalletRail bundle pallet.
PARCEL_NEXT_DAY_NATIONALParcelNational next-day parcel. Weight bracket resolved automatically.
PARCEL_NEXT_DAY_LOCALParcelLocal next-day parcel. Weight bracket resolved automatically.

Pricing

Price is determined by the rate card and the service type. The rate card sets which service types are available to your account; the service type sets the price. See the full explanation, field breakdown and worked example in .

๐Ÿ’ท

Amounts are pence, GBP, net of VAT

Every price field on this API โ€” product, overweight surcharge, and both service legs โ€” is an integer number of pence, exclusive of VAT.

๐Ÿ”€

POSTX-rated and external prices can mix

One consignment can contain some lines rated from your POSTX rate card and some lines carrying your own external price for comparison โ€” the two are not mutually exclusive.

โœ…

A POSTX-rated price is corrected on mismatch

A price sent as a POSTX rate is checked against your account rate card and corrected if it does not match. An external comparison price is accepted as given and never corrected.


Business Rules

The API enforces the following rules on every consignment:

โžก๏ธ

Collection before delivery

collectionDateTime must be strictly before deliveryDateTime.

๐Ÿ“ฆ

At least one shipment required

Every consignment must include at least one shipment in the shipments array.

๐Ÿ—“๏ธ

Booking days and cut-off times are per account

Permitted booking days, cut-off times, and the cancellation window are set per account at contract, not globally. There are no fixed weekday or noon cut-off rules that apply to every account โ€” check your contract, or once available, GET /rate-cards (see Additional functionality).


Errors and recovery

All errors follow a consistent JSON structure:

json
{
  "statusCode": 400,
  "message": "collectionDateTime must not be in the past.",
  "error": "Bad Request"
}
โ„น๏ธmessage is currently free text โ€” there is no stable, machine-readable error code yet (planned, see ). Do not string-match on the exact sentence beyond what is published below.
HTTP CodeMeaningCommon Causes
400Bad Request
  • collectionDateTime must not be in the past.
  • deliveryDateTime must be after collectionDateTime.
  • shipments must contain at least 1 element.
  • No capacity available for the requested date and product.
  • A booking-day or cut-off violation, worded against your account's configured values โ€” the exact message is not yet published for every rule.
401UnauthorizedMissing or expired JWT token. Re-authenticate to get a new token.
409ConflictConsignment already routed to a driver, or already cancelled.
500Server ErrorUnexpected error. Retry with exponential backoff โ€” note there is currently no idempotency key, so a retried create can double-book. See .

POSTX platform

This document covers the Shipping API only. Booking through the API is one way in โ€” your team can also use the separate POSTX operations platform for day-to-day work on shipments already created, including shipment history, label printing, delivery progress, managing shipments, billing information and support.


Additional functionality

This is functionality the POSTX Shipping API will have. Each item below is tagged with its current availability so you can plan your integration around it without building against something before it ships.

GET /consignments/:reference

Not yet available

Look up a consignment by its reference to get current status, cancellation charge flag, priced breakdown and its label โ€” for state reconciliation, billing verification and label recovery.

POST /rate

Not yet available

Price a job before you book it. Submit the same payload as create without commitment and get back the priced breakdown, so you can quote your own end customer accurately.

Signed webhooks

Not yet available

Collected, in transit, delivered, failed and cancelled events pushed to your system as they happen, as an alternative to polling the tracking URL.

Label reprint, plus ZPL output

Not yet available

Recover and reprint a shipping label after the original create response, and receive it as ZPL as well as PDF.

GET /consignments (list)

Not yet available

List and filter your consignments with pagination, instead of tracking every reference yourself.

Self-serve sandbox

Not yet available

Get test credentials and start integrating immediately, without a commercial conversation first.

GET /rate-cards

Not yet available

Read back your account's rate card directly โ€” the service types it covers, the products it prices, cut-off times, permitted booking days and cancellation terms.

POSTX Developer Documentation ยท v1 ยท dev@postx.ai

ยฉ 2026 POSTX. All rights reserved.