Skip to main content

πŸ”½ Downstream API - send to 🌐

Base URL: https://api.dockflow.com/v3 (or https://uat.dockflow.com/v3 for the sandbox)


Endpoints​

MethodPathDescription
POST/downstream/tradeflowsCreate 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, // optional

// 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, stored as a free-text reference
"delivery_event_date": "2021-08-24T15:00:25+00:00" // optional, stored as a free-text reference
},

// Optional self-defined events
"events": [
{
"message": "delivery at client",
"container_reference": "ABCD1234567",
"location_name": "BEANR", // 5-character UN/LOCODE; any other value leaves the event without a location
"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​

FieldTypeDescription
custom_referencesobjectA free-form dictionary whose keys are fully user-defined. Each value should 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.).
  • Values are stored as text. Use flat values only; do not nest objects or arrays.
  • Keys are case-sensitive. A key you have not used before is created for your organisation.
  • Sending null or an empty string for a key removes that property from the tradeflow; the strings null and #null are ignored.

Complete-list flags​

FlagApplies toEffect when true
container_references_completecontainer_reference[]Containers not listed are removed.
bill_of_lading_references_completebill_of_lading_reference[]Same logic.
booking_references_completebooking_reference[]Same logic.
partners_completepartners[]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 role customer.
  • 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_contact on the tradeflow root β€” the person responsible for the whole shipment on your side.
  • lead_contact on a partner object β€” the person responsible at that partner organization.

Accepted values (in order of reliability):

FormatExampleNotes
Email[email protected]Recommended β€” unambiguous exact match
Full nameSophie DupontMatched 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.

FieldTypeRequiredDescription
dwell_typestring (enum)yesOne of the 5 modern dwell types - see list below.
free_daysinteger β‰₯ 0yes*Number of free days for this override. Required unless cancelled: true. Zero is valid.
container_referencestringnoISO 6346 container reference. If present and valid, the override is scoped to that container. If absent, the override is tradeflow-wide.
cancelledbooleannoWhen 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
  • equipment_free_time_out_of_port - equipment free time after gate-out
  • equipment_free_time_combined - combined pool (carriers like Evergreen, or Maersk on some lanes)
  • storage_free_time - terminal storage above carrier demurrage
  • electricity_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 a container_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 β€” the older names destination_demurrage and destination_detention are not accepted, 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 acknowledges each queued item:

{
"status": "queued",
"tradeflows": [
{
"tradeflow_reference": "PO4564268",
"warnings": []
}
]
}

warnings is reserved for soft-fail feedback and is currently always empty β€” a value that fails a soft-fail rule is ignored silently. To see what Dockflow did with a payload, open the tradeflow in the app and use Download β–Έ Download V3 API, or read it back from the upstream API. Hard-fail rules are reported synchronously as 400 Bad Request.


2 Β· Remove tradeflows DELETE /downstream/tradeflows/{tradeflow_reference}​

ActionHow
Deactivate (preferred)DELETE /downstream/tradeflows/PO4564268
β€” same effect as posting "active": false.
Permanent deleteDELETE /downstream/tradeflows/PO4564268?hard=true

Returns 204 No Content on success.

Bulk delete​

Using * as the tradeflow_reference deactivates every tradeflow of the organisation the token belongs to. Add ?hard=true for permanent deletion.

DELETE /downstream/tradeflows/*
EnvironmentBehaviour
UATAllowed as-is.
ProductionRequires ?confirm=PRODUCTION. Without it the call is refused with 400 Bad Request; every accepted production bulk delete is logged. When the organisation has no tradeflows, the call returns 404.

Validation rules​

The request is accepted with 202 Accepted as long as the body is valid JSON and is an object or an array of objects; otherwise it is refused with 400 Bad Request. Everything else is processed after the response, and an invalid value is skipped silently while the rest of the payload is applied. Check the outcome in the app or via the upstream API.

tradeflow_reference is required. An item without a usable (non-blank) reference is not imported.

Values that are skipped silently:

  • container_reference not matching ^[A-Z]{4}[0-9]{7}$ after upper-casing and removing spaces and hyphens.
  • Empty strings or null values inside array fields.
  • Dates that cannot be parsed (use ISO-8601, or YYYYMMDD for estimated_time_of_arrival).
  • port_of_loading / port_of_discharge that are not a 2-letter ISO country code or a 5-character UN/LOCODE.
  • carrier_name or carrier_scac shorter than 4 characters.
  • customer_name shorter than 2 characters; partner name of 2 characters or fewer.
  • incoterms of 2 characters or fewer.
  • Bill of lading and booking references shorter than 5 characters.
  • team_name shorter than 3 characters or not matching an existing team.
  • lead_contact that matches no existing user.
  • Unknown top-level properties (outside custom_references).
  • On the UAT host, customer_name and partners are not processed.

When active is omitted, an inactive tradeflow is reactivated only if its arrival is in the future, or, with no arrival date, if it was created within the last two months. "active": false deactivates it.


Error codes​

StatusMeaning
400 Bad RequestBody is not valid JSON, or not an object or array. Also Token format invalid.
401 UnauthorizedMissing or malformed Authorization header, or unknown token.
403 ForbiddenToken environment does not match the host (prod_ vs uat_), or the token is revoked.
404 Not FoundTradeflow not found on delete.
500 Internal Server ErrorUnexpected error during processing.

Questions or feedback? Create an issue in the public repository or contact Dockflow support.