Orders API
Sync orders from your system, download shipping labels, and manage shipments. Everything you do in your panel, now automated.
Successful responses and business-rule errors use the success / message / data envelope shown below (errors also carry errors and a timestamp). Two cases come straight from the framework and look different: a missing or invalid token returns 401 with just {"message": "Unauthenticated."} (a valid token that isn't a merchant API token gets a 401 in the envelope with Authentication required.), and failed input validation returns 422 with {"message": "...", "errors": {"field": ["..."]}} — no success, no timestamp, and messages may be in Spanish. Always branch on the HTTP status code, never on the presence of success. See Error handling.
Every {tracking_number} path parameter below must match ^(4N|SH)\d{12}$. A malformed value returns a 422 validation error (The tracking number format is invalid.), not a 404. A well-formed number that doesn't belong to your account returns 404 with Order not found..
Sync an order
Send order details from your system. This is the same as filling out the "Create Order" form in your panel. Returns 201 Created.
Request Body
- Name
sender_name- Type
- string
- Description
Name of the sender or business. Max 255 characters. Required.
- Name
sender_company- Type
- string
- Description
Sender company name. Max 255 characters. Defaults to your account name.
- Name
sender_phone- Type
- string
- Description
Sender phone number. Max 50 characters.
- Name
sender_email- Type
- string
- Description
Sender email address. Must be a valid email. Max 255 characters.
- Name
recipient_name- Type
- string
- Description
Name of the recipient. Max 255 characters. Required.
- Name
recipient_company- Type
- string
- Description
Recipient company name. Max 255 characters.
- Name
recipient_phone- Type
- string
- Description
Recipient phone number. Max 50 characters.
- Name
recipient_email- Type
- string
- Description
Recipient email address. Must be a valid email. Max 255 characters.
- Name
destination_address- Type
- string
- Description
Destination street address. Max 500 characters. Required.
- Name
destination_locality- Type
- string
- Description
Destination locality (comuna). Send either the locality name (matched against our catalog) or its numeric ID from the References API. Max 100 characters. Required. An unknown locality returns
404; a locality outside your coverage returns422.
- Name
destination_reference- Type
- string
- Description
Reference or landmark for the destination. Max 500 characters.
- Name
destination_building_number- Type
- string
- Description
Building or apartment number at destination. Max 50 characters.
- Name
external_reference- Type
- string
- Description
Your own order code. Max 255 characters. Must be unique within your account — reusing one returns
422. Orders created with it can be looked up by this code in Order events.
- Name
cost_center- Type
- string
- Description
Cost center for internal accounting. Max 255 characters.
- Name
purchase_order- Type
- string
- Description
Purchase order number. Max 255 characters.
- Name
bill_of_lading- Type
- string
- Description
Bill of lading reference. Max 255 characters.
- Name
service_id- Type
- integer
- Description
ID of one of your active delivery services (see Services). If omitted, your first active service is used (excluding the on-route service reserved for driver-created cargo); if your account has none, the request fails with
422. A service that exists but belongs to another account also returns422.
- Name
weight- Type
- number
- Description
Package weight in kilograms. Must be >= 0. Default:
0. Not allowed whentypeispouch.
- Name
valuation- Type
- integer
- Description
Declared value of the package. Must be >= 0. Default:
0.
- Name
packages_count- Type
- integer
- Description
Number of packages in this order. Must be >= 1. Default:
1.
- Name
type- Type
- string
- Description
Order type:
standard(default) orpouch. A pouch carries no weight — don't sendweightwith a pouch.
- Name
custom_note_1- Type
- string
- Description
Free-text note for your own use. Max 200 characters.
custom_note_2throughcustom_note_5are also available.
Errors
404—Locality not found: {value}whendestination_localitymatches nothing.422(envelope) —Merchant {name} has no coverage for locality: {locality},The specified service is not available for this merchant., orThere are no active services available for this merchant.422(validation) — missing required fields, invalid email,external_referencealready used (The external reference has already been taken for this merchant.), aservice_idthat doesn't exist (The selected service does not exist.), orweightsent with apouch.
curl -X POST https://api.4nortes.app/api/v1/orders/create \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"sender_name": "John Store",
"sender_phone": "+56912345678",
"sender_email": "store@example.com",
"recipient_name": "Jane Doe",
"recipient_phone": "+56987654321",
"recipient_email": "jane@example.com",
"destination_address": "Calle Secundaria 456",
"destination_locality": "Providencia",
"destination_reference": "Near the plaza",
"weight": 2.5,
"external_reference": "ORDER-001",
"service_id": 1,
"packages_count": 1
}'
Response (201)
{
"success": true,
"message": "Order created successfully",
"data": {
"id": 12345,
"tracking_number": "4N000000012345",
"external_reference": "ORDER-001",
"cost_center": null,
"purchase_order": null,
"bill_of_lading": null,
"merchant_id": 42,
"service_id": 1,
"destination": {
"address_line": "Calle Secundaria 456",
"locality_id": 2,
"locality_name": "Providencia",
"reference": "Near the plaza"
},
"recipient": {
"name": "Jane Doe",
"phone": "+56987654321",
"email": "jane@example.com"
},
"sender": {
"name": "John Store",
"phone": "+56912345678",
"email": "store@example.com"
},
"delivery_state": "pending",
"packages_count": 1,
"weight": 2.5,
"valuation": 0,
"created_at": "2025-02-03T10:30:00.000000Z"
},
"timestamp": "2025-02-03T10:30:00.000000Z"
}
Validation error (422)
{
"message": "The recipient name is required. (and 1 more error)",
"errors": {
"recipient_name": ["The recipient name is required."],
"external_reference": [
"The external reference has already been taken for this merchant."
]
}
}
Locality error (404)
{
"success": false,
"message": "Locality not found: Providencai",
"errors": null,
"timestamp": "2025-02-03T10:30:00.000000Z"
}
Get order details
Fetch order details using the tracking number. Same info you see when clicking an order in your panel.
Path Parameters
- Name
tracking_number- Type
- string
- Description
The order tracking number (e.g.,
4N000000012345). Required.
Response Fields
- Name
delivery_state- Type
- string
- Description
Current delivery state. See Delivery states.
- Name
internal_state- Type
- string | null
- Description
The courier-side status name as it appears in the 4 Nortes panel (free text, in Spanish). It is managed by our operations team and can change over time — do not branch on it. Use
delivery_statefor logic.
- Name
packages_count- Type
- integer
- Description
Total packages in the order.
- Name
picked_up_packages_count- Type
- integer | null
- Description
Packages already scanned at pickup.
nulluntil per-package scanning has started for this order.
- Name
pending_pickup_packages_count- Type
- integer | null
- Description
Packages not yet scanned at pickup.
nulluntil per-package scanning has started.
- Name
delivered_packages_count- Type
- integer
- Description
Packages delivered so far.
- Name
failed_packages_count- Type
- integer
- Description
Packages whose last delivery attempt failed.
- Name
returned_packages_count- Type
- integer
- Description
Packages returned to sender.
- Name
pending_packages_count- Type
- integer
- Description
Packages neither delivered nor returned (
packages_count - delivered - returned).
- Name
delivery_progress- Type
- string
- Description
Delivered vs. total as a fraction string, e.g.
"2/3".
- Name
packages- Type
- array
- Description
One entry per package:
tracking_number,delivery_state(pending,delivered,failedorreturned),picked_up_at,delivered_at,returned_at(ISO 8601 ornull).
- Name
timeline- Type
- array
- Description
Delivery-state changes in chronological order, each with
stateandtimestamp. For the full step-by-step history use Order events.
- Name
estimated_delivery_date- Type
- string | null
- Description
Expected delivery date.
- Name
delivery_date- Type
- string | null
- Description
Actual delivery date, once delivered.
curl https://api.4nortes.app/api/v1/orders/4N000000012345 \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"message": "Operation successful",
"data": {
"id": 12345,
"tracking_number": "4N000000012345",
"external_reference": "ORDER-001",
"cost_center": null,
"purchase_order": null,
"bill_of_lading": null,
"delivery_state": "in_transit",
"internal_state": "En bodega destino",
"sender": {
"name": "John Store",
"phone": "+56912345678",
"email": "store@example.com"
},
"recipient": {
"name": "Jane Doe",
"phone": "+56987654321",
"email": "jane@example.com"
},
"destination": {
"address_line": "Calle Secundaria 456",
"locality_id": 2,
"locality_name": "Providencia",
"reference": "Near the plaza"
},
"packages_count": 2,
"picked_up_packages_count": 2,
"pending_pickup_packages_count": 0,
"delivered_packages_count": 0,
"failed_packages_count": 0,
"returned_packages_count": 0,
"pending_packages_count": 2,
"delivery_progress": "0/2",
"packages": [
{
"tracking_number": "4N000000012345-305",
"delivery_state": "pending",
"picked_up_at": "2025-02-03T14:30:00.000000Z",
"delivered_at": null,
"returned_at": null
},
{
"tracking_number": "4N000000012345-418",
"delivery_state": "pending",
"picked_up_at": "2025-02-03T14:30:00.000000Z",
"delivered_at": null,
"returned_at": null
}
],
"weight": 2.5,
"valuation": 0,
"timeline": [
{
"state": "pending",
"timestamp": "2025-02-03T10:30:00.000000Z"
},
{
"state": "picked_up",
"timestamp": "2025-02-03T14:30:00.000000Z"
},
{
"state": "in_transit",
"timestamp": "2025-02-03T18:00:00.000000Z"
}
],
"estimated_delivery_date": "2025-02-05T00:00:00.000000Z",
"delivery_date": null,
"created_at": "2025-02-03T10:30:00.000000Z"
},
"timestamp": "2025-02-04T08:00:00.000000Z"
}
Not found (404)
{
"success": false,
"message": "Order not found.",
"errors": null,
"timestamp": "2025-02-04T08:00:00.000000Z"
}
Malformed number (422)
{
"message": "The tracking number format is invalid.",
"errors": {
"tracking_number": ["The tracking number format is invalid."]
}
}
Order events
The step-by-step history of an order — every step we took, oldest first. Where Get order tells you where the order is now, this tells you how it got there: when it was created, each delivery-state change, every failed attempt and, if enabled for your account, the operator-side movements between our warehouses and routes.
This endpoint speaks JSON:API: successful responses have Content-Type: application/vnd.api+json and are not wrapped in the success / data envelope used by the other endpoints. Errors are different again: 403 and 404 do use the envelope, and 422 uses the raw validation shape. Branch on the HTTP status and only parse 2xx bodies as JSON:API — don't feed error bodies to a strict JSON:API client library.
Path Parameters
- Name
reference- Type
- string
- Description
Either our tracking number (e.g.
4N000000012345) or your own code, as sent inexternal_referencewhen the order was created. Only your account's orders are searched. If a value matches both a tracking number and anexternal_reference, the tracking number wins. Looking up by your code only works for orders created with anexternal_reference. Required.
Query Parameters
- Name
filter[scope]- Type
- string
- Description
public(default) orinternal.internaladds operator-side movements (warehouse receptions, route assignments, internal status). It must be enabled for your account by 4 Nortes — contact your account manager. Without it,internalreturns403.
Response
A JSON:API document. data is the full, unpaginated list of events, oldest first. Each item is { "id", "type": "order-events", "attributes": {...} } with these attributes:
- Name
event- Type
- string
- Description
Event name (see the table below). New names may appear over time — ignore events you don't recognise.
- Name
from- Type
- mixed
- Description
Value before the change, or
null. Type depends on the event.
- Name
to- Type
- mixed
- Description
Value after the change, or
null. Type depends on the event.
- Name
failure- Type
- object | null
- Description
Only on
delivery_attempt_failed:type(human-readable, Spanish — don't branch on it),reason(machine-readable, see below) andnotes(driver notes ornull).
- Name
source- Type
- string
- Description
Who caused the step:
system(automatic),api(a request to this API — your integration or the 4 Nortes driver app),user(4 Nortes staff in the panel),webhook(an inbound carrier webhook) oragent(an automated 4 Nortes operations assistant acting on an approved decision). Staff identities are never exposed.
- Name
occurred_at- Type
- string
- Description
When it happened, ISO 8601 (UTC).
Top-level meta carries the order's tracking_number, external_reference, current delivery_state and the scope that was applied.
Events
| Event | Scope | from / to |
|---|---|---|
order_created | public | from is null, to is the tracking number |
delivery_state_changed | public | Delivery state values, e.g. out_for_delivery → delivered |
delivery_attempt_failed | public | Both null; details are in failure. Also emitted when a pickup visit fails |
internal_state_changed | internal | Objects with slug and name (the courier-side status), or null |
warehouse_changed | internal | Warehouse names. Emitted whenever the order moves to a different warehouse, i.e. on each warehouse reception that moves it |
received_at_warehouse | internal | to is the date of the first warehouse reception (ISO 8601); emitted once |
route_assignment_changed | internal | Route codes, e.g. 4N-R-494681; null when unassigned or removed from a route |
estimated_delivery_date_changed | internal | ISO 8601 dates |
delivery_attempts_changed | internal | Integer attempt counts |
package_added | internal | to is the new package's tracking number |
package_removed | internal | from is the removed package's tracking number |
failure.reason is one of not_home, refused, wrong_address, inaccessible, business_closed, pending_stock_break, no_cargo_ready, no_cargo_to_ship, customer_unavailable, other.
Delivery evidence (recipient name, photos, GPS) is not part of the event history. Fetch it from the Tracking API.
Errors
401— no merchant token.403(envelope) —filter[scope]=internalwithout the internal-events option enabled:Internal events are not enabled for this account.This check runs before the order lookup.404(envelope) —Order not found.when no order of yours matches{reference}. There is no format check on{reference}, so a malformed value is simply a404.422(validation) — an unknownfilter[scope]value.
# -g stops curl from treating [scope] as a URL glob
curl -g "https://api.4nortes.app/api/v1/orders/288698844/events?filter[scope]=internal" \
-H "Authorization: Bearer {token}"
Response
{
"data": [
{
"id": "981201",
"type": "order-events",
"attributes": {
"event": "order_created",
"from": null,
"to": "4N202609146790",
"failure": null,
"source": "api",
"occurred_at": "2026-09-14T13:02:11.000000Z"
}
},
{
"id": "981377",
"type": "order-events",
"attributes": {
"event": "internal_state_changed",
"from": null,
"to": { "slug": "en-transito", "name": "En tránsito" },
"failure": null,
"source": "user",
"occurred_at": "2026-09-14T23:36:02.000000Z"
}
},
{
"id": "981378",
"type": "order-events",
"attributes": {
"event": "received_at_warehouse",
"from": null,
"to": "2026-09-14T23:36:00.000000Z",
"failure": null,
"source": "system",
"occurred_at": "2026-09-14T23:36:02.000000Z"
}
},
{
"id": "981379",
"type": "order-events",
"attributes": {
"event": "warehouse_changed",
"from": "00-Postalchile-RM",
"to": "Bodega Central 4 Norte Logística",
"failure": null,
"source": "system",
"occurred_at": "2026-09-14T23:36:02.000000Z"
}
},
{
"id": "982540",
"type": "order-events",
"attributes": {
"event": "route_assignment_changed",
"from": null,
"to": "4N-R-494681",
"failure": null,
"source": "user",
"occurred_at": "2026-09-15T11:48:30.000000Z"
}
},
{
"id": "982541",
"type": "order-events",
"attributes": {
"event": "delivery_state_changed",
"from": "in_transit",
"to": "out_for_delivery",
"failure": null,
"source": "system",
"occurred_at": "2026-09-15T11:48:30.000000Z"
}
},
{
"id": "983902",
"type": "order-events",
"attributes": {
"event": "delivery_state_changed",
"from": "out_for_delivery",
"to": "delivered",
"failure": null,
"source": "api",
"occurred_at": "2026-09-15T16:21:07.000000Z"
}
}
],
"meta": {
"tracking_number": "4N202609146790",
"external_reference": "288698844",
"delivery_state": "delivered",
"scope": "internal"
}
}
Failed attempt event
{
"id": "983110",
"type": "order-events",
"attributes": {
"event": "delivery_attempt_failed",
"from": null,
"to": null,
"failure": {
"type": "Entrega fallida",
"reason": "not_home",
"notes": "Timbre malo, nadie contesta"
},
"source": "api",
"occurred_at": "2026-09-15T14:05:44.000000Z"
}
}
Forbidden (403)
{
"success": false,
"message": "Internal events are not enabled for this account.",
"errors": null,
"timestamp": "2026-09-16T09:00:00.000000Z"
}
List your orders
Get a list of your orders, newest first. Like the orders table in your panel, but in your code.
Query Parameters
- Name
page- Type
- integer
- Description
Page number for pagination. Default:
1
- Name
per_page- Type
- integer
- Description
Number of results per page. Default:
15, Max:100
Each item carries the same package counters as Get order (picked_up_packages_count, pending_pickup_packages_count, delivered_packages_count, failed_packages_count, returned_packages_count, pending_packages_count, delivery_progress) but not the packages list, timeline or internal_state.
curl "https://api.4nortes.app/api/v1/orders?page=1&per_page=10" \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"message": "Orders retrieved successfully",
"data": {
"items": [
{
"id": 12345,
"tracking_number": "4N000000012345",
"external_reference": "ORDER-001",
"cost_center": null,
"purchase_order": null,
"bill_of_lading": null,
"destination": {
"address_line": "Calle Secundaria 456",
"locality_id": 2,
"locality_name": "Providencia",
"reference": "Near the plaza"
},
"recipient": {
"name": "Jane Doe",
"phone": "+56987654321",
"email": "jane@example.com"
},
"delivery_state": "pending",
"packages_count": 1,
"picked_up_packages_count": null,
"pending_pickup_packages_count": null,
"delivered_packages_count": 0,
"failed_packages_count": 0,
"returned_packages_count": 0,
"pending_packages_count": 1,
"delivery_progress": "0/1",
"weight": 2.5,
"valuation": 0,
"created_at": "2025-02-03T10:30:00.000000Z"
}
],
"meta": {
"current_page": 1,
"from": 1,
"to": 10,
"last_page": 5,
"per_page": 10,
"total": 47
}
},
"timestamp": "2025-02-04T08:00:00.000000Z"
}
Update an order
Edit an existing order. All fields are optional — send only the ones you want to change. Orders in a final state (delivered, closed_with_return, nulled) cannot be updated.
This endpoint can update recipient details, the destination address, and order metadata. It cannot change sender_*, packages_count, or service_id — use Update package count for package counts.
Path Parameters
- Name
tracking_number- Type
- string
- Description
The order tracking number. Required.
Request Body
All fields are optional. Only include the ones you want to change. recipient_name, destination_address and destination_locality cannot be set to null — send a value or omit the field. Every other field accepts null to clear it.
- Name
recipient_name- Type
- string
- Description
Name of the recipient. Max 255 characters. Not nullable.
- Name
recipient_company- Type
- string
- Description
Recipient company name. Max 255 characters.
- Name
recipient_phone- Type
- string
- Description
Recipient phone number. Max 50 characters.
- Name
recipient_email- Type
- string
- Description
Recipient email address. Must be a valid email. Max 255 characters.
- Name
destination_address- Type
- string
- Description
Destination street address. Max 500 characters. Not nullable.
- Name
destination_locality- Type
- string
- Description
Destination locality (comuna) name or numeric ID. Max 100 characters. Not nullable. Resolved like on create: unknown →
404, outside your coverage →422.
- Name
destination_reference- Type
- string
- Description
Reference or landmark. Max 500 characters.
- Name
destination_building_number- Type
- string
- Description
Building or apartment number. Max 50 characters.
- Name
external_reference- Type
- string
- Description
Your own order code. Max 255 characters. Must stay unique within your account — a value already used by another of your orders returns
422.
- Name
cost_center- Type
- string
- Description
Cost center for internal accounting. Max 255 characters.
- Name
purchase_order- Type
- string
- Description
Purchase order number. Max 255 characters.
- Name
bill_of_lading- Type
- string
- Description
Bill of lading reference. Max 255 characters.
- Name
valuation- Type
- integer
- Description
Declared value of the package. Must be >= 0.
- Name
weight- Type
- number
- Description
Package weight in kilograms. Must be >= 0.
Errors
404(envelope) —Order not found., orLocality not found: {value}.422(envelope) —Order cannot be updated. Current state: {state}for final states;Merchant {name} has no coverage for locality: {locality}.422(validation) — malformed tracking number, duplicateexternal_reference, invalid field values.
The response body is the same order detail as Get order.
curl -X PATCH https://api.4nortes.app/api/v1/orders/4N000000012345 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"recipient_phone": "+56911112222",
"destination_address": "Nueva Avenida 789",
"destination_reference": "Building B, gate 3"
}'
Response
{
"success": true,
"message": "Order updated successfully",
"data": {
"id": 12345,
"tracking_number": "4N000000012345",
"external_reference": "ORDER-001",
"cost_center": null,
"purchase_order": null,
"bill_of_lading": null,
"delivery_state": "pending",
"internal_state": null,
"sender": {
"name": "John Store",
"phone": "+56912345678",
"email": "store@example.com"
},
"recipient": {
"name": "Jane Doe",
"phone": "+56911112222",
"email": "jane@example.com"
},
"destination": {
"address_line": "Nueva Avenida 789",
"locality_id": 2,
"locality_name": "Providencia",
"reference": "Building B, gate 3"
},
"packages_count": 1,
"picked_up_packages_count": null,
"pending_pickup_packages_count": null,
"delivered_packages_count": 0,
"failed_packages_count": 0,
"returned_packages_count": 0,
"pending_packages_count": 1,
"delivery_progress": "0/1",
"packages": [
{
"tracking_number": "4N000000012345-305",
"delivery_state": "pending",
"picked_up_at": null,
"delivered_at": null,
"returned_at": null
}
],
"weight": 2.5,
"valuation": 0,
"timeline": [
{
"state": "pending",
"timestamp": "2025-02-03T10:30:00.000000Z"
}
],
"estimated_delivery_date": "2025-02-05T00:00:00.000000Z",
"delivery_date": null,
"created_at": "2025-02-03T10:30:00.000000Z"
},
"timestamp": "2025-02-03T11:15:00.000000Z"
}
Final-state error (422)
{
"success": false,
"message": "Order cannot be updated. Current state: delivered",
"errors": null,
"timestamp": "2025-02-06T09:00:00.000000Z"
}
Cancel an order
Cancel an order that hasn't reached a final state. Same as the cancel button in your panel.
Path Parameters
- Name
tracking_number- Type
- string
- Description
The order tracking number to cancel. Required.
Orders can be cancelled while in any non-final state. Once an order reaches delivered, closed_with_return or nulled, it cannot be cancelled and the request returns 422 with Order cannot be cancelled. Current state: {state}.
curl -X POST https://api.4nortes.app/api/v1/orders/4N000000012345/cancel \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"message": "Order cancelled successfully",
"data": {
"tracking_number": "4N000000012345",
"delivery_state": "nulled"
},
"timestamp": "2025-02-03T11:00:00.000000Z"
}
Final-state error (422)
{
"success": false,
"message": "Order cannot be cancelled. Current state: delivered",
"errors": null,
"timestamp": "2025-02-06T09:00:00.000000Z"
}
Get labels
Get the shipping label PDF for an order (one label per package).
Path Parameters
- Name
tracking_number- Type
- string
- Description
The order tracking number. Required.
Response Fields
- Name
url- Type
- string
- Description
URL to download the label PDF.
- Name
packages_count- Type
- integer
- Description
Number of packages in the order (one label per package).
- Name
generated_at- Type
- string
- Description
Timestamp when the label was generated.
Errors
404(envelope) —Order not found.422(validation) — malformed tracking number.500(envelope) —Failed to generate labels.Retry later.
curl "https://api.4nortes.app/api/v1/orders/4N000000012345/labels" \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"message": "Operation successful",
"data": {
"url": "https://storage.example.com/labels/4N000000012345.pdf",
"packages_count": 1,
"generated_at": "2025-02-03T10:35:00.000000Z"
},
"timestamp": "2025-02-03T10:35:00.000000Z"
}
Not found (404)
{
"success": false,
"message": "Order not found.",
"errors": null,
"timestamp": "2025-02-03T10:35:00.000000Z"
}
Batch labels
Generate one PDF with the labels of several orders at once.
Request Body
- Name
tracking_numbers- Type
- array
- Description
Array of 1 to 100 tracking numbers. Required. Numbers that don't match any of your orders are skipped and listed in
missing_tracking_numbers.
Errors
404(envelope) —No orders found for the provided tracking numbers.when none of them matches.422(validation) — empty array or more than 100 entries.500(envelope) —Failed to generate labels.Retry later.
curl -X POST https://api.4nortes.app/api/v1/orders/labels/batch \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"tracking_numbers": ["4N000000012345", "4N000000012346"]
}'
Response
{
"success": true,
"message": "Operation successful",
"data": {
"url": "https://storage.example.com/labels/batch-abc123.pdf",
"orders_count": 2,
"packages_count": 3,
"missing_tracking_numbers": [],
"generated_at": "2025-02-03T10:35:00.000000Z"
},
"timestamp": "2025-02-03T10:35:00.000000Z"
}
Update package count
Set the number of packages for an order. Packages are added or removed to reach the new total, and the order weight is split evenly across them.
Path Parameters
- Name
tracking_number- Type
- string
- Description
The order tracking number. Required.
Request Body
- Name
packages_count- Type
- integer
- Description
New total number of packages, 1 to 100. Required.
Errors
404(envelope) —Order not found.422(envelope) —Order cannot be modified. Current state: {state}for orders in a final state (delivered,closed_with_return,nulled).422(validation) — malformed tracking number, orpackages_countoutside 1–100.
curl -X POST https://api.4nortes.app/api/v1/orders/4N000000012345/packages/set \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"packages_count": 3
}'
Response
{
"success": true,
"message": "Successfully added 2 package(s)",
"data": {
"tracking_number": "4N000000012345",
"previous_count": 1,
"packages_count": 3,
"change": 2
},
"timestamp": "2025-02-03T11:00:00.000000Z"
}
Final-state error (422)
{
"success": false,
"message": "Order cannot be modified. Current state: delivered",
"errors": null,
"timestamp": "2025-02-06T09:00:00.000000Z"
}
Record a delivery
Record the outcome of a delivery attempt yourself — delivered, failed, or per package — with proof of delivery. Use it when your own team hands the parcel over and you want the order closed in 4 Nortes with the same evidence a driver would capture. The request body is multipart/form-data because it carries photos.
The outcome is applied to the order's most recent active delivery shipment (one in pending, dispatched, in_transit or partially_delivered). On a successful delivery the order moves to delivered and delivery_date is set; on a failure it moves to failed; with mixed per-package outcomes it becomes partially_delivered.
Path Parameters
- Name
tracking_number- Type
- string
- Description
The order tracking number. Required.
Request Body (multipart)
- Name
success- Type
- boolean
- Description
1= delivered,0= failed attempt. Required unlesspackagesis sent. In multipart bodies send1or0— the strings"true"/"false"are rejected with422.
- Name
person_name- Type
- string
- Description
Who received the parcel (or who you dealt with on a failed attempt). Max 255 characters. Required.
- Name
person_rut- Type
- string
- Description
Recipient's RUT. Max 255 characters.
- Name
person_role- Type
- string
- Description
Relationship of the person:
recipient,merchant_staff,operatororother. Any other value returns422.
- Name
latitude- Type
- number
- Description
Delivery location latitude, between -90 and 90.
- Name
longitude- Type
- number
- Description
Delivery location longitude, between -180 and 180.
- Name
notes- Type
- string
- Description
Free-text notes. Max 1000 characters.
- Name
photos[]- Type
- file[]
- Description
1 to 10 image files, each up to 10 MB. Required.
- Name
failed_reason- Type
- string
- Description
Why the attempt failed. Max 1000 characters. Required when
successis0. Stored on the proof notes asMotivo del fallo: …, after yournotesif you sent any.
- Name
packages[]- Type
- array
- Description
Optional per-package outcomes instead of
success. Each entry hastracking_number(a package tracking number of this order, e.g.4N000000012345-305),delivered(1or0) and, for failed packages, an optionalfailure_reason:not_home,refused,wrong_address,inaccessible,business_closed,pending_stock_break,no_cargo_ready,no_cargo_to_ship,customer_unavailableorother. Tracking numbers must be distinct.
Response
data has three blocks: order (state, dates, package counters, delivery_attempts_count, is_on_time, is_late), shipment (state, failed_attempts_count) and proof (what was recorded). delivery_state_label and state_label are human-readable Spanish labels — use the raw delivery_state / state values for logic. message is Order delivered successfully, Order partially delivered or Failed delivery attempt recorded.
Errors
404(envelope) —Order not found.422(envelope,errors: null) —Order has already been delivered.whensuccessis1and the order is alreadydelivered.422(envelope,errors: null) —No active shipment found for this order.when there is nothing left to deliver against.422(envelope,errors.packages) — a package tracking number that doesn't belong to the order, was already delivered, already returned, or is reserved for return to sender.422(validation) — missingsuccess/person_name/photos, a non-image or oversized photo, missingfailed_reasonon a failed attempt, an unknownperson_role, or a malformed tracking number.
curl -X POST https://api.4nortes.app/api/v1/orders/4N000000012345/fulfill \
-H "Authorization: Bearer {token}" \
-F "success=1" \
-F "person_name=Jane Doe" \
-F "person_rut=12.345.678-9" \
-F "person_role=recipient" \
-F "latitude=-33.4489" \
-F "longitude=-70.6693" \
-F "notes=Left with the recipient at the door" \
-F "photos[]=@/path/to/photo.jpg"
Response
{
"success": true,
"message": "Order delivered successfully",
"data": {
"order": {
"id": 12345,
"tracking_number": "4N000000012345",
"delivery_state": "delivered",
"delivery_state_label": "Entregado",
"delivery_date": "2025-02-05T16:21:07.000000Z",
"estimated_delivery_date": "2025-02-05T00:00:00.000000Z",
"packages_count": 1,
"delivered_packages_count": 1,
"delivery_attempts_count": 1,
"delivery_progress": "1/1",
"is_on_time": false,
"is_late": true
},
"shipment": {
"id": 98765,
"state": "delivered",
"state_label": "Entregado",
"failed_attempts_count": 0
},
"proof": {
"id": 55501,
"type": "destination",
"person_name": "Jane Doe",
"latitude": -33.4489,
"longitude": -70.6693,
"notes": "Left with the recipient at the door",
"created_at": "2025-02-05T16:21:07.000000Z"
}
},
"timestamp": "2025-02-05T16:21:07.000000Z"
}
Per-package outcomes (cURL)
curl -X POST https://api.4nortes.app/api/v1/orders/4N000000012345/fulfill \
-H "Authorization: Bearer {token}" \
-F "person_name=Jane Doe" \
-F "packages[0][tracking_number]=4N000000012345-305" \
-F "packages[0][delivered]=1" \
-F "packages[1][tracking_number]=4N000000012345-418" \
-F "packages[1][delivered]=0" \
-F "packages[1][failure_reason]=refused" \
-F "photos[]=@/path/to/photo.jpg"
Package error (422)
{
"success": false,
"message": "The following tracking numbers do not belong to this order: 4N000000099999-001",
"errors": {
"packages": [
"The following tracking numbers do not belong to this order: 4N000000099999-001"
]
},
"timestamp": "2025-02-05T16:21:07.000000Z"
}