Getting Data Out
The Trackberry API
Read your shipments, tracking, free time, alerts and documents from your own scripts and systems, with a token you create in settings.
41 min readPublished
Goal
Read your organization’s shipment data from a script, a spreadsheet tool, a BI dashboard or your own system, without exporting files by hand.
The API is read-only. It returns what you can already see in Trackberry, as JSON, for one organization at a time. Creating or changing shipments still happens by email, upload or in the app.
For AI agents and code generators
The whole API is described in one OpenAPI 3.1 file that needs no token:
https://trackberry.com/api/v1/openapi.json.
Give that URL to your coding agent, or load it into a code generator or an API
client such as Postman or Insomnia, and it has every endpoint, parameter, enum
value and field, each with a plain-language description of what it means for
the business (for example how effective_eta, eta, original_eta and
predicted_eta differ). It always describes the latest API version.
A few facts worth knowing before generating code:
- Every field is always present. A field with no value is
null, never missing, so declare nullable types instead of optional ones. - Ignore fields and enum values you don’t recognize. New ones are added without a new version.
- Lists of shipments, alerts and checks are paged with
limitandstarting_after; the other lists are not paged. - The file is also linked from llms.txt, for agents that start there.
The rest of this page is the same contract written for people.
Create a token
- Go to Settings → API tokens (
/your-slug/settings/api). - Click New token, give it a name that says where it will live (“Power BI refresh”, “ERP sync”) and pick when it expires.
- Copy the token. It is shown once. Trackberry only keeps a fingerprint of it, so nobody, including our team, can show it to you again. If you lose it, revoke it and create a new one.
A token belongs to you and to one organization. It can read everything you can read in that organization and nothing else. Any member can create tokens for themselves; admins and owners can see and revoke every token in the organization.
A token stops working when:
- it expires (30 days, 90 days, 1 year, or never, chosen when you create it),
- someone revokes it in settings,
- you leave the organization or are removed from it.
Tokens start with tb_ followed by 40 letters and digits. If you run a secret
scanner, this pattern finds them: \btb_[A-Za-z0-9]{40}\b. Treat a token like a
password: keep it in your secret store, never in a spreadsheet cell or a
public repository.
Make a request
The base URL is https://trackberry.com/api/v1. Send the token in the
Authorization header:
curl https://trackberry.com/api/v1/organization \
-H "Authorization: Bearer tb_your_token"
{
"object": "organization",
"id": "org_42",
"name": "Fresh Imports Ltd",
"slug": "fresh-imports",
"api_version": "2026-10-01",
"token": { "id": "tok_7", "name": "ERP sync", "scopes": ["read"], "expires_at": "2027-09-29T10:00:00Z", "user_email": "you@freshimports.com" }
}
There is no organization slug in the URLs: the token already says which organization you are reading.
Versions
The API is versioned, so an integration you write today keeps working as the API grows.
- Each version is named after the day it was released, such as
2026-10-01. - Your organization is pinned to the latest version the first time it calls
the API without a
Trackberry-Versionheader. Every later response uses that shape until an admin moves the organization forward from Settings → API tokens. - To try a newer version before switching, send it with a single request:
Trackberry-Version: 2026-10-01. That does not change the pin. - Successful responses include a
Trackberry-Versionheader with the version they were built for.
New fields, new endpoints and new values in a status list are added to every version, so your code should ignore fields it doesn’t recognize. Anything that removes, renames or changes the meaning of a field gets a new version, and the changelog explains what changed and how to adapt.
IDs, lists and formats
- IDs are strings with a prefix that names the kind of object:
shp_for shipments,ctr_containers,doc_documents,alr_alerts,chk_checks,pkl_packing lists,lbl_labels,org_organizations,tok_tokens,leg_route legs,evt_tracking events,eta_ETA revisions,plt_pallets andpln_packing lines. Treat them as opaque; pass them back exactly as you received them. An id with the wrong prefix, or from another organization, is a 404 when it is in the path. - Lists come back as
{ "object": "list", "data": [...], "has_more": true }, newest first. Ask for up to 100 items withlimit(default 25). To get the next page, pass theidof the last item you received asstarting_after, and stop whenhas_moreisfalse. Items that arrive while you page don’t cause gaps or repeats. - Times are UTC in ISO 8601 (
2026-09-29T14:03:00Z); calendar days are2026-09-29. Filters accept either. - Weights are kilograms (
net_weight_kg), temperatures are Celsius (temperature_celsius), and statuses are lowercase strings (in_transit). - Fields with no value are
null, never missing. Empty lists are[].
Endpoints
All endpoints are GET.
| Endpoint | Returns |
|---|---|
/organization |
Your organization, its pinned version, and the token you used |
/shipments |
Shipments, newest first, with filters (below) |
/shipments/{id} |
One shipment: status, ETA, route, carrier, tracking, containers, cargo totals, labels, check counts |
/shipments/{id}/timeline |
Route legs, tracking events and every ETA revision |
/shipments/{id}/free_time |
Demurrage and detention clocks for the shipment |
/shipments/{id}/documents |
Documents attached to the shipment |
/shipments/{id}/packing_lists |
Current packing lists with pallets, lines and totals |
/documents/{id} |
One document’s details |
/documents/{id}/data |
The fields Trackberry extracted from the document |
/free_time/at_risk |
Containers close to or past their free time, most urgent first |
/alerts |
Open monitoring alerts; shipment filters to one shipment |
/checks |
Failed and warning quality checks; status and shipment filter them |
Searching shipments
/shipments accepts these parameters, all optional:
| Parameter | Example | Meaning |
|---|---|---|
q |
MSCU1234567 |
Reference, B/L, AWB, container number or produce |
status |
in_transit,arrived |
One or more of draft, validated, in_transit, arrived, in_warehouse |
labels |
lbl_3,lbl_9 |
Shipments that carry all of these labels |
archived |
true |
false (default), true, or any |
created_after, created_before |
2026-09-01 |
When the shipment was created |
eta_after, eta_before |
2026-10-01T00:00:00Z |
Expected arrival |
limit, starting_after |
50, shp_812 |
Paging, as above |
curl "https://trackberry.com/api/v1/shipments?status=in_transit&eta_before=2026-10-07" \
-H "Authorization: Bearer tb_your_token"
Errors
Errors have one shape, whatever went wrong:
{ "error": { "type": "invalid_request_error", "code": "invalid_parameter", "message": "limit must be an integer between 1 and 100", "param": "limit" } }
| Status | code |
What to do |
|---|---|---|
| 400 | invalid_parameter |
Fix the parameter named in param |
| 400 | invalid_version |
Send a published version in Trackberry-Version, or none |
| 401 | missing_token |
Add the Authorization: Bearer header |
| 401 | invalid_token |
The token is wrong, expired, revoked, or you left the organization. Create a new one |
| 403 | insufficient_scope |
The token can’t use this endpoint |
| 404 | resource_missing |
No such object in this organization, or no such endpoint |
| 429 | rate_limited |
Slow down; wait the number of seconds in Retry-After |
Limits
Each token can make 600 requests every 5 minutes, which is plenty for a sync
that runs every few minutes. Requests from one IP address are capped at 1,200
every 5 minutes across all tokens, and requests with no token at all (including
a fetch of openapi.json) are capped at 30 every 5 minutes per IP address.
When you hit a limit you get a 429 with a Retry-After header.
Endpoint reference
Every request takes the optional Trackberry-Version header described under Versions. Every response body below shows all of its fields: a field with no value is null, never missing. Times are UTC. Successful responses carry a Trackberry-Version header, and a 404 or 400 caused by a parameter does too. Errors have the shape described under Errors.
Get the organization and token behind the request
GET /organization (operation get_organization)
Use this first to check that a token works and to learn which organization it reads, which API version that organization is pinned to, and when the token expires. Read-only and cheap.
No parameters.
Example response, 200:
{
"object": "organization",
"id": "org_42",
"name": "Fresh Imports Ltd",
"slug": "fresh-imports",
"api_version": "2026-10-01",
"token": {
"id": "tok_7",
"name": "ERP sync",
"scopes": [
"read"
],
"expires_at": "2027-09-29T10:00:00Z",
"user_email": "you@freshimports.com"
}
}
Errors: 400, 401, 429.
List and search shipments
GET /shipments (operation list_shipments)
Use this to find shipments, to sync the whole book, or to answer questions like “what is arriving next week” (eta_after and eta_before) or “which shipments are in transit” (status). Newest first, keyset paged. Shipments still waiting for approval are never listed. Archived shipments are left out unless archived says otherwise. Each item is the full shipment object, the same as get_shipment. All parameters are optional and combine with AND.
| Parameter | In | Type | Description |
|---|---|---|---|
q |
query | string | Free-text search. Case-insensitive, partial matches on the shipment reference, the ERP reference, the transport reference (bill of lading or air waybill number), the consignor and consignee names (also tolerant of small spelling differences), container numbers, and produce names (common aliases are understood). Spaces and dashes are ignored when matching transport references and container numbers, so MSCU 123456-7 finds MSCU1234567. An empty value means no search. Example: MSCU1234567. |
status |
query | comma-separated list | Only shipments in one of these statuses. One comma-separated value. Repeating the parameter is not supported (only the last occurrence is used) and status[]= is a 400. The status error exists on shipments but cannot be filtered on. Omit to get every status. One of draft, validated, in_transit, arrived, in_warehouse. Example: in_transit,arrived. |
labels |
query | comma-separated list | Only shipments that carry all of these labels (AND, not OR). One comma-separated value of label ids (lbl_ prefix), as found in labels[].id on shipments. A malformed id is a 400. Example: lbl_3,lbl_9. |
archived |
query | string | Whether to include archived shipments. false (the default) lists only active ones, true only archived ones, any both. One of false, true, any. Default false. Example: any. |
created_after |
query | date-time or date string | Only shipments created at or after this moment (inclusive). ISO 8601 date-time, or a bare date meaning midnight UTC at the start of that day. Example: 2026-09-01. |
created_before |
query | date-time or date string | Only shipments created at or before this moment (inclusive). ISO 8601 date-time, or a bare date, which means midnight UTC at the start of that day: created_before=2026-09-30 excludes everything created after 00:00 UTC on 30 September. To include a whole day, pass the following day or a full date-time. Example: 2026-09-30T23:59:59Z. |
eta_after |
query | date-time or date string | Only shipments whose effective_eta is at or after this moment (inclusive). Shipments with no ETA at all never match once either eta_after or eta_before is given. ISO 8601 date-time or bare date (midnight UTC). Example: 2026-10-01T00:00:00Z. |
eta_before |
query | date-time or date string | Only shipments whose effective_eta is at or before this moment (inclusive). Same rules as eta_after, including the midnight rule for a bare date. Example: 2026-10-07. |
limit |
query | integer | Maximum number of items in the page, 1 to 100. Decimal digits only; anything else (0, 101, 1e1, 0x10, a negative number) is a 400. Default 25. Example: 50. |
starting_after |
query | string | Cursor for the next page: the id of the last shipment of the previous page. Must start with shp_; anything else is a 400. Example: shp_812. |
Example response, 200:
{
"object": "list",
"has_more": true,
"data": [
{
"object": "shipment",
"id": "shp_812",
"reference": "SHIP-20260915-K7QX",
"erp_reference": "PO-88231",
"transport_reference": "MEDURU156671",
"transport_reference_type": "bill_of_lading",
"transport_type": "ocean",
"cargo_type": "reefer",
"temperature_celsius": 2.0,
"status": "in_transit",
"archived": false,
"archived_at": null,
"validated_at": "2026-09-16T08:30:00Z",
"approved_at": "2026-09-15T12:05:00Z",
"origin": {
"location": "Callao",
"country": "Peru",
"timezone": "-05:00"
},
"destination": {
"location": "Rotterdam",
"country": "Netherlands",
"timezone": "+02:00"
},
"etd": "2026-09-10T18:00:00Z",
"eta": "2026-10-05T06:00:00Z",
"effective_eta": "2026-10-05T06:00:00Z",
"original_eta": "2026-10-02T06:00:00Z",
"predicted_eta": null,
"carrier": {
"name": "MSC",
"scac": "MSCU"
},
"tracking": {
"state": "available",
"status": "in_transit",
"unavailable_reason": null,
"halted_reason": null,
"last_tracked_at": "2026-09-29T09:41:00Z",
"carrier_updated_at": "2026-09-29T06:12:00Z"
},
"parties": {
"consignor": "Agro Andes SAC",
"consignee": "Fresh Imports Ltd",
"notify_party": null
},
"produce": [
"Grapes"
],
"organic": false,
"cargo": {
"pallets": 20,
"boxes": 2400,
"net_weight_kg": 9600.0,
"gross_weight_kg": 10320.0
},
"containers": [
{
"object": "container",
"id": "ctr_1301",
"number": "MSCU1234567",
"seal_number": "ES123456",
"vessel": "MSC AURORA",
"voyage": "2609W",
"port_of_loading": "Callao",
"port_of_discharge": "Rotterdam",
"etd": "2026-09-10T18:00:00Z",
"eta": "2026-10-05T06:00:00Z",
"cargo_type": "reefer",
"temperature_celsius": 2.0
}
],
"labels": [
{
"object": "label",
"id": "lbl_3",
"name": "Priority",
"color": "red",
"color_hex": "#ef4444"
}
],
"checks": {
"total": 6,
"passed": 4,
"failed": 1,
"warnings": 1,
"skipped": 0,
"pending": 0
},
"notes": null,
"created_at": "2026-09-15T12:00:00Z",
"updated_at": "2026-09-29T09:41:00Z"
}
]
}
Errors: 400, 401, 429.
Get one shipment
GET /shipments/{id} (operation get_shipment)
Use this when you already have a shipment id and want its current state: status, ETAs, route, carrier, tracking health, parties, produce, cargo totals, containers, labels and check counts. Archived shipments are still found. For tracking events and ETA history use get_shipment_timeline; for demurrage and detention use get_shipment_free_time.
| Parameter | In | Type | Description |
|---|---|---|---|
id |
path | string, required | The shipment id (shp_ prefix). An id from another organization, or with another prefix, is a 404. Example: shp_812. |
Example response, 200:
{
"object": "shipment",
"id": "shp_812",
"reference": "SHIP-20260915-K7QX",
"erp_reference": "PO-88231",
"transport_reference": "MEDURU156671",
"transport_reference_type": "bill_of_lading",
"transport_type": "ocean",
"cargo_type": "reefer",
"temperature_celsius": 2.0,
"status": "in_transit",
"archived": false,
"archived_at": null,
"validated_at": "2026-09-16T08:30:00Z",
"approved_at": "2026-09-15T12:05:00Z",
"origin": {
"location": "Callao",
"country": "Peru",
"timezone": "-05:00"
},
"destination": {
"location": "Rotterdam",
"country": "Netherlands",
"timezone": "+02:00"
},
"etd": "2026-09-10T18:00:00Z",
"eta": "2026-10-05T06:00:00Z",
"effective_eta": "2026-10-05T06:00:00Z",
"original_eta": "2026-10-02T06:00:00Z",
"predicted_eta": null,
"carrier": {
"name": "MSC",
"scac": "MSCU"
},
"tracking": {
"state": "available",
"status": "in_transit",
"unavailable_reason": null,
"halted_reason": null,
"last_tracked_at": "2026-09-29T09:41:00Z",
"carrier_updated_at": "2026-09-29T06:12:00Z"
},
"parties": {
"consignor": "Agro Andes SAC",
"consignee": "Fresh Imports Ltd",
"notify_party": null
},
"produce": [
"Grapes"
],
"organic": false,
"cargo": {
"pallets": 20,
"boxes": 2400,
"net_weight_kg": 9600.0,
"gross_weight_kg": 10320.0
},
"containers": [
{
"object": "container",
"id": "ctr_1301",
"number": "MSCU1234567",
"seal_number": "ES123456",
"vessel": "MSC AURORA",
"voyage": "2609W",
"port_of_loading": "Callao",
"port_of_discharge": "Rotterdam",
"etd": "2026-09-10T18:00:00Z",
"eta": "2026-10-05T06:00:00Z",
"cargo_type": "reefer",
"temperature_celsius": 2.0
}
],
"labels": [
{
"object": "label",
"id": "lbl_3",
"name": "Priority",
"color": "red",
"color_hex": "#ef4444"
}
],
"checks": {
"total": 6,
"passed": 4,
"failed": 1,
"warnings": 1,
"skipped": 0,
"pending": 0
},
"notes": null,
"created_at": "2026-09-15T12:00:00Z",
"updated_at": "2026-09-29T09:41:00Z"
}
Errors: 400, 401, 404, 429.
Get the route, tracking events and ETA revisions of a shipment
GET /shipments/{shipment_id}/timeline (operation get_shipment_timeline)
Use this to answer “where is it and what happened” and “how has the ETA moved”. Returns the route legs in order, every tracking event (both events that happened and estimated ones, oldest first) and every recorded revision of the estimated arrival, oldest first. Not paged.
| Parameter | In | Type | Description |
|---|---|---|---|
shipment_id |
path | string, required | The shipment id (shp_ prefix). An id from another organization, or with another prefix, is a 404. Example: shp_812. |
Example response, 200:
{
"object": "timeline",
"shipment_id": "shp_812",
"legs": [
{
"object": "shipment_leg",
"id": "leg_5501",
"position": 0,
"transport_type": "ocean",
"carrier": "MSC",
"transport_reference": "MEDURU156671",
"origin": {
"location": "Callao",
"country": "Peru",
"timezone": "-05:00"
},
"destination": {
"location": "Rotterdam",
"country": "Netherlands",
"timezone": "+02:00"
},
"etd": "2026-09-10T18:00:00Z",
"eta": "2026-10-05T06:00:00Z"
}
],
"events": [
{
"object": "tracking_event",
"id": "evt_90211",
"milestone": "loaded",
"actual": true,
"occurred_at": "2026-09-10T14:20:00Z",
"occurred_at_local": "2026-09-10T09:20:00-05:00",
"container_number": "MSCU1234567",
"leg_index": 1,
"location": {
"name": "Callao",
"code": "PECLL",
"country_code": "PE"
},
"vessel": {
"name": "MSC AURORA",
"imo": "9876543",
"voyage": "2609W"
},
"flight_number": null,
"position": {
"latitude": -12.05,
"longitude": -77.15
}
},
{
"object": "tracking_event",
"id": "evt_90233",
"milestone": "arrived",
"actual": false,
"occurred_at": "2026-10-05T06:00:00Z",
"occurred_at_local": "2026-10-05T08:00:00+02:00",
"container_number": "MSCU1234567",
"leg_index": 1,
"location": {
"name": "Rotterdam",
"code": "NLRTM",
"country_code": "NL"
},
"vessel": {
"name": "MSC AURORA",
"imo": "9876543",
"voyage": "2609W"
},
"flight_number": null,
"position": {
"latitude": null,
"longitude": null
}
}
],
"eta_revisions": [
{
"object": "eta_revision",
"id": "eta_4401",
"observed_at": "2026-09-11T05:00:00Z",
"previous_eta": null,
"new_eta": "2026-10-02T06:00:00Z",
"slip_seconds": null,
"first_estimate": true,
"backfilled": false
},
{
"object": "eta_revision",
"id": "eta_4470",
"observed_at": "2026-09-25T05:00:00Z",
"previous_eta": "2026-10-02T06:00:00Z",
"new_eta": "2026-10-05T06:00:00Z",
"slip_seconds": 259200.0,
"first_estimate": false,
"backfilled": false
}
]
}
Errors: 400, 401, 404, 429.
Get the demurrage and detention clocks of a shipment
GET /shipments/{shipment_id}/free_time (operation get_shipment_free_time)
Use this to answer “how many free days are left on this shipment” or “what will demurrage cost us”. Returns one demurrage clock and one detention clock per container, plus the clock that matters most right now (active_clock). Clocks only exist for ocean shipments, for each container that has loading, discharge, gate-out or empty-return events, and stay not_started until the container is discharged; for any other shipment the clock lists are empty and active_clock is null. Free days come from the shipment itself, the latest arrival notice, or the organization’s carrier terms, in that order (see free_days_source).
| Parameter | In | Type | Description |
|---|---|---|---|
shipment_id |
path | string, required | The shipment id (shp_ prefix). An id from another organization, or with another prefix, is a 404. Example: shp_812. |
Example response, 200:
{
"object": "free_time_summary",
"shipment_id": "shp_790",
"shipment_reference": "SHIP-20260901-B2MD",
"transport_reference": "MAEU123456789",
"at_risk": true,
"terms_unknown": false,
"demurrage": [
{
"object": "free_time_clock",
"kind": "demurrage",
"container_number": "TGHU7654321",
"state": "running",
"free_days": 5,
"free_days_source": "carrier",
"free_days_basis": "calendar",
"started_on": "2026-09-25",
"ended_on": null,
"last_free_day": "2026-09-29",
"days_left": 1,
"elapsed_days": null,
"used_days": null,
"overdue_days": null,
"carrier": "Maersk"
}
],
"detention": [
{
"object": "free_time_clock",
"kind": "detention",
"container_number": "TGHU7654321",
"state": "not_started",
"free_days": 10,
"free_days_source": "carrier",
"free_days_basis": "calendar",
"started_on": null,
"ended_on": null,
"last_free_day": null,
"days_left": null,
"elapsed_days": null,
"used_days": null,
"overdue_days": null,
"carrier": "Maersk"
}
],
"active_clock": {
"object": "free_time_clock",
"kind": "demurrage",
"container_number": "TGHU7654321",
"state": "running",
"free_days": 5,
"free_days_source": "carrier",
"free_days_basis": "calendar",
"started_on": "2026-09-25",
"ended_on": null,
"last_free_day": "2026-09-29",
"days_left": 1,
"elapsed_days": null,
"used_days": null,
"overdue_days": null,
"carrier": "Maersk"
}
}
Errors: 400, 401, 404, 429.
List the documents of a shipment
GET /shipments/{shipment_id}/documents (operation list_shipment_documents)
Use this to see which paperwork Trackberry holds for a shipment (bill of lading, packing list, invoice, certificates) and whether each was read successfully. Only current documents are listed: replaced versions, reference-only attachments and internal page-split records are left out. Oldest first, not paged. The API describes documents but does not serve the files.
| Parameter | In | Type | Description |
|---|---|---|---|
shipment_id |
path | string, required | The shipment id (shp_ prefix). An id from another organization, or with another prefix, is a 404. Example: shp_812. |
Example response, 200:
{
"object": "list",
"has_more": false,
"data": [
{
"object": "document",
"id": "doc_301",
"shipment_id": "shp_812",
"type": "packing_list",
"filename": "PL_MEDURU156671.xlsx",
"content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"byte_size": 48211,
"source": "email_upload",
"parse_status": "parsed",
"downloadable": true,
"page_range": null,
"data_available": true,
"created_at": "2026-09-15T12:01:00Z",
"updated_at": "2026-09-15T12:03:00Z"
}
]
}
Errors: 400, 401, 404, 429.
List the packing lists of a shipment with pallets and lines
GET /shipments/{shipment_id}/packing_lists (operation list_shipment_packing_lists)
Use this to read what is physically in the shipment: for each current packing list, its declared totals, its pallets, and each pallet’s produce lines (produce, variety, calibre, box counts and weights). Only current packing lists (not replaced by a newer document) are listed, oldest first, not paged. Pallets that belong to no packing list are not reachable here (they still count in cargo.pallets of the shipment).
| Parameter | In | Type | Description |
|---|---|---|---|
shipment_id |
path | string, required | The shipment id (shp_ prefix). An id from another organization, or with another prefix, is a 404. Example: shp_812. |
Example response, 200:
{
"object": "list",
"has_more": false,
"data": [
{
"object": "packing_list",
"id": "pkl_55",
"shipment_id": "shp_812",
"document_id": "doc_301",
"container_id": "ctr_1301",
"reference": "PL-2026-0915",
"declared_box_count": 240,
"declared_net_weight_kg": 960.0,
"totals": {
"pallets": 2,
"boxes": 240,
"net_weight_kg": 960.0
},
"pallets": [
{
"object": "pallet",
"id": "plt_9001",
"pallet_number": "PAL0001",
"container_id": "ctr_1301",
"lines": [
{
"object": "packing_line",
"id": "pln_70001",
"line_index": 1,
"produce_name": "Grapes",
"produce_type": "Organic",
"variety": "Sweet Globe",
"calibre": "L",
"quality_category": "Class I",
"pack_format": "4.0 kg carton",
"label": "Andes Gold",
"ggn": "4049929123456",
"box_count": 120,
"box_weight_kg": 4.0,
"net_weight_kg": 480.0,
"gross_weight_kg": 522.0
}
]
},
{
"object": "pallet",
"id": "plt_9002",
"pallet_number": "PAL0002",
"container_id": "ctr_1301",
"lines": [
{
"object": "packing_line",
"id": "pln_70002",
"line_index": 1,
"produce_name": "Grapes",
"produce_type": "Organic",
"variety": "Sweet Globe",
"calibre": "L",
"quality_category": "Class I",
"pack_format": "4.0 kg carton",
"label": "Andes Gold",
"ggn": "4049929123456",
"box_count": 120,
"box_weight_kg": 4.0,
"net_weight_kg": 480.0,
"gross_weight_kg": 522.0
}
]
}
]
}
]
}
Errors: 400, 401, 404, 429.
List shipments whose demurrage free time is nearly or already used up
GET /free_time/at_risk (operation list_free_time_at_risk)
Use this for a daily “what do I need to collect today” view. Returns one free-time summary per shipment that has a demurrage clock running with 2 days or fewer left (or already overdue), most urgent first. Only ocean shipments that are not archived, not yet received into the warehouse, and were discharged in the last 45 days are considered. Not paged. Shipments with unknown free-time terms never appear here; terms_unknown on get_shipment_free_time says when terms are missing.
No parameters.
Example response, 200:
{
"object": "list",
"has_more": false,
"data": [
{
"object": "free_time_summary",
"shipment_id": "shp_790",
"shipment_reference": "SHIP-20260901-B2MD",
"transport_reference": "MAEU123456789",
"at_risk": true,
"terms_unknown": false,
"demurrage": [
{
"object": "free_time_clock",
"kind": "demurrage",
"container_number": "TGHU7654321",
"state": "running",
"free_days": 5,
"free_days_source": "carrier",
"free_days_basis": "calendar",
"started_on": "2026-09-25",
"ended_on": null,
"last_free_day": "2026-09-29",
"days_left": 1,
"elapsed_days": null,
"used_days": null,
"overdue_days": null,
"carrier": "Maersk"
}
],
"detention": [
{
"object": "free_time_clock",
"kind": "detention",
"container_number": "TGHU7654321",
"state": "not_started",
"free_days": 10,
"free_days_source": "carrier",
"free_days_basis": "calendar",
"started_on": null,
"ended_on": null,
"last_free_day": null,
"days_left": null,
"elapsed_days": null,
"used_days": null,
"overdue_days": null,
"carrier": "Maersk"
}
],
"active_clock": {
"object": "free_time_clock",
"kind": "demurrage",
"container_number": "TGHU7654321",
"state": "running",
"free_days": 5,
"free_days_source": "carrier",
"free_days_basis": "calendar",
"started_on": "2026-09-25",
"ended_on": null,
"last_free_day": "2026-09-29",
"days_left": 1,
"elapsed_days": null,
"used_days": null,
"overdue_days": null,
"carrier": "Maersk"
}
}
]
}
Errors: 400, 401, 429.
List open monitoring alerts
GET /alerts (operation list_alerts)
Use this to find shipments that Trackberry’s monitoring says have a problem right now: tracking gone quiet, ETA overdue or slipped, cargo sitting at the terminal, and similar. Only open alerts of the kinds customers can see are listed, across all shipments (archived ones included), newest first, keyset paged. Pass shipment to look at one shipment.
| Parameter | In | Type | Description |
|---|---|---|---|
shipment |
query | string | Only alerts of this shipment. Must start with shp_; anything else is a 400. A well-formed id that is not in this organization simply matches nothing. Example: shp_812. |
limit |
query | integer | Maximum number of items in the page, 1 to 100. Decimal digits only; anything else (0, 101, 1e1, 0x10, a negative number) is a 400. Default 25. Example: 50. |
starting_after |
query | string | Cursor for the next page: the id of the last alert of the previous page. Must start with alr_; anything else is a 400. Example: alr_2210. |
Example response, 200:
{
"object": "list",
"has_more": false,
"data": [
{
"object": "monitoring_alert",
"id": "alr_2210",
"shipment_id": "shp_812",
"shipment_reference": "SHIP-20260915-K7QX",
"key": "eta_drift",
"group": "schedule",
"severity": "warning",
"title": "ETA has slipped",
"summary": "ETA has moved 3 days later than first quoted (2026-10-02 → 2026-10-05).",
"since": "2026-10-02T06:00:00Z",
"first_detected_at": "2026-09-25T03:00:00Z",
"last_detected_at": "2026-09-29T03:00:00Z",
"resolved_at": null
}
]
}
Errors: 400, 401, 429.
List quality checks across shipments
GET /checks (operation list_checks)
Use this to find paperwork and data problems: missing documents, packing list totals that disagree with the declared ones, invalid container numbers, and similar. By default only checks that failed or warned are listed; pass status to see others. Across all shipments (archived ones included), newest first, keyset paged. Pass shipment to look at one shipment.
| Parameter | In | Type | Description |
|---|---|---|---|
status |
query | comma-separated list | Only checks in one of these statuses. One comma-separated value. Defaults to failed,warning when omitted or empty. An unknown status is a 400. One of pending, passed, failed, skipped, warning. Default failed,warning. Example: failed,warning. |
shipment |
query | string | Only checks of this shipment. Must start with shp_; anything else is a 400. A well-formed id that is not in this organization simply matches nothing. Example: shp_812. |
limit |
query | integer | Maximum number of items in the page, 1 to 100. Decimal digits only; anything else (0, 101, 1e1, 0x10, a negative number) is a 400. Default 25. Example: 50. |
starting_after |
query | string | Cursor for the next page: the id of the last check of the previous page. Must start with chk_; anything else is a 400. Example: chk_9001. |
Example response, 200:
{
"object": "list",
"has_more": false,
"data": [
{
"object": "shipment_check",
"id": "chk_9001",
"shipment_id": "shp_812",
"shipment_reference": "SHIP-20260915-K7QX",
"key": "has_commercial_invoice",
"category": "documents",
"status": "warning",
"title": "Commercial invoice",
"message": "No commercial invoice has been received for this shipment yet.",
"ran_at": "2026-09-29T03:00:00Z"
}
]
}
Errors: 400, 401, 429.
Get one document
GET /documents/{id} (operation get_document)
Use this to describe a document you found through list_shipment_documents: its type, file name, size, source, processing status, and whether extracted data is available. It does not return the file itself. Only current documents are found; a replaced or reference-only document is a 404.
| Parameter | In | Type | Description |
|---|---|---|---|
id |
path | string, required | The document id (doc_ prefix). An id from another organization, with another prefix, or of a document that is not current, is a 404. Example: doc_301. |
Example response, 200:
{
"object": "document",
"id": "doc_301",
"shipment_id": "shp_812",
"type": "packing_list",
"filename": "PL_MEDURU156671.xlsx",
"content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"byte_size": 48211,
"source": "email_upload",
"parse_status": "parsed",
"downloadable": true,
"page_range": null,
"data_available": true,
"created_at": "2026-09-15T12:01:00Z",
"updated_at": "2026-09-15T12:03:00Z"
}
Errors: 400, 401, 404, 429.
Get the data Trackberry extracted from a document
GET /documents/{id}/data (operation get_document_data)
Use this to read the structured content Trackberry parsed out of a document (a packing list’s lines, an invoice’s totals, a bill of lading’s parties and departure and arrival days, a certificate’s numbers). Check data_available on the document first, or accept an empty result: when nothing was extracted, or the document type has no structured schema, the response is still a 200 with schema null and fields an empty object.
| Parameter | In | Type | Description |
|---|---|---|---|
id |
path | string, required | The document id (doc_ prefix). An id from another organization, with another prefix, or of a document that is not current, is a 404. Example: doc_301. |
Example response, 200:
{
"object": "document_data",
"document_id": "doc_301",
"type": "packing_list",
"schema": "packing_list",
"fields": {
"packing_list_number": "PL-2026-0915",
"exporter_name": "Agro Andes SAC",
"exporter_port": "Callao",
"exporter_country": "Peru",
"importer_name": "Fresh Imports Ltd",
"importer_country": "Netherlands",
"total_net_weight": 960.0,
"total_boxes": 240,
"diagram_pallet_numbers": [],
"container_number": "MSCU1234567",
"line_items": [
{
"pallet_number": "PAL0001",
"produce_name": "Grapes",
"variety": "Sweet Globe",
"size_calibre": "L",
"quality_category": "Class I",
"format": "4.0 kg carton",
"label": "Andes Gold",
"produce_type": "Organic",
"ggn": "4049929123456",
"number_of_boxes": 120,
"net_weight_kg": 480.0,
"box_weight_kg": 4.0,
"gross_weight_kg": 522.0
}
]
}
}
Errors: 400, 401, 404, 429.
Get this OpenAPI description
GET /openapi.json (operation get_openapi_document)
Use this to load the machine-readable description of the API into an agent, a code generator or a documentation tool. Public: no token needed. It describes the latest API version and does not depend on the organization or on Trackberry-Version. It counts against the per-IP limit for requests without a token. Cacheable for an hour.
No parameters.
Returns 200 with an OpenAPI 3.1 document as JSON (it is the file this reference is built from).
Errors: 429.
Objects
Objects the API returns carry an object field naming their type, and most have an id. Nested objects are shown with dotted field names. The type column says or null where a field can be null. Place is a building block used inside other objects; List and Error are the envelopes for lists and errors.
Error object
The single error body used by every failure.
| Field | Type | Description |
|---|---|---|
error |
object | The details of what went wrong. |
error.type |
string | The broad class of the error. One of authentication_error, permission_error, not_found_error, invalid_request_error, rate_limit_error. |
error.code |
string | A stable machine-readable reason. Branch on this. One of missing_token, invalid_token, insufficient_scope, resource_missing, invalid_parameter, invalid_version, rate_limited. |
error.message |
string | An English sentence for people. Do not parse it. |
error.param |
string or null | The query parameter or header at fault, or null when the error is not about one. |
List object
The envelope every list endpoint returns.
| Field | Type | Description |
|---|---|---|
object |
string | Always list. |
data |
array of objects | The items of this page, in the order the endpoint documents. Each item is an object of the kind the endpoint returns. |
has_more |
boolean | True when more items exist after this page. Pass the last item’s id as starting_after to fetch them. Always false for unpaged lists. |
Organization object
The organization a token reads, with the token that made the request.
| Field | Type | Description |
|---|---|---|
object |
string | Always organization. |
id |
string | The organization id. |
name |
string | The organization’s display name. |
slug |
string | The organization’s URL slug in the Trackberry app. |
api_version |
string or null | The API version the organization is pinned to. Null only if the organization has not made a request without a Trackberry-Version header yet. |
token |
object | The API token that authenticated this request. |
token.id |
string | The token id (not the secret). |
token.name |
string | The name given to the token when it was created. |
token.scopes |
array of strings | What the token may do. Only read exists. One of read. |
token.expires_at |
date-time string or null | When the token stops working, or null if it never expires. |
token.user_email |
string | The email of the user the token belongs to. |
Shipment object
A consignment of goods: one bill of lading or air waybill, its containers, and everything Trackberry knows about where it is and what is in it.
| Field | Type | Description |
|---|---|---|
object |
string | Always shipment. |
id |
string | The shipment id. |
reference |
string | Trackberry’s reference for the shipment, unique within the organization. Generated (like SHIP-20260915-K7QX) unless a person set one. |
erp_reference |
string or null | The organization’s own reference for the shipment (for example a purchase order number), when one was recorded. |
transport_reference |
string or null | The number the cargo is tracked by, taken from the transport document. An ocean bill of lading number, an air waybill number or a container number. Ocean and road references are upper-cased with spaces and dashes removed; air waybills use the canonical 3-digit-prefix format. |
transport_reference_type |
string or null | What kind of number transport_reference is (a container number, an air waybill or a bill of lading), or null when it is blank or matches none of them. One of container, awb, bill_of_lading. |
transport_type |
string or null | How the cargo travels. Only ocean and air shipments are tracked with a carrier feed. Null when not yet known. One of ocean, air, road. |
cargo_type |
string or null | The temperature regime of the cargo. Null when not yet known. One of ambient, reefer, frozen. |
temperature_celsius |
number or null | The temperature set point in degrees Celsius for refrigerated cargo, when known. |
status |
string | Where the shipment is in its life. draft is data read from documents that nobody has confirmed; validated means a person or the automatic checks confirmed the key facts; in_transit means the cargo is moving; arrived means it reached the port or airport; in_warehouse means it was received at the warehouse; error means processing failed (rarely used). Shipments waiting for approval are not exposed. One of draft, validated, in_transit, arrived, error, in_warehouse. |
archived |
boolean | True when the shipment was archived. Archived shipments are hidden from list_shipments unless archived asks for them. |
archived_at |
date-time string or null | When the shipment was archived, or null when it is not archived. |
validated_at |
date-time string or null | When the key facts were first confirmed. Stays set after the status moves on to in_transit, arrived or in_warehouse. Null for a shipment never validated. |
approved_at |
date-time string or null | When the shipment was approved, either by a person or automatically because it arrived from a trusted sender. Null when no approval was recorded. |
origin |
Place object | An origin or a destination. |
destination |
Place object | An origin or a destination. |
etd |
date-time string or null | Estimated (later actual) time of departure, from the documents or the carrier. |
eta |
date-time string or null | The estimated time of arrival at the destination as last stated by the documents or the carrier. This is the carrier’s own figure and moves whenever the carrier changes it. Null when unknown. |
effective_eta |
date-time string or null | The arrival time to plan around. It is eta when set, otherwise the earliest eta among the shipment’s containers, otherwise null. The eta_after and eta_before filters of list_shipments compare against this. |
original_eta |
date-time string or null | The first arrival estimate Trackberry recorded for the documented destination. Later estimates do not overwrite it, so eta minus original_eta is the total slip. Null when no estimate was ever recorded. |
predicted_eta |
date-time string or null | A separate arrival prediction for the port of discharge from the tracking data source, built from vessel movements, port congestion and weather. Only some sources publish one, and only when the shipment is within about three days of arrival. It is independent of eta (the carrier’s figure) and never overwrites it. Null when there is none. |
carrier |
object | The shipping line or airline. |
carrier.name |
string or null | The carrier’s name in its canonical spelling, from tracking data. Null before tracking has identified one. |
carrier.scac |
string or null | The carrier’s SCAC code (Standard Carrier Alpha Code), when known. |
tracking |
object | Health of carrier tracking for this shipment. |
tracking.state |
string | What Trackberry knows about tracking. available means tracking data exists; unavailable means Trackberry asked and cannot get data (see unavailable_reason); pending means tracking was requested and nothing has come back yet; not_started means there is a reference but tracking has not been requested; awaiting_reference means it could be tracked once a bill of lading, container or air waybill number is known; none means tracking does not apply (for example road freight). One of available, unavailable, pending, not_started, awaiting_reference, none. |
tracking.status |
string or null | The carrier’s latest reported status in the tracking data source’s own words (for example in_transit, arrived, not_found). Not a closed list. Null when there is none. |
tracking.unavailable_reason |
string or null | Why tracking could not produce data, when it could not. unsupported_carrier means the carrier or reference type is not tracked; invalid_reference means the number is not usable; not_found means the carrier has no record of it yet; provider_error means the lookup returned nothing usable; past_voyage means the voyage ended long before the documents arrived so tracking was not started. Null otherwise. One of unsupported_carrier, invalid_reference, not_found, provider_error, past_voyage. |
tracking.halted_reason |
string or null | Set when the tracking source reported that it stopped producing data. errored means its carrier feed failed on this reference; dropped means it removed the shipment from tracking. Cleared automatically when data flows again. Null otherwise. One of errored, dropped. |
tracking.last_tracked_at |
date-time string or null | When Trackberry last refreshed tracking data for this shipment. Null if never. |
tracking.carrier_updated_at |
date-time string or null | When the carrier last published new data for this shipment, as opposed to when Trackberry last asked. Null when the source does not say. |
parties |
object | The companies named on the transport document. |
parties.consignor |
string or null | The sender of the goods (shipper or supplier). |
parties.consignee |
string or null | The receiver of the goods named on the transport document. |
parties.notify_party |
string or null | The party the carrier notifies on arrival, when different from the consignee. |
produce |
array of strings | The distinct produce names in the shipment, from its packing lines, or from the draft entry when no packing list has been read yet. |
organic |
boolean | True when at least one visible packing line is marked organic. |
cargo |
object | Totals over all pallets of the shipment. Zero when no packing list has been read. |
cargo.pallets |
integer | Number of pallets recorded for the shipment. |
cargo.boxes |
integer | Total number of boxes over the visible packing lines. |
cargo.net_weight_kg |
number | Total net weight of the produce in kilograms. |
cargo.gross_weight_kg |
number | Total gross weight, produce plus packaging, in kilograms. |
containers |
array of Container objects | The containers of the shipment, oldest first. |
labels |
array of Label objects | The labels the organization attached to the shipment, sorted by name. |
checks |
object | How many quality checks the shipment has in each state. Use list_checks for the checks themselves. |
checks.total |
integer | All checks of the shipment. |
checks.passed |
integer | Checks that passed. |
checks.failed |
integer | Checks that failed, meaning something is wrong. |
checks.warnings |
integer | Checks that passed with a warning. |
checks.skipped |
integer | Checks skipped because their preconditions were not met. |
checks.pending |
integer | Checks that have not run yet. |
notes |
string or null | Free-text notes on the shipment. |
created_at |
date-time string | When the shipment was created in Trackberry. |
updated_at |
date-time string | When the shipment record last changed. |
Place object
An origin or a destination.
| Field | Type | Description |
|---|---|---|
location |
string or null | The city or port, normalized (for example Rotterdam), without the country. |
country |
string or null | The country’s English name (for example Netherlands). |
timezone |
string or null | The UTC offset of the place as +HH:MM or -HH:MM (for example +02:00), learned from carrier data. Not an IANA time zone name. |
Container object
One container of a shipment.
| Field | Type | Description |
|---|---|---|
object |
string | Always container. |
id |
string | The container id. |
number |
string or null | The ISO 6346 container number (4 letters and 7 digits, like MSCU1234567). |
seal_number |
string or null | The seal number on the container door. |
vessel |
string or null | The vessel name the documents give for this container. |
voyage |
string or null | The voyage number the documents give for this container. |
port_of_loading |
string or null | Where the container is loaded, as written in the documents. |
port_of_discharge |
string or null | Where the container is discharged, as written in the documents. |
etd |
date-time string or null | Estimated time of departure of this container. |
eta |
date-time string or null | Estimated time of arrival of this container. When the shipment has no eta of its own, the earliest container eta becomes its effective_eta. |
cargo_type |
string or null | The temperature regime of this container. One of ambient, reefer, frozen. |
temperature_celsius |
number or null | The container’s temperature set point in degrees Celsius. |
Label object
A colored tag the organization uses to group shipments.
| Field | Type | Description |
|---|---|---|
object |
string | Always label. |
id |
string | The label id. Use it in the labels filter of list_shipments. |
name |
string | The label’s name, unique within the organization. |
color |
string or null | The name of the palette color. One of gray, red, orange, amber, green, teal, blue, indigo, purple, pink. |
color_hex |
string | The color as a hex code such as #ef4444. |
Timeline object
The route, tracking events and ETA history of one shipment.
| Field | Type | Description |
|---|---|---|
object |
string | Always timeline. |
shipment_id |
string | The shipment this timeline belongs to. |
legs |
array of ShipmentLeg objects | The legs of the route in travel order. |
events |
array of TrackingEvent objects | Tracking events, oldest first. Events without a time are placed by the usual order of milestones. |
eta_revisions |
array of EtaRevision objects | Every recorded change of the estimated arrival, oldest first. |
ShipmentLeg object
One leg of a shipment’s planned route, for example a sea leg followed by a road leg.
| Field | Type | Description |
|---|---|---|
object |
string | Always shipment_leg. |
id |
string | The leg id. |
position |
integer | The zero-based order of the leg in the route. Not the same as leg_index on tracking events. |
transport_type |
string or null | How the cargo travels on this leg. One of ocean, air, road. |
carrier |
string or null | The carrier of this leg, as written in the transport document. |
transport_reference |
string or null | The bill of lading, air waybill or consignment number of this leg. |
origin |
Place object | An origin or a destination. |
destination |
Place object | An origin or a destination. |
etd |
date-time string or null | Departure time of this leg, from the transport document. |
eta |
date-time string or null | Arrival time of this leg, from the transport document. |
TrackingEvent object
One milestone of the cargo’s journey, actual or estimated.
| Field | Type | Description |
|---|---|---|
object |
string | Always tracking_event. |
id |
string | The event id. |
milestone |
string | What happened, from Trackberry’s own milestone vocabulary (never a carrier’s raw code). Cargo milestones in usual order: booked, received_from_shipper (air), empty_pickup, stuffed, gate_in, manifested (air), loaded, departed, transshipment_arrival, transshipment_discharge, transferred (air), transshipment_load, transshipment_departure, arrived, discharged, customs_cleared, notified (air), available_for_pickup, gate_out, delivered, stripped, empty_return. Lifecycle milestones: eta_revised, exception, untracked. discharged (off the vessel) and gate_out (left the terminal) start and stop the demurrage clock. One of booked, received_from_shipper, empty_pickup, stuffed, gate_in, manifested, loaded, departed, transshipment_arrival, transshipment_discharge, transferred, transshipment_load, transshipment_departure, arrived, discharged, customs_cleared, notified, available_for_pickup, gate_out, delivered, stripped, empty_return, eta_revised, exception, untracked. |
actual |
boolean | True when the event has happened; false when it is an estimate of a future or unconfirmed milestone. |
occurred_at |
date-time string or null | When the event happened (or is expected to), in UTC. Null when the source gave no time. |
occurred_at_local |
date-time string or null | The same instant written with the UTC offset of the place it happened (for example 2026-09-10T09:20:00-05:00), when the source reported the offset; otherwise the UTC time. Null when occurred_at is null. |
container_number |
string or null | The container the event is about. Null for events about the whole shipment. |
leg_index |
integer or null | The one-based number of the vessel or flight leg of the journey the event belongs to, as counted from the carrier’s event sequence (1 is the first leg, 2 comes after a transshipment). Not the position of a shipment leg. Null when the source does not say. |
location |
object | Where the event happened. |
location.name |
string or null | The place name, such as a port or an airport. |
location.code |
string or null | The location code as reported, a UN/LOCODE for ports (for example NLRTM) where available. |
location.country_code |
string or null | The ISO 3166-1 alpha-2 country code. |
vessel |
object | The vessel involved, for ocean events. |
vessel.name |
string or null | The vessel name. |
vessel.imo |
string or null | The vessel’s IMO number. |
vessel.voyage |
string or null | The voyage number. |
flight_number |
string or null | The flight, for air events. |
position |
object | Coordinates of the event, when the source gave them. |
position.latitude |
number or null | Latitude in decimal degrees. |
position.longitude |
number or null | Longitude in decimal degrees. |
EtaRevision object
One observed change of a shipment’s estimated arrival. Revisions are recorded only when the ETA moves by 5 minutes or more.
| Field | Type | Description |
|---|---|---|
object |
string | Always eta_revision. |
id |
string | The revision id. |
observed_at |
date-time string | When Trackberry saw the new estimate. For backfilled revisions this is only the time of the last refresh, not when the carrier changed its mind. |
previous_eta |
date-time string or null | The estimate before this revision. Null for the first estimate ever learned. |
new_eta |
date-time string | The estimate after this revision. |
slip_seconds |
number or null | How much later the arrival got, in seconds (new_eta minus previous_eta). Negative when the carrier moved the arrival earlier. Null for the first estimate, because there is nothing to compare with. |
first_estimate |
boolean | True for the opening quote, when there was no previous estimate. |
backfilled |
boolean | True when the revision was reconstructed from older data, so observed_at is not the moment the change happened. Leave these out when measuring how fast schedules slip. |
FreeTimeSummary object
The demurrage and detention position of one shipment. Demurrage is the charge for leaving a container at the terminal past its free days; detention is the charge for keeping the empty container past its free days. Only ocean shipments have clocks.
| Field | Type | Description |
|---|---|---|
object |
string | Always free_time_summary. |
shipment_id |
string | The shipment id. |
shipment_reference |
string | The shipment’s Trackberry reference. |
transport_reference |
string or null | The shipment’s bill of lading, air waybill or container number. |
at_risk |
boolean | True when the demurrage clock is running with known free days and 2 days or fewer are left (or it is already overdue). Shipments with unknown terms are never at risk. |
terms_unknown |
boolean | True when the free days for demurrage or detention are not known, meaning neither the shipment, an arrival notice nor the organization’s carrier terms supply them. Set the terms in Trackberry to get countdowns. |
demurrage |
array of FreeTimeClock objects | One demurrage clock per container. Empty for shipments that are not ocean or have no tracking events for it. |
detention |
array of FreeTimeClock objects | One detention clock per container, in the same order as demurrage. Empty for shipments that are not ocean. |
active_clock |
FreeTimeClock object or null | The clock to look at first. The most urgent demurrage clock while demurrage has not finished (this includes a not_started one); once demurrage has stopped or given up, the most urgent detention clock if it is running. Null when there are no clocks or nothing is left to watch. |
FreeTimeClock object
One demurrage or detention clock for one container. Demurrage starts at the container’s discharge and stops at gate out (or, without one, at the return of the empty container). Detention starts at gate out and stops at the return of the empty container. Days are counted in the local calendar of the port. This object has no id.
| Field | Type | Description |
|---|---|---|
object |
string | Always free_time_clock. |
kind |
string | Which charge this clock measures. One of demurrage, detention. |
container_number |
string or null | The container the clock is for. Null when tracking events carry no container number. |
state |
string | not_started means the clock has nothing to count from yet; running means it is counting against known free days; running_unknown_terms means it is counting but the free days are unknown (only elapsed_days is filled); stopped means it has ended (see ended_on, used_days, overdue_days); end_not_reported (demurrage) and return_not_reported (detention) mean the clock gave up waiting for the ending event because the container was archived or received in the warehouse, or 30 days passed without it. One of not_started, running, running_unknown_terms, stopped, end_not_reported, return_not_reported. |
free_days |
integer or null | The number of free days that apply. Null when unknown. |
free_days_source |
string or null | Where free_days comes from, in order of authority. shipment means set on the shipment itself; notice means read from the latest arrival notice; carrier means the organization’s negotiated terms for this carrier. Null when free_days is unknown. One of shipment, notice, carrier. |
free_days_basis |
string or null | How days are counted. calendar counts every day; working skips weekends and the country’s public holidays. Null when there are no known terms. One of calendar, working. |
started_on |
date string or null | The port-local day the clock started (the discharge day for demurrage, the gate-out day for detention). Null while not_started. |
ended_on |
date string or null | The port-local day the clock ended. Null unless stopped. |
last_free_day |
date string or null | The last day that is still free. Null unless running. |
days_left |
integer or null | Free days remaining after today, counted on free_days_basis. 0 means today is the last free day. Negative once overdue (at least -1). Null unless running. |
elapsed_days |
integer or null | Calendar days since the start, counting the start day. Only set while running_unknown_terms. |
used_days |
integer or null | How many days were used between start and end, counting both. Only set when stopped. |
overdue_days |
integer or null | How many days beyond the free days were used. 0 when the clock stopped in time. Only set when stopped and the free days are known. |
carrier |
string or null | The carrier the terms belong to, as a label. |
MonitoringAlert object
A problem Trackberry’s monitoring found on a shipment and that is still open. An alert opens when a problem starts, can grow from warning to critical, and disappears from the API once resolved.
| Field | Type | Description |
|---|---|---|
object |
string | Always monitoring_alert. |
id |
string | The alert id. |
shipment_id |
string | The shipment the alert is about. |
shipment_reference |
string | That shipment’s Trackberry reference. |
key |
string | Which monitor raised it. tracking_halted: the tracking source said it stopped producing data. tracking_blind: the tracking source stopped reaching the carrier. tracking_stale: the carrier has published nothing new for longer than usual. tracking_silent: registered for tracking but the carrier never said anything. tracking_not_found: the tracking source does not recognize the reference. overdue_eta: the ETA passed and arrival is not confirmed. missing_eta: nothing says when it will arrive. eta_drift: the ETA moved 5 days or more later than first quoted. rollover: the container is not on the ship it was booked on. port_dwell: discharged more than 5 days ago and not yet gated out. stalled_draft: approved but never validated. unresolved_checks: failed checks left unresolved for more than 3 days. New keys may be added. One of tracking_halted, tracking_blind, tracking_stale, tracking_silent, tracking_not_found, overdue_eta, missing_eta, eta_drift, rollover, port_dwell, stalled_draft, unresolved_checks. |
group |
string or null | The theme of the alert. Null if the monitor that raised it no longer exists. One of tracking, schedule, workflow. |
severity |
string | How urgent it is. Severity can rise from warning to critical as the problem ages. One of warning, critical. |
title |
string | A short English title for the kind of problem. |
summary |
string or null | An English sentence saying what is wrong on this shipment. |
since |
date-time string or null | When the problem began, as the monitor measures it (for example the moment the ETA passed). Null when unknown. |
first_detected_at |
date-time string or null | When a monitoring sweep first saw the problem. |
last_detected_at |
date-time string or null | When the latest sweep still saw it. |
resolved_at |
date-time string or null | When the problem went away. Always null here, because only open alerts are returned. |
ShipmentCheck object
The result of one quality check run against one shipment, for example whether a packing list is present or whether its box count matches the declared total.
| Field | Type | Description |
|---|---|---|
object |
string | Always shipment_check. |
id |
string | The check result id. |
shipment_id |
string | The shipment the check ran against. |
shipment_reference |
string | That shipment’s Trackberry reference. |
key |
string | The stable identifier of the check, for example has_packing_list, packing_list_box_count or invoice_total. New keys may be added. |
category |
string or null | The kind of problem the check looks for. documents means a required document is missing; data_integrity means figures that should agree do not; data_completeness means a needed value is missing from a document. Null if the check no longer exists. One of documents, data_integrity, data_completeness. |
status |
string | The outcome. pending has not run yet; passed is fine; failed means something is wrong; skipped means its preconditions were not met; warning means it passed with a caveat. One of pending, passed, failed, skipped, warning. |
title |
string | A short English name for this result. |
message |
string or null | An English sentence explaining the outcome. Null when the check has not produced one. |
ran_at |
date-time string or null | When the check last ran. Null if it never ran. |
Document object
A file attached to a shipment, such as a bill of lading, packing list, invoice or certificate, with its processing state. The file itself is not served by the API.
| Field | Type | Description |
|---|---|---|
object |
string | Always document. |
id |
string | The document id. |
shipment_id |
string | The shipment the document belongs to. |
type |
string | What kind of document Trackberry decided it is. transport_document covers bills of lading, air waybills and road consignment notes; merged_document is a single file holding several kinds; unknown means it could not be classified. One of unknown, packing_list, transport_document, invoice, phytosanitary_cert, merged_document, certificate_of_origin, warehouse_receipt, inspection_report, courier_document, other_certificate, arrival_notice. |
filename |
string or null | The file’s name. Null when no file is attached. |
content_type |
string or null | The file’s MIME type. Null when no file is attached. |
byte_size |
integer or null | The file size in bytes. Null when no file is attached. |
source |
string | How the document reached Trackberry. manual_upload was uploaded in the app; email_upload arrived by email; api came in through an integration; correction_link was sent in answer to a correction request. One of manual_upload, email_upload, api, correction_link. |
parse_status |
string | Whether Trackberry has read the document. pending and processing are in progress; parsed means data was extracted; failed means reading failed. One of pending, processing, parsed, failed. |
downloadable |
boolean | True when a file is attached and passed the security scan. The API itself never serves the file; this tells you whether it can be downloaded in the app. |
page_range |
string or null | For a document split out of a larger multi-document PDF, the pages of the original file it covers, like 3-5 or 7. Null for documents that are whole files. |
data_available |
boolean | True when get_document_data will return extracted fields for this document. |
created_at |
date-time string | When the document was added to Trackberry. |
updated_at |
date-time string | When the document record last changed. |
DocumentData object
The structured data Trackberry extracted from one document. The set of fields depends on schema.
| Field | Type | Description |
|---|---|---|
object |
string | Always document_data. |
document_id |
string | The document the data was read from. |
type |
string | The document’s class name when it has one (finer than Document.type, for example exporter_invoice, transport_invoice, sanitary_document), otherwise its type. |
schema |
string or null | The shape of fields. Null when nothing was extracted or the document type has no structured schema, in which case fields is empty. One of packing_list, transport_document, invoice, certificate, inspection_report, arrival_notice. |
fields |
object | The extracted values, keys in snake_case, calendar days as YYYY-MM-DD strings, amounts and weights as numbers, missing values null, repeated groups as arrays of objects. Fields by schema. packing_list: packing_list_number, exporter_name, exporter_port, exporter_country, importer_name, importer_country, total_net_weight, total_boxes, diagram_pallet_numbers, container_number, line_items (each with pallet_number, produce_name, variety, size_calibre, quality_category, format, label, produce_type, ggn, number_of_boxes, net_weight_kg, box_weight_kg, gross_weight_kg). transport_document: transport_type, shipment_reference, equipment_numbers, package_count, package_unit, consignor, consignee, notify_party, carrier, departure_location and arrival_location (each with location_name and country), etd, eta, temperature_setpoint_celsius, cargo_type. invoice: seller_name, seller_location, seller_country, buyer_name, buyer_location, buyer_country, invoice_number, invoice_date, total_amount, currency, line_items (each with produce_description, produce_name, variety, calibre, pack_format, box_weight_kg, quantity, unit_price, price_unit, total_amount). certificate: exporter_name, exporter_location, exporter_country, importer_name, importer_location, importer_country, certificate_number, certificate_date, produce_description. inspection_report: inspection_company, inspector_name, report_number, inspection_date, inspection_location, container_number, produce_description, total_pallets, overall_impression, overall_score, overall_impression_category, general_remarks, results (each with pallet_number, lot_code, produce_name, variety, calibre, score, recommendation, remarks, defects, photo_numbers). arrival_notice: carrier_name, bill_of_lading_number, container_numbers, vessel_arrival_date, free_time (each with applies_to, cargo_class, days, hours, basis, from_date, until_date, from_event, estimated, quote). Fields may be added over time. |
PackingList object
A packing list read from a document, saying what the exporter states is in the container, by pallet and produce line.
| Field | Type | Description |
|---|---|---|
object |
string | Always packing_list. |
id |
string | The packing list id. |
shipment_id |
string | The shipment it belongs to. |
document_id |
string or null | The document it was read from. Null when it was created without one. |
container_id |
string or null | The container it covers. Null when the document did not say. |
reference |
string or null | The packing list’s own number. |
declared_box_count |
integer or null | The total number of boxes the document states, before Trackberry sums the lines. Compare with totals.boxes. |
declared_net_weight_kg |
number or null | The total net weight in kilograms the document states. Compare with totals.net_weight_kg. |
totals |
object | Totals Trackberry computed from this packing list’s own visible lines. |
totals.pallets |
integer | Number of pallets on this packing list. |
totals.boxes |
integer | Sum of the box counts of its lines. |
totals.net_weight_kg |
number | Sum of the net weights of its lines, in kilograms. |
pallets |
array of Pallet objects | The pallets of this packing list, oldest first. |
Pallet object
One pallet of a packing list.
| Field | Type | Description |
|---|---|---|
object |
string | Always pallet. |
id |
string | The pallet id. |
pallet_number |
string or null | The pallet’s number or SSCC as printed on the packing list. Unique within a shipment when set. |
container_id |
string or null | The container the pallet is loaded in. Null when unknown. |
lines |
array of PackingLine objects | The pallet’s produce lines in reading order. Lines merged into another line are left out. |
PackingLine object
One produce line on a pallet, a quantity of one variety, calibre and pack format.
| Field | Type | Description |
|---|---|---|
object |
string | Always packing_line. |
id |
string | The line id. |
line_index |
integer or null | The line’s position in the packing list, used to order lines. |
produce_name |
string or null | The produce, normalized (for example Grapes). |
produce_type |
string or null | How the produce was grown, as written on the packing list. Lines marked organic (any letter case) make the shipment organic. |
variety |
string or null | The variety or cultivar. |
calibre |
string or null | The size grade of the produce. |
quality_category |
string or null | The quality class, such as Class I. |
pack_format |
string or null | How the produce is packed, for example a carton size. |
label |
string or null | The brand or label printed on the packaging. |
ggn |
string or null | The GLOBALG.A.P. Number (GGN) of the producer, when stated. |
box_count |
integer or null | Number of boxes on this line. |
box_weight_kg |
number or null | Net weight of one box in kilograms. |
net_weight_kg |
number or null | Net weight of the whole line in kilograms. |
gross_weight_kg |
number or null | Gross weight of the whole line in kilograms, packaging included. |
What the API doesn’t do yet
- No writes. You can’t create shipments, approve them or upload documents through the API.
- No file downloads.
/documents/{id}describes a document but doesn’t link to the file. Download it in the app or with the document library export. - No webhooks. Trackberry can’t call your system when a shipment changes;
poll
/shipmentsor/alertsinstead. - No browser calls. The API is for servers and scripts, so it doesn’t send CORS headers.
If one of these would unblock you, email support@trackberry.com with what you’re building.