This API is in Beta. Behavior may change. Contact developers@tread.io with questions or feedback.
Base URL and authentication
Every Importer endpoint lives under the same host as the rest of the API, with an/ingest prefix.
Content-Type depends on the endpoint. Orders, Projects, and Tickets take JSON:
metadata object for your own tracking, like a batch ID or source system name. Tread stores it but doesn’t act on it.
The async model
Orders, Projects, and Tickets process asynchronously. A202 Accepted response means Tread saved your payload and queued it for processing. It does not mean the record was created or updated.
Two ways to check on a payload after you send it:
- Reports > API Integrations in the Tread app. Shows Imported For, Import Received At, State, Last Error, and the raw payload you sent. Defaults to the last 7 days, most recent first.
- Error webhooks, if you’ve configured one. Tread pushes an event when a payload fails to process. See Webhooks.
If a record is
failed or exhausted, read its last_error field for the reason, fix the source data, and resend. Tread deduplicates automatically, so resending the same payload is safe.
The Files endpoint is the one exception — it processes synchronously. See Files.
Orders
POST /ingest/orders creates or updates Orders. The root key is orders — send an array, even for a single record.
Required fields
Example request
Behavior notes
- Matching is by
external_id, scoped to your company. A match updates the order’s root fields — name, quantities, rates, notes, and so on. customer,material,equipment_type, andsitesare nested records. Tread creates them if they don’t exist but doesn’t update them on a match — see external_id matching.foremenandvendorsare arrays. Every payload replaces the whole array — it doesn’t merge with what’s already there. This is true even if you omit the field: omittingforemendoes not preserve the existing foremen. Send the complete set every time.- If an order is canceled and you later send a payload with the same
external_idin a non-canceled state, Tread renames the canceled order’sexternal_idtoX-{N}and creates a new order. This is automatic — no cleanup needed on your end.
Projects
POST /ingest/projects creates or updates Projects. The root key is projects.
Required fields
Example request
Behavior notes
- Matching is by
external_id. A match updates root fields — name, dates, notes, rates. - Phase sync is destructive. Every payload replaces the full phase list. A phase left out of the payload is deleted. Always send the complete set, not just what changed.
- Materials sync the same way. A material left out of the payload is removed from the project.
- Sites need an address. Every site needs
full_addressorlat/lon. If your source data only has a site name, setfull_addressto that name — Tread geocodes it automatically. Without one of these, the site fails validation and is silently dropped: the project still reports success, but that pickup or drop-off is missing and no error surfaces. See Site Coordinates & Geofences for the coordinate format and how the geofence gets built. foremenreplace on update, the same as Orders.- If a project’s name collides with a different project’s name, Tread appends
-{external_id}to keep both.
Tickets
POST /ingest/tickets creates Tickets — the proof-of-load record for one Load. Root key is tickets.
Required fields
Example request
Behavior notes
- Tread links a ticket to an order two ways:
tread_order_id(direct, preferred) ordispatch_numberplus a matching job start date (fallback). Sendtread_order_idwhen you have it. unit_of_measurenormalization is case-insensitive but exact values are safer."tons"becomes"Ton", but a string the system doesn’t recognize can silently fall back to the default (Ton) instead of erroring. Use the exact enum value.siteis a single object on Tickets — unlike Orders and Projects, wheresitesis an array.
Files
POST /ingest/files attaches a file to an existing (or soon-to-exist) Order. It uses multipart/form-data, not JSON — every other Importer endpoint uses JSON.
Required fields
Optional:
category (Inspection Report, Site Map, Scale Ticket (External), Scale Ticket (Internal), Timesheet, or Other) and description. Maximum file size is 10 MB. Accepted types: JPEG, PNG, WebP, GIF, and PDF.
Example request
Behavior notes
Files process synchronously — the one exception among the Importer APIs.201 Created— the Order already exists. Tread attaches the file immediately.202 Accepted— the Order doesn’t exist yet. Tread stores the file and attaches it automatically once a matching Order arrives — files and orders can arrive in either order. No extra call needed.422— the file failed validation (wrong type or over 10 MB).
external_id matching and upsert behavior
Every Importer endpoint usesexternal_id — your system’s identifier — to decide whether to create a new record or update an existing one. It’s scoped per company and case-sensitive.
Root records (Order, Project, Ticket) work as you’d expect: found by external_id → update; not found → create.
Nested records (customer, material, equipment type, sites, foremen) work differently. Tread creates them if they don’t exist, but generally doesn’t update their fields once matched. Sending a different name for a customer that already exists doesn’t rename it.
To rename a customer, material, or other master-data record, use the REST API elsewhere in this reference — not the Importer APIs.
Arrays follow one of three patterns on update:
Enum reference
Exact string values Tread expects. A value outside this list either gets normalized (unit of measure) or rejected. Unit of measure —Load, Tonne, Ton, Yard, Meter, Foot, Liter, Hour, Bushel, Gallon, CubicMeter, Mile, Kilometer, Barrel, Bag, Pallet. Default: Ton.
Rate type — RatePerHour (default), RatePerDay, RatePerLoad, RatePerTon, RatePerTonne, RatePerYard, RatePerBushel, RateCommission, RateFlatCommission, RateFlatRate.
Site waypoint — pickup, staging, drop_off, weigh_point.
Site type — Plant, Quarry, JobSite, Depot, EquipmentHomeBase, Daily, Other (default).
Common pitfalls
202doesn’t mean it worked. Check the imported record’s state before you treat a payload as done.- Nested records don’t update on match. Renaming a customer or material in your payload has no effect once that record already exists. Use the REST API to rename it.
- Sites without an address are dropped, silently. No
full_addressorlat/lonon a site means Tread drops it — and the Project or Order still reports success. So does sending one coordinate without the other. See Site Coordinates & Geofences. - Invalid phone numbers are dropped, silently. A phone that doesn’t normalize to E.164 is stripped from the contact. No error, no
last_errorentry. - Duplicate payloads are skipped, not reprocessed. Sending the exact same payload twice marks the second one
skipped. This is expected, not a bug. - Phase sync deletes what you leave out. Every Project payload replaces the entire phase list, not just the phases you’re changing.
- Foremen and vendors replace, they don’t merge. Every payload with a
foremenorvendorsarray swaps the whole thing, even if you omit the field. - Unit of measure is picky.
"tons"normalizes to"Ton", but a string the system doesn’t recognize silently falls back to the default (Ton) instead of erroring. Use exact enum values.
Managing individual records
Need to create, update, or delete one record at a time instead of bulk-loading? Use the REST API endpoints elsewhere in this reference. They’re synchronous — a201 or 200 means it’s done — and they support full field updates on nested records, including renaming a customer or material. The Importer APIs are for bulk loads only.
Going further
Site Coordinates & Geofences
Send
lat/lon so imported Sites get a working geofence.Authentication
Get a bearer token for these endpoints.
Webhooks
Get notified when an imported payload fails to process.
Orders and Projects
How the dispatch hierarchy fits together.
Tickets and Timesheets
What a Ticket records, and how it becomes a Settlement.