π½ Downstream API - send to π
Endpointsβ
| Method | Path | Description |
|---|---|---|
| POST | /downstream/tradeflows | Create a tradeflow or update an existing one. Accepts a single object or an array. |
| DELETE | /downstream/tradeflows/{tradeflow_reference} | Deactivate a tradeflow.?hard=true β permanently delete. |
1 Β· Create / update tradeflows POST /downstream/tradeflowsβ
Payload formatβ
A single JSON object or an array of objects.
{
"tradeflow_reference": "PO4564268", // required
// Tracking references β string OR array
"container_reference": [
{
"reference": "ABCD1234567",
"custom_properties": {
"requires_inspection": true,
"quality_check_date": "2025-05-01"
}
},
{
"reference": "EFGH7654321",
"custom_properties": {
"requires_inspection": true,
"quality_check_date": "2025-05-01"
}
}
],
"container_references_complete": true,
"bill_of_lading_reference": "ANR00001010",
"booking_reference": ["94512540", "94512888"],
// Tradeflow status
"active": true, // default = true
// Carrier name
"carrier_name": "Maersk", // optional
"carrier_scac": "MAEU", // optional
// Partner shortcuts
"customer_name": "Fruit Maker EXIM International",
"customer_reference": "PO_12345_CUST", // optional
"partners": [
{
"name": "Best Forwarder BV",
"role": "forwarder",
"reference": "PO_4564268",
"lead_contact": "[email protected]" // optional - email of lead contact at partner
}
],
"partners_complete": false,
// Team assignment
"team_name": "Sales Team EMEA", // optional
// Lead contact - individual responsible for this tradeflow
"lead_contact": "[email protected]", // optional - email or full name
// Voyage metadata
"port_of_loading": "BEANR",
"port_of_discharge": "USLAX",
"estimated_time_of_departure": "2025-05-14T12:00:00Z",
// or - when vessel has already departed
"actual_time_of_departure": "2025-05-14T12:00:00Z",
"estimated_time_of_arrival": "2025-06-06T22:00:00Z",
// or - when vessel has already arrived
"actual_time_of_arrival": "2025-06-06T22:00:00Z",
"vessel": "Maersk SOPHIE",
"incoterms": "FOB",
"references": {
"house_bill_of_lading": "hbl_123456789", // optional house bill of lading reference
"delivery_location": "Factory yard 12345", // optional, string of the delivery location
"delivery_event_date": "2021-08-24T15:00:25+00:00" // optional, ISO-date of delivery
},
// Optional self-defined events
"events": [
{
"message": "delivery at client",
"container_reference": "ABCD1234567",
"location_name": "BEANR", // also accepts string-addresses
"event_date": "2025-05-12T08:34:00Z",
"actual": true // whether the event already happened β or is scheduled
}
],
// Per-tradeflow / per-container free-time overrides (PATCH, append-only)
"free_time_overrides": [
{ "dwell_type": "equipment_free_time_in_port", "free_days": 14 },
{ "dwell_type": "equipment_free_time_out_of_port", "free_days": 7,
"container_reference": "ABCD1234567" }
],
// NEW Β· Arbitrary key-value pairs defined by you
"custom_references": {
"invoice_number": "INV-12345",
"priority": 2,
"quality_check_date": "2025-05-01",
"requires_inspection": true
}
}
custom_references β what & whyβ
| Field | Type | Description |
|---|---|---|
custom_references | object | A free-form dictionary whose keys are fully user-defined. Each value may be a string, number, boolean, or ISO-8601 date. Use it for anything that doesnβt fit the prescribed schema (e.g. internal IDs, workflow flags, etc.). |
- Nested objects or arrays inside
custom_referencesare not allowed (hard-fail). - Keys are case-sensitive UTF-8 strings (β€ 255 chars).
- Duplicate keys in the object are rejected (
409 Conflict).
Complete-list flagsβ
| Flag | Applies to | Effect when true |
|---|---|---|
container_references_complete | container_reference[] | Containers not listed are removed. |
bill_of_lading_references_complete | bill_of_lading_reference[] | Same logic. |
booking_references_complete | booking_reference[] | Same logic. |
partners_complete | partners[] | Partners not listed are removed. |
If a _complete flag is omitted, the list is merged instead of replaced.
Partner inputβ
customer_nameβ quick way to add one partner with rolecustomer.partnersβ full array that supports multiple roles and references. Both inputs may be combined.
Team assignmentβ
team_nameβ assigns an existing team to the tradeflow.- Must be an existing team (minimum 3 characters)
- First searches your organization, then partner organizations involved in the tradeflow
- Case-insensitive matching (e.g., "Sales Team EMEA" matches "sales team emea")
- If no matching team is found in any involved organization, the field is silently ignored
Lead contactβ
A lead contact is the individual user accountable for a tradeflow. They appear in the "My Tradeflows" view and receive assignment notifications. See the Lead Contact guide for the full feature overview.
lead_contacton the tradeflow root β the person responsible for the whole shipment on your side.lead_contacton a partner object β the person responsible at that partner organization.
Accepted values (in order of reliability):
| Format | Example | Notes |
|---|---|---|
[email protected] | Recommended β unambiguous exact match | |
| Full name | Sophie Dupont | Matched against first_name + last_name, word separators are flexible |
Matching rules:
- Must resolve to an existing user within your organization (for the root-level field) or the partner organization (for the partner-level field).
- If the user belongs to a different entity than the one being set, the lead contact is also propagated to that entity's tradeflow record.
- If no user matches, the field is silently ignored β the tradeflow is still created/updated without a lead contact.
Free time overridesβ
Per-tradeflow and per-container overrides for free-time monitoring (demurrage, detention, storage, electricity). Useful when a contract grants a one-off extension or grace period that should win over the global free-time rules.
| Field | Type | Required | Description |
|---|---|---|---|
dwell_type | string (enum) | yes | One of the 5 modern dwell types - see list below. |
free_days | integer β₯ 0 | yes* | Number of free days for this override. Required unless cancelled: true. Zero is valid. |
container_reference | string | no | ISO 6346 container reference. If present and valid, the override is scoped to that container. If absent, the override is tradeflow-wide. |
cancelled | boolean | no | When true, cancels the override at this scope. free_days is ignored. |
Accepted dwell_type values:
equipment_free_time_in_port- equipment free time at the port (legacy alias:destination_demurrage)equipment_free_time_out_of_port- equipment free time after gate-out (legacy alias:destination_detention)equipment_free_time_combined- combined pool (carriers like Evergreen, or Maersk on some lanes)storage_free_time- terminal storage above carrier demurrageelectricity_free_time- reefer electricity free time
Semantics:
- PATCH, append-only. Listed scopes are upserted; unlisted scopes are untouched. Re-posting the same value is a no-op (idempotent). An empty array
[]is also a no-op. - Scope precedence. A per-container override wins over a tradeflow-wide override for that container; tradeflow-wide applies to all other containers. A cancellation at one scope does not affect the override at the other scope.
- Cancellation. Send
{ "dwell_type": "...", "cancelled": true }(optionally with acontainer_reference) to clear the override at that exact scope. - Pre-creation. A per-container override may be authored before the container is added to the tradeflow; it is picked up automatically once the container appears.
- Effective downstream. Once accepted, the override is reflected in the upstream API output, in graph-tp transport plans, and in the free-time-exceeded flag generation (typically within a few minutes due to the cron's cooldown).
Invalid entries (unknown dwell_type, non-numeric or negative free_days) are silently skipped. A malformed container_reference is ignored and the entry is treated as tradeflow-wide.
Response 202 Acceptedβ
Processing is asynchronous. The response lists queued items and any warnings:
{
"status": "queued",
"tradeflows": [
{
"tradeflow_reference": "PO4564268",
"created": false,
"warnings": [
{
"path": "[0].container_reference[1]",
"message": "EFGH7654321 does not match ISO 6346 and was ignored"
},
{
"path": "[0].custom_references.quality_check_date",
"message": "Date must be ISO-8601; received \"20250501\""
}
]
}
]
}
Warnings indicate values that were ignored without blocking the request (soft-fail).
2 Β· Remove tradeflows DELETE /downstream/tradeflows/{tradeflow_reference}β
| Action | How |
|---|---|
| Deactivate (preferred) | DELETE /downstream/tradeflows/PO4564268 β same effect as posting "active": false. |
| Permanent delete | DELETE /downstream/tradeflows/PO4564268?hard=true |
Returns 204 No Content on success.
Bulk delete (UAT only)β
Using * as the tradeflow_reference deletes all tradeflows in your UAT (User Acceptance Testing) environment. This wildcard is restricted to UAT environments to prevent accidental deletion of production data.
Example:
DELETE /downstream/tradeflows/*
This deactivates all tradeflows in your UAT environment. Add ?hard=true for permanent deletion.
Note: This endpoint returns
403 Forbiddenwhen called from a production environment.
Validation rulesβ
Hard-fail (request rejected β 400 Bad Request):
-
Payload must be JSON object or array.
-
tradeflow_referencemissing or longer than 255 characters. -
Date fields not ISO-8601 (
YYYY-MM-DDTHH:MM:SSZ) orYYYYMMDD. -
port_of_loading / port_of_dischargenot a 2-letter ISO country code or 5-character UN/LOCODE. -
custom_references:- Contains nested array/object values.
- A value is not string/number/boolean/date.
- Total number of keys > 50.
Soft-fail (processed but returned as warnings):
container_referencenot matching^[A-Z]{4}[0-9]{7}$.- Empty strings or null values inside array fields.
- Unknown top-level properties (outside
custom_references).
Error codesβ
| Status | Meaning |
|---|---|
| 400 Bad Request | Validation failed (hard-fail rules). |
| 401 Unauthorized | Missing or invalid Authorization token. |
| 404 Not Found | Tradeflow not found on delete. |
| 409 Conflict | Same tradeflow_reference appears twice in one payload.Duplicate key inside custom_references. |
| 500 Internal Server Error | Unexpected error during processing. |
Questions or feedback? Create an issue in the public repository or contact Dockflow support.