Orders API

Sync orders from your system, download shipping labels, and manage shipments. Everything you do in your panel, now automated.


POST/orders/create

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 returns 422.

  • 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 returns 422.

  • Name
    weight
    Type
    number
    Description

    Package weight in kilograms. Must be >= 0. Default: 0. Not allowed when type is pouch.

  • 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) or pouch. A pouch carries no weight — don't send weight with a pouch.

  • Name
    custom_note_1
    Type
    string
    Description

    Free-text note for your own use. Max 200 characters. custom_note_2 through custom_note_5 are also available.

Errors

  • 404 — Locality not found: {value} when destination_locality matches nothing.
  • 422 (envelope) — Merchant {name} has no coverage for locality: {locality}, The specified service is not available for this merchant., or There are no active services available for this merchant.
  • 422 (validation) — missing required fields, invalid email, external_reference already used (The external reference has already been taken for this merchant.), a service_id that doesn't exist (The selected service does not exist.), or weight sent with a pouch.
POST
/orders/create
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/orders/{tracking_number}

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_state for 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. null until per-package scanning has started for this order.

  • Name
    pending_pickup_packages_count
    Type
    integer | null
    Description

    Packages not yet scanned at pickup. null until 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, failed or returned), picked_up_at, delivered_at, returned_at (ISO 8601 or null).

  • Name
    timeline
    Type
    array
    Description

    Delivery-state changes in chronological order, each with state and timestamp. 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.

GET
/orders/{tracking_number}
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."]
  }
}

GET/orders/{reference}/events

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 in external_reference when the order was created. Only your account's orders are searched. If a value matches both a tracking number and an external_reference, the tracking number wins. Looking up by your code only works for orders created with an external_reference. Required.

Query Parameters

  • Name
    filter[scope]
    Type
    string
    Description

    public (default) or internal. internal adds 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, internal returns 403.

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) and notes (driver notes or null).

  • 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) or agent (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

EventScopefrom / to
order_createdpublicfrom is null, to is the tracking number
delivery_state_changedpublicDelivery state values, e.g. out_for_delivery → delivered
delivery_attempt_failedpublicBoth null; details are in failure. Also emitted when a pickup visit fails
internal_state_changedinternalObjects with slug and name (the courier-side status), or null
warehouse_changedinternalWarehouse names. Emitted whenever the order moves to a different warehouse, i.e. on each warehouse reception that moves it
received_at_warehouseinternalto is the date of the first warehouse reception (ISO 8601); emitted once
route_assignment_changedinternalRoute codes, e.g. 4N-R-494681; null when unassigned or removed from a route
estimated_delivery_date_changedinternalISO 8601 dates
delivery_attempts_changedinternalInteger attempt counts
package_addedinternalto is the new package's tracking number
package_removedinternalfrom 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.

Errors

  • 401 — no merchant token.
  • 403 (envelope) — filter[scope]=internal without 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 a 404.
  • 422 (validation) — an unknown filter[scope] value.
GET
/orders/{reference}/events
# -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"
}

GET/orders

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.

GET
/orders
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"
}

PATCH/orders/{tracking_number}

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.

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., or Locality 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, duplicate external_reference, invalid field values.

The response body is the same order detail as Get order.

PATCH
/orders/{tracking_number}
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"
}

POST/orders/{tracking_number}/cancel

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.

POST
/orders/{tracking_number}/cancel
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/orders/{tracking_number}/labels

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.
GET
/orders/{tracking_number}/labels
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"
}

POST/orders/labels/batch

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.
POST
/orders/labels/batch
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"
}

POST/orders/{tracking_number}/packages/set

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, or packages_count outside 1–100.
POST
/orders/{tracking_number}/packages/set
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"
}

POST/orders/{tracking_number}/fulfill

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 unless packages is sent. In multipart bodies send 1 or 0 — the strings "true" / "false" are rejected with 422.

  • 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, operator or other. Any other value returns 422.

  • 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 success is 0. Stored on the proof notes as Motivo del fallo: …, after your notes if you sent any.

  • Name
    packages[]
    Type
    array
    Description

    Optional per-package outcomes instead of success. Each entry has tracking_number (a package tracking number of this order, e.g. 4N000000012345-305), delivered (1 or 0) and, for failed packages, an optional failure_reason: not_home, refused, wrong_address, inaccessible, business_closed, pending_stock_break, no_cargo_ready, no_cargo_to_ship, customer_unavailable or other. 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. when success is 1 and the order is already delivered.
  • 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) — missing success/person_name/photos, a non-image or oversized photo, missing failed_reason on a failed attempt, an unknown person_role, or a malformed tracking number.
POST
/orders/{tracking_number}/fulfill
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"
}

Was this page helpful?