Read your bookings, equipment, customers and invoices from your own software. Read-only: a key can never change anything in your account.
Available on the Unlimited plan. Create keys in your dashboard under Integrations → API keys.
Send your key as a bearer token on every request. Keys look like hb_ followed by 48 hexadecimal characters.
curl https://haulbase.ca/api/v1/bookings \
-H "Authorization: Bearer hb_your_key_here"A key reads your whole yard. Treat it like a password: keep it on a server, never in a browser, a phone app, or anything you publish. We store only a fingerprint of it, so we can never show it to you again - if you lose one, revoke it and create another.
Every endpoint returns the same shape: a data array and a paging object.
{
"data": [ { "id": "…", "…": "…" } ],
"paging": { "limit": 50, "offset": 0, "total": 128, "has_more": true }
}Rows come back newest first. Page with limit and offset, and stop when has_more is false - not when a page comes back short, which can happen for other reasons.
| Parameter | Default | What it does |
|---|---|---|
limit | 50 | Rows per page, 1 to 200. Anything higher is capped at 200. |
offset | 0 | Rows to skip. |
from | – | Earliest date, YYYY-MM-DD. Any other format is ignored rather than guessed at. |
to | – | Latest date, YYYY-MM-DD. |
GET /api/v1/bookingsEvery rental: dates, totals, what was paid and how, deposits, delivery, and the platform fee. (from / to filter on start_date)
idunit_idcustomer_idcustomer_namecustomer_phonecustomer_emailstart_dateend_datetotalpaid_amountstatuspayment_statuspaid_methodpaid_attax_ratetax_labeldeposit_amountdeposit_statusdelivery_requesteddelivery_feedelivery_distance_kmaccessories_totaldiscount_amountpromo_labelcommission_amountproduct_typequantitymeter_outmeter_inoverage_unitsoverage_amountcreated_atGET /api/v1/unitsYour fleet: rates, category, meter readings, service dates and asset details. (from / to filter on created_at)
idyard_idlabelnicknametypecategoryproduct_typestatusdaily_rateweekly_ratemonthly_ratedamage_deposit_amountdescriptionbilling_modeusage_meter_typeincluded_units_per_dayoverage_unit_ratecurrent_meter_readingunit_of_measuremin_orderorder_incrementserial_numberyearmakemodellicence_platelast_servicenext_serviceretired_atcreated_atGET /api/v1/customersYour customer list and how many times each has rented. (from / to filter on created_at)
idnamephoneemailrentalscreated_atGET /api/v1/invoicesNumbered invoices with status, due dates and what has been paid. (from / to filter on created_at)
idbooking_idinvoice_numbercustomer_namecustomer_phonecustomer_emailamounttaxabletax_ratetax_labelnotestatusdue_datesent_atpaid_atwritten_off_atpaid_methodcreated_atFields not listed above are deliberately not exposed - signed agreements, driving licence details and payment-processor identifiers stay inside Haulbase.
120 requests per 60 seconds per key. Going over returns 429 with a Retry-After header saying how many seconds to wait. Counting is per key, not per address, so one busy integration cannot throttle another.
| Status | Means |
|---|---|
401 | Missing, malformed, revoked or unknown key. |
402 | The account’s plan no longer includes API access. |
429 | Rate limited. Wait for the number of seconds in Retry-After. |
500 | Our fault. Retry with a backoff. |
Errors are JSON: { "error": "…" }. If an account drops to a plan without API access, the key keeps working for a short grace period and the responses carry an X-Haulbase-Notice header saying when it stops - so an overnight sync warns you rather than simply failing one morning.
let offset = 0;
const all = [];
while (true) {
const res = await fetch(
`https://haulbase.ca/api/v1/bookings?limit=200&offset=${offset}`,
{ headers: { Authorization: `Bearer ${process.env.HAULBASE_KEY}` } }
);
if (!res.ok) throw new Error(`Haulbase API: ${res.status}`);
const { data, paging } = await res.json();
all.push(...data);
if (!paging.has_more) break;
offset += paging.limit;
}