Dossiers API
The Dossiers API provides full CRUD operations for managing customs dossiers, which group related declarations and transits, track purchase costs, and generate revenue for invoicing.
Required Scope: dossiers:read, dossiers:write, dossiers:delete
List Dossiers
Retrieve a paginated list of dossiers with optional filters.
curl -X GET "https://app.borderbolt.com/api/v1/dossiers?status=open&page=1" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Query Parameters
| Parameter | Type | Description |
|---|---|---|
customer_code | string | Filter by customer code (exact match) |
status | string | Filter by status (open, complete, ready_to_invoice, invoiced, closed) |
transport_mode | string | Filter by transport mode |
dossier_number | string | Filter by dossier number (partial match) |
customer_reference | string | Filter by customer reference (partial match) |
search | string | Search across dossier number, AWB/BL numbers, customer reference |
created_from | date | Filter by creation date (from, YYYY-MM-DD) |
created_to | date | Filter by creation date (to, YYYY-MM-DD) |
sort | string | Field to sort by: id, created_at, updated_at, dossier_number, status, customer_code (default: created_at) |
direction | string | asc or desc (default: desc) |
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 25, max: 100) |
Response
{
"data": [
{
"id": 3001,
"dossier_number": "DOS-2026-001",
"customer_code": "CUST001",
"invoice_to_customer_id": null,
"status": "open",
"master_airwaybill": null,
"house_airwaybill": null,
"master_bill_of_lading": null,
"house_bill_of_lading": null,
"vessel_name": null,
"voyage_number": null,
"transport_mode": "air",
"carrier_name": null,
"carrier_eori": null,
"eta": "2026-04-01T00:00:00+00:00",
"etd": null,
"invoice_frequency": "immediate",
"invoice_reference": "PO-2026-441",
"invoiced_at": null,
"prepayment_amount": null,
"prepayment_invoice_id": null,
"is_prepaid": false,
"total_colli": null,
"total_weight": null,
"goods_location_id": null,
"incoterms": null,
"incoterms_place": null,
"incoterms_location_id": null,
"shipper_details": null,
"chargeable_weight": null,
"pickup_window_from": null,
"pickup_window_to": null,
"estimated_departure_from": null,
"estimated_departure_to": null,
"estimated_arrival_from": null,
"estimated_arrival_to": null,
"actual_departure": null,
"actual_arrival": null,
"internal_notes": null,
"customer_reference": "Q1-2026",
"declarations": [
{
"id": 12345,
"declaration_type": "H1",
"lrn": null,
"mrn": "26NL123456789012345",
"status": "REL"
}
],
"invoice_lines": [
{
"id": 201,
"dossier_id": 3001,
"billable_item_id": 42,
"description": "Customs clearance service",
"quantity": 5,
"unit_price": 100.00,
"amount": 500.00,
"vat_rate": 21.00,
"vat_amount": 105.00,
"payment_term_group": "handling",
"is_locked": false
}
],
"purchase_lines": [
{
"id": 101,
"dossier_id": 3001,
"category": "freight",
"description": "Transport costs",
"quantity": 1,
"unit_price": 500.00,
"amount": 500.00,
"vat_rate": 21.00,
"vat_amount": 105.00,
"currency": "EUR"
}
],
"invoices_count": 0,
"pending_invoice_lines_count": 2,
"created_at": "2026-03-20T10:00:00+00:00",
"updated_at": "2026-03-25T14:30:00+00:00"
}
],
"meta": {
"current_page": 1,
"last_page": 2,
"per_page": 25,
"total": 45
}
}Get Single Dossier
Retrieve a single dossier, including its linked declarations and transits.
curl -X GET "https://app.borderbolt.com/api/v1/dossiers/3001" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Response
Same shape as a list item, plus transits (list items omit transits):
{
"data": {
"id": 3001,
"dossier_number": "DOS-2026-001",
"customer_code": "CUST001",
"status": "open",
"invoice_reference": "PO-2026-441",
"declarations": [
{
"id": 12345,
"declaration_type": "H1",
"lrn": null,
"mrn": "26NL123456789012345",
"status": "REL"
}
],
"transits": [
{
"id": 5001,
"lrn": "26NL00001234567890123",
"mrn": "26NL12345678901234567",
"status": "CMP"
}
],
"invoice_lines": [
{
"id": 201,
"dossier_id": 3001,
"billable_item_id": 42,
"description": "Customs clearance service",
"quantity": 5,
"unit_price": 100.00,
"amount": 500.00,
"vat_rate": 21.00,
"vat_amount": 105.00,
"payment_term_group": "handling",
"is_locked": false
}
],
"purchase_lines": [
{
"id": 101,
"dossier_id": 3001,
"category": "freight",
"description": "Transport costs",
"quantity": 1,
"unit_price": 500.00,
"amount": 500.00,
"vat_rate": 21.00,
"vat_amount": 105.00,
"currency": "EUR"
}
],
"invoices_count": 0,
"pending_invoice_lines_count": 2
}
}invoice_lines includes both pending and already-invoiced lines. For invoiced lines grouped by which invoice they belong to, use List Invoice Lines instead.
Create Dossier
Create a new dossier.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"customer_code": "CUST001",
"dossier_number": "DOS-2026-002",
"customer_reference": "Q1-2026",
"invoice_reference": "PO-2026-441",
"transport_mode": "air",
"master_airwaybill": "123-45678901",
"eta": "2026-04-01"
}'Request Body
| Field | Required | Type | Description |
|---|---|---|---|
customer_code | Yes | string | Customer code (max 50 chars) |
dossier_number | No | string | Unique dossier number (auto-generated if omitted) |
invoice_to_customer_id | No | integer | Override the invoice-to customer. Must be a company on the customer’s invoice-to allow-list (configured on the customer record) - otherwise the request is rejected with a validation error. |
invoice_reference | No | string | Customer’s PO/reference to print on the resulting invoice. Required before a declaration can be created for this dossier - set it here or update it later, before calling Create Declaration. |
transport_mode | No | string | Transport mode (e.g. air, sea, road) |
master_airwaybill | No | string | Master AWB number |
house_airwaybill | No | string | House AWB number |
master_bill_of_lading | No | string | Master BL number |
house_bill_of_lading | No | string | House BL number |
vessel_name | No | string | Vessel name |
voyage_number | No | string | Voyage number |
carrier_name | No | string | Carrier name |
carrier_eori | No | string | Carrier EORI number |
eta | No | date | Estimated time of arrival (YYYY-MM-DD) |
etd | No | date | Estimated time of departure (YYYY-MM-DD) |
customer_reference | No | string | Customer’s own reference |
internal_notes | No | string | Internal notes |
invoice_frequency | No | string | immediate, delayed, weekly, monthly |
total_colli | No | integer | Total number of colli/packages |
total_weight | No | decimal | Total shipment weight (kg) |
chargeable_weight | No | decimal | Chargeable weight for freight billing (kg) |
goods_location_id | No | integer | Customer location ID where goods are held |
incoterms | No | string | Incoterms code (e.g. FOB, CIF, EXW) |
incoterms_place | No | string | Incoterms named place |
incoterms_location_id | No | integer | Customer location ID for the incoterms place |
shipper_details | No | string | Free-text shipper details |
pickup_window_from / pickup_window_to | No | datetime | Pickup window |
estimated_departure_from / estimated_departure_to | No | datetime | Estimated departure window |
estimated_arrival_from / estimated_arrival_to | No | datetime | Estimated arrival window |
actual_departure | No | datetime | Actual departure timestamp |
actual_arrival | No | datetime | Actual arrival timestamp |
is_prepaid | No | boolean | Whether this dossier is covered by a prepayment |
prepayment_amount | No | decimal | Prepayment amount applied |
prepayment_invoice_id | No | integer | Invoice ID the prepayment was drawn from |
Update Dossier
Update an existing dossier. Accepts the same fields as Create Dossier (all optional), plus status.
curl -X PUT "https://app.borderbolt.com/api/v1/dossiers/3001" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"invoice_reference": "PO-2026-441-REV2",
"status": "complete"
}'Changing invoice_to_customer_id re-prices every pending (not-yet-invoiced) revenue line under the new billing customer’s rate card and VAT treatment.
Delete Dossier
Delete a dossier. Only dossiers that are still editable (not locked by an invoiced/closed state) can be deleted.
curl -X DELETE "https://app.borderbolt.com/api/v1/dossiers/3001" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Link Declaration
Link an existing declaration to a dossier. Requires the dossier’s billing customer to have an active rate card with at least one billable item configured.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/link-declaration" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"declaration_id": 12345
}'Unlink Declaration
Remove a declaration from a dossier.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/unlink-declaration" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"declaration_id": 12345
}'Link Transit
Link a transit declaration to a dossier. Same billing-setup requirement as linking a declaration.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/link-transit" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"transit_id": 5001
}'Unlink Transit
Remove a transit from a dossier.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/unlink-transit" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"transit_id": 5001
}'Purchase Lines (Costs)
List Purchase Lines
curl -X GET "https://app.borderbolt.com/api/v1/dossiers/3001/purchase-lines" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Add Purchase Line
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/purchase-lines" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"description": "Transport costs",
"category": "freight",
"quantity": 1,
"unit_price": 500.00,
"vat_rate": 21.00
}'category must be one of: duties, taxes, freight, inspection, storage, handling, other.
Update Purchase Line
curl -X PUT "https://app.borderbolt.com/api/v1/dossiers/3001/purchase-lines/101" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"unit_price": 550.00
}'Delete Purchase Line
curl -X DELETE "https://app.borderbolt.com/api/v1/dossiers/3001/purchase-lines/101" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Purchase lines cannot be added, updated, or deleted once the dossier has been invoiced or closed.
Invoice Lines (Revenue)
List Invoice Lines
Returns both pending (not-yet-invoiced) and already-invoiced lines.
curl -X GET "https://app.borderbolt.com/api/v1/dossiers/3001/invoice-lines" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"{
"dossier_id": 3001,
"dossier_number": "DOS-2026-001",
"pending_lines": [
{
"id": 201,
"type": "pending",
"invoice_id": null,
"description": "Customs clearance service",
"quantity": 5,
"unit_price": 100.00,
"amount": 500.00,
"vat_rate": 21.00,
"payment_term_group": "handling",
"triggered_at": "2026-03-22T09:15:00+00:00"
}
],
"invoiced_lines": [],
"totals": {
"pending_amount": 500.00,
"invoiced_amount": 0
}
}Add Invoice Line
Every revenue line must reference a revenue-type billable item from the customer’s active rate card - a purchase-type item is rejected.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/invoice-lines" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"billable_item_id": 42,
"description": "Customs clearance service",
"quantity": 5,
"unit_price": 100.00,
"vat_rate": 21.00
}'If vat_rate is omitted, it’s resolved from the rate card (with reverse-charge applied automatically when the billing customer is eligible).
Update Invoice Line
curl -X PUT "https://app.borderbolt.com/api/v1/dossiers/3001/invoice-lines/201" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"unit_price": 110.00
}'Delete Invoice Line
curl -X DELETE "https://app.borderbolt.com/api/v1/dossiers/3001/invoice-lines/201" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Invoice lines cannot be updated or deleted once they’ve been invoiced.
Recalculate Revenue
Re-run the rate card’s automated triggers for this dossier, generating any new revenue lines that are now due.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/recalculate-revenue" \
-H "Authorization: Bearer your-access-token" \
-H "Accept: application/json"Response
{
"data": {
"lines_count": 1,
"total_revenue": 2750.00,
"total_revenue_vat": 577.50,
"margin": 1500.00,
"margin_percentage": 54.55
},
"message": "Generated 1 revenue lines"
}Update Status
Transition a dossier to a new status. Not all transitions are allowed - see the workflow table below.
curl -X POST "https://app.borderbolt.com/api/v1/dossiers/3001/update-status" \
-H "Authorization: Bearer your-access-token" \
-H "Content-Type: application/json" \
-d '{
"status": "complete"
}'Request Body
| Field | Required | Type | Description |
|---|---|---|---|
status | Yes | string | Target status: open, complete, ready_to_invoice, invoiced, or closed |
Example Response
{
"data": {
"old_status": "open",
"new_status": "complete",
"dossier": {
"id": 3001,
"status": "complete"
}
},
"message": "Dossier status updated to complete"
}HTTP 422 is returned for invalid transitions.
Status Workflow
| Status | Description | Allowed Next Statuses |
|---|---|---|
open | Active dossier, costs/revenue still being accumulated | complete, closed |
complete | Work done; automated revenue triggers run once on entry | open, ready_to_invoice, closed |
ready_to_invoice | Queued for the next invoice run | complete, invoiced, closed |
invoiced | Invoice generated; purchase/invoice lines are locked | closed |
closed | Paid and archived | open |
Next Steps
- Invoices API - Generate invoices from dossiers
- Declarations API - Link declarations to dossiers (requires
invoice_referenceset on the dossier first) - Transit API - Link transit to dossiers