REST API · v1
WasteBolt API
Create and manage Waste Transfer Notes programmatically. Integrate WasteBolt into your weighbridge software, ERP, or custom workflow.
Jump to section
Quick Start
The fastest way to explore the API is with our Bruno collection — a ready-to-run set of requests covering every endpoint, including hazardous waste, POPs, and DWT submission scenarios.
WasteBolt Bruno Collection
8 pre-built requests · all waste types · environment variables · DWT readiness examples
Install Bruno (free, open source API client)
Download and unzip the collection above, then open the folder in Bruno
Open Environments → Production and replace your_api_key_here with your key
Select the Production environment and run any request — check dwt_readiness in the response
Base URL
https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1Authentication
All API requests require an x-api-key header containing your WasteBolt API key. Keys are generated from your account under Settings → Apps & Downloads. Keys are prefixed with wbsync_.
x-api-key: wbsync_AbCdEfGhIjKlMnOpQrStUvWxYz012345Keep your API key secret. Do not expose it in client-side code or public repositories. If a key is compromised, disable it immediately from Apps & Downloads and create a new one.
Rate Limiting
Each API key is limited to 60 requests per minute. Limits are tracked per key using a fixed 1-minute window. All responses include rate limit headers so you can monitor usage.
X-RateLimit-LimitMax requests per window
60X-RateLimit-RemainingRequests left this window
47X-RateLimit-ResetWindow reset timestamp (ISO)
2026-03-02T09:02:00ZWhen the limit is exceeded you will receive a 429 response with a Retry-After header indicating seconds until reset.
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2026-03-02T09:02:00.000Z
Retry-After: 23
{
"success": false,
"error": "Rate limit exceeded. 60 requests per minute allowed. Retry in 23s.",
"code": "RATE_LIMIT_EXCEEDED"
}Error Codes
All error responses share the same shape. The code field is stable and safe to use in your error handling logic.
{
"success": false,
"error": "Human readable message",
"code": "MACHINE_READABLE_CODE"
}| Code | HTTP | Description |
|---|---|---|
| NO_API_KEY | 401 | x-api-key header missing from request |
| INVALID_KEY_FORMAT | 401 | Key does not start with wbsync_ |
| INVALID_KEY | 401 | Key not found in WasteBolt |
| KEY_DISABLED | 401 | Key has been manually disabled |
| KEY_EXPIRED | 401 | Key has passed its expiry date |
| SUBSCRIPTION_INACTIVE | 403 | WasteBolt subscription has expired |
| RATE_LIMIT_EXCEEDED | 429 | 60 req/min limit reached — see Retry-After header |
| VALIDATION_ERROR | 422 | Required field missing or invalid |
| INVALID_STATUS | 422 | Status value not allowed via API |
| NOT_FOUND | 404 | WTN not found or not accessible by this key |
| WTN_LOCKED | 409 | WTN is signed and cannot be updated |
| INVALID_JSON | 400 | Request body is not valid JSON |
| INVALID_ID | 400 | WTN id in the URL must be numeric |
| METHOD_NOT_ALLOWED | 405 | HTTP method not supported on this endpoint |
| NOTE_NUMBER_ERROR | 500 | Failed to generate a unique note number — retry |
| DATABASE_ERROR | 500 | Internal database error — retry after a moment |
/create-wtn-apiCreate a Waste Transfer Note
Creates a new WTN under your account. Returns the full note including the auto-generated note number.
Required Fields
Optional Fields
Hazardous waste — set waste_details.is_hazardous: true
These fields follow the same standard as WasteBolt's own hazardous WTN form, so notes created here submit to DWT identically.
POPs — set waste_details.contains_pops: true
POPs can apply to hazardous or non-hazardous waste — the two flags are independent.
curl -X POST https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1/create-wtn-api \
-H "x-api-key: wbsync_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"producer_details": {
"name": "Acme Waste Ltd",
"address": "123 Industrial Estate, Birmingham, B1 1AA",
"postcode": "B1 1AA"
},
"carrier_details": {
"name": "Fast Carriers Ltd",
"address": "456 Transport Road, Coventry, CV1 2BB",
"vehicle_reg": "AB12 CDE",
"license_no": "CBDU123456"
},
"consignee_details": {
"name": "Green Recycling Ltd",
"address": "789 Waste Park, Wolverhampton, WV1 3CC",
"postcode": "WV1 3CC",
"license_no": "EPR/AB1234CD/A001",
"contact_email": "site@greenrecycling.co.uk"
},
"waste_details": {
"waste_ewc": "20 03 01",
"waste_name": "Mixed municipal waste",
"weight_kg": 5000,
"is_hazardous": false,
"contains_pops": false
},
"transfer_details": {
"transfer_date": "2026-03-02"
},
"note_type": "single",
"status": "draft"
}'curl -X POST https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1/create-wtn-api \
-H "x-api-key: wbsync_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"producer_details": {
"name": "Acme Waste Ltd",
"address": "123 Industrial Estate, Birmingham, B1 1AA"
},
"carrier_details": {
"name": "Fast Carriers Ltd",
"vehicle_reg": "AB12 CDE",
"license_no": "CBDU123456"
},
"consignee_details": {
"name": "Green Recycling Ltd",
"address": "789 Waste Park, Wolverhampton",
"postcode": "WV1 3CC",
"license_no": "EPR/AB1234CD/A001",
"contact_email": "site@greenrecycling.co.uk"
},
"waste_details": {
"waste_ewc": "16 06 01*",
"waste_name": "Waste batteries",
"weight_kg": 500,
"is_hazardous": true,
"hazardous_property_code": ["HP_3", "HP_14"],
"source_of_components": "OWN_TESTING",
"hazardous_components": [
{ "name": "Lead", "concentration": 12.5 }
],
"hazardous_waste_consignment_code": "ABC123/00001",
"contains_pops": true,
"pops_source_of_components": "OWN_TESTING",
"pops_components": [
{ "code": "PFOS", "concentration": 0.005 }
]
},
"transfer_details": {
"transfer_date": "2026-03-02"
}
}'const response = await fetch(
'https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1/create-wtn-api',
{
method: 'POST',
headers: {
'x-api-key': 'wbsync_YOUR_KEY_HERE',
'Content-Type': 'application/json',
},
body: JSON.stringify({
producer_details: {
name: 'Acme Waste Ltd',
address: '123 Industrial Estate, Birmingham, B1 1AA',
},
waste_details: {
waste_ewc: '20 03 01',
waste_name: 'Mixed municipal waste',
weight_kg: 5000,
},
transfer_details: {
transfer_date: '2026-03-02',
},
}),
}
);
const data = await response.json();
console.log(data.data.note_number); // e.g. "ACM-1042"
console.log(data.dwt_readiness); // { ready, errors: [...], warnings: [...] }{
"success": true,
"message": "Waste Transfer Note created successfully",
"data": {
"id": 1042,
"note_number": "ACM-1042",
"status": "draft",
"note_type": "single",
"created_at": "2026-03-02T09:15:32.000Z",
"producer_details": { ... },
"carrier_details": { ... },
"consignee_details": { ... },
"waste_details": { ... },
"transfer_details": { ... }
},
"dwt_readiness": {
"ready": false,
"errors": [],
"warnings": [
"Carrier registration/licence number is missing — DWT submission will need carrier_details.registration_reason"
]
}
}dwt_readiness
Every successful create response includes a dwt_readiness object — the same checks WasteBolt runs before a WTN can be submitted to DEFRA's Digital Waste Tracking service. errors block DWT submission until fixed; warnings won't block submission but will prompt for a reason (e.g. no carrier registration, no consignment code) inside the app.
/wtn-apiList Waste Transfer Notes
Returns a paginated list of WTNs for your account, newest first. Supports filtering by status, date range, note type, DWT status, and note number search.
Query Parameters
curl "https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1/wtn-api?status=complete&from=2026-01-01&limit=20&page=1" \
-H "x-api-key: wbsync_YOUR_KEY_HERE"{
"success": true,
"data": [ { ... }, { ... } ],
"pagination": {
"total": 84,
"page": 1,
"limit": 20,
"total_pages": 5,
"has_next": true,
"has_prev": false
},
"filters_applied": {
"status": "complete",
"from": "2026-01-01"
}
}/wtn-api/:idGet a Single WTN
Returns a single WTN by its numeric ID. Only returns WTNs belonging to your account.
curl "https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1/wtn-api/1042" \
-H "x-api-key: wbsync_YOUR_KEY_HERE"{
"success": true,
"data": {
"id": 1042,
"note_number": "ACM-1042",
"status": "complete",
"note_type": "single",
"created_at": "2026-03-02T09:15:32.000Z",
"dwt_status": "pending",
"producer_details": { ... },
"carrier_details": { ... },
"consignee_details": { ... },
"waste_details": { ... },
"transfer_details": { ... }
}
}/wtn-api/:idUpdate WTN Status
Updates the status of a WTN. Signed WTNs are locked and cannot be modified via the API.
Body Fields
curl -X PATCH "https://vfhjhirnyulkvkmukpbj.supabase.co/functions/v1/wtn-api/1042" \
-H "x-api-key: wbsync_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"status": "complete"}'{
"success": true,
"message": "WTN updated successfully",
"data": {
"id": 1042,
"note_number": "ACM-1042",
"status": "complete",
...
}
}API FAQ.
Common questions about integrating with WasteBolt.
How many requests can I make?
Each API key is limited to 60 requests per minute, tracked with a fixed 1-minute window. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers so you can monitor usage — exceeding the limit returns a 429 with a Retry-After header.
Can I create hazardous waste WTNs through the API?
Yes. Set waste_details.is_hazardous to true and supply the HP codes, source of components, and hazardous components — the same fields WasteBolt's own hazardous WTN form uses, so notes created via the API submit to DWT identically. POPs fields work the same way and are independent of the hazardous flag.
What happens if I try to update a signed WTN?
Signed WTNs are locked. A PATCH request against one returns a 409 with code WTN_LOCKED rather than modifying it.
Does the API support Season Tickets?
Yes — set note_type to "season_ticket" on create, the same as creating one in the web app.
What should I do if my API key is compromised?
Disable it immediately from Settings → Apps & Downloads in your WasteBolt account and generate a new one. Keys are prefixed wbsync_ and should never be exposed in client-side code or public repositories.
Related Features