Skip to the content

API reference

Rates, shipments, labels, tracking and webhooks for Nigerian shipping, through one API.

Authentication. Send your secret key as Authorization: Bearer <key>. Keys are for servers: never put one in a browser or an app. The key decides the environment: evp_test_… keys use the sandbox (test carriers, no money, nothing real is shipped); evp_live_… keys use production (real carriers, paid from your EviPostal wallet) once production access is enabled for your business.

Errors share one shape: { "error": { "code", "message", "request_id", "fields"?, "docs_url" } }. Quote request_id (also in the X-Request-Id header) when you contact support.

Idempotency. Send an Idempotency-Key header (1–255 of A-Z a-z 0-9 _ . : -) on mutations; it is required on POST /shipments. The same key and body replays the first result with Idempotent-Replayed: true for 24 hours; the same key with a different body is 422 idempotency_key_reused.

Rate limits are per application and environment; every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset, and a 429 adds Retry-After.

Versioning. v1 only grows: new optional fields, new response fields, new enum values in open enums (shipment status, tracking event type) and new event types. Ignore fields and event types you do not know.

Webhooks are signed with EviPostal-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>. During the 24 hours after a secret rotation a second v1= entry is signed with the previous secret: accept the request if any v1 matches. Reject it when |now − t| > 300 seconds (replay protection). Failed deliveries are retried after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h. Production endpoints also receive the events of shipments your store books in the EviPostal dashboard or POS (created_through: "dashboard").

Sandbox scenarios. Start to.line1 with: MOCK-NO-SERVICE — No rates: rates is empty and messages has no_service. MOCK-INVALID-ADDRESS — No rates: messages has invalid_address. MOCK-TIMEOUT — The test carrier does not answer: 503 carrier_unavailable (takes the carrier timeout). MOCK-BOOK-FAIL — Booking refused: 422 booking_failed. Nothing charged. MOCK-BOOK-TIMEOUT — 202 with status booking; EviPostal confirms it later and sends shipment.booked. MOCK-BOOK-LOST — 202 with status booking; EviPostal finds no booking and sends shipment.booking_failed. MOCK-NO-FUNDS — 402 insufficient_funds, as a production key with an empty wallet would get. MOCK-LABEL-LATER — The label stays pending at first: GET label answers 409 label_not_ready. MOCK-DELAYED — The timeline reports a delay: shipment.delayed. MOCK-PICKUP-FAIL — The carrier cannot collect it: shipment.exception with status delivery_issue.

Base URLhttps://api.evipostal.com/v1· version v1

Account

Your API key.

get/v1/me

Check your API key

Returns the environment, scopes and application of the key you sent. Use it to test that your key works. Any valid key may call it.

Scope
None needed
Idempotency-Key header
Not used

Answers

Fields in the answer
Check your API key answer
FieldTypeDetails
objectRequired"api_key"—
environmentRequiredenum

One of: sandbox, production

keyRequiredstring—
scopesRequiredarray of enum

Each one of: rates:read, shipments:read, shipments:write, labels:read, tracking:read, webhooks:read, webhooks:write

applicationRequiredobject—
application.nameRequiredstring—
businessRequiredobject—
business.nameRequiredstring—
api_versionRequired"v1"—
curl "https://api.evipostal.com/v1/me" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "object": "api_key",
  "environment": "sandbox",
  "key": "evp_test_7Qm2…x9Ka",
  "scopes": [
    "rates:read",
    "shipments:read",
    "shipments:write",
    "labels:read",
    "tracking:read",
    "webhooks:read",
    "webhooks:write"
  ],
  "application": {
    "name": "Order sync"
  },
  "business": {
    "name": "Ada Stores"
  },
  "api_version": "v1"
}

Rates

Quotes from the carriers available to your key.

post/v1/rates

Get rates

Quotes a parcel with every carrier available to your key: the sandbox uses test carriers only. Each rate has an id you book with POST /shipments before expires_at. amount is what booking the rate costs your business. Nothing is charged here. When no rate comes back, messages says why. Rate requests have their own, lower rate limit.

Scope
rates:read
Idempotency-Key header
Optional, recommended

Parameters

Get rates parameters
FieldTypeDetails
Idempotency-KeyOptionalheader · string

Makes a retry safe: the same key and body replays the first result for 24 hours.

Pattern ^[A-Za-z0-9_.:-]{1,255}$

Request body

Get rates request body
FieldTypeDetails
fromRequiredobject—
from.nameRequiredstring

1–120 characters

from.phoneRequiredstring

Pattern ^\+?[0-9][0-9 ()-]{6,19}$

from.emailOptionalstring

Up to 254 characters · An email address

from.companyOptionalstring

Up to 120 characters

from.line1Requiredstring

1–200 characters

from.line2Optionalstring

Up to 200 characters

from.cityRequiredstring

1–80 characters

from.stateRequiredstring

1–80 characters

from.postal_codeOptionalstring

Up to 16 characters

from.countryOptionalstring

Pattern ^[A-Z]{2}$ · Default "NG"

from.landmarkOptionalstring

Up to 200 characters

toRequiredobject—
to.nameRequiredstring

1–120 characters

to.phoneRequiredstring

Pattern ^\+?[0-9][0-9 ()-]{6,19}$

to.emailOptionalstring

Up to 254 characters · An email address

to.companyOptionalstring

Up to 120 characters

to.line1Requiredstring

1–200 characters

to.line2Optionalstring

Up to 200 characters

to.cityRequiredstring

1–80 characters

to.stateRequiredstring

1–80 characters

to.postal_codeOptionalstring

Up to 16 characters

to.countryOptionalstring

Pattern ^[A-Z]{2}$ · Default "NG"

to.landmarkOptionalstring

Up to 200 characters

parcelsRequiredarray of object

1–5 items

parcels[].package_typeOptionalenum

One of: box, envelope, soft_pack · Default "box"

parcels[].weight_gramsRequiredinteger

1–1,000,000

parcels[].length_cmRequiredinteger

1–500

parcels[].width_cmRequiredinteger

1–500

parcels[].height_cmRequiredinteger

1–500

parcels[].descriptionRequiredstring

1–200 characters

parcels[].declared_valueRequiredinteger

0–100,000,000,000

currencyOptional"NGN"

Default "NGN"

referenceOptionalstring

Up to 64 characters

metadataOptionalobject of string—

Answers

Fields in the answer
Get rates answer
FieldTypeDetails
objectRequired"rate_list"—
environmentRequiredenum

One of: sandbox, production

referenceRequiredstring or null—
metadataRequiredobject of string—
ratesRequiredarray of object—
rates[].idRequiredstring—
rates[].objectRequired"rate"—
rates[].carrierRequiredobject—
rates[].carrier.codeRequiredstring—
rates[].carrier.nameRequiredstring—
rates[].serviceRequiredobject—
rates[].service.codeRequiredstring—
rates[].service.nameRequiredstring—
rates[].service.descriptionRequiredstring or null—
rates[].amountRequiredinteger

0–9,007,199,254,740,991

rates[].currencyRequiredstring—
rates[].chargesRequiredarray of object—
rates[].charges[].typeRequiredenum

One of: base, insurance, tax, fuel, discount, other

rates[].charges[].labelRequiredstring—
rates[].charges[].amountRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

rates[].includes_insuranceRequiredboolean—
rates[].estimated_deliveryRequiredobject—
rates[].estimated_delivery.atRequiredstring (date-time) or null—
rates[].estimated_delivery.transit_daysRequiredinteger or null

0–9,007,199,254,740,991

rates[].estimated_delivery.textRequiredstring—
rates[].chargeable_weight_gramsRequiredinteger or null

0–9,007,199,254,740,991

rates[].noticesRequiredarray of object—
rates[].notices[].levelRequiredenum

One of: info, warning

rates[].notices[].messageRequiredstring—
rates[].testRequiredboolean—
rates[].created_atRequiredstring (date-time)—
rates[].expires_atRequiredstring (date-time)—
messagesRequiredarray of object—
messages[].codeRequiredenum

One of: no_service, invalid_address, carrier_unavailable, rates_incomplete

messages[].messageRequiredstring—
created_atRequiredstring (date-time)—
curl -X POST "https://api.evipostal.com/v1/rates" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "from": {
    "name": "Ada Stores",
    "phone": "+2348012345678",
    "email": "orders@example.com",
    "line1": "12 Allen Avenue",
    "city": "Ikeja",
    "state": "Lagos",
    "country": "NG"
  },
  "to": {
    "name": "Tunde Bello",
    "phone": "+2348098765432",
    "email": "tunde@example.com",
    "line1": "5 Aminu Kano Crescent",
    "city": "Wuse",
    "state": "FCT",
    "country": "NG",
    "landmark": "Opposite the pharmacy"
  },
  "parcels": [
    {
      "package_type": "box",
      "weight_grams": 1500,
      "length_cm": 30,
      "width_cm": 20,
      "height_cm": 15,
      "description": "Shoes",
      "declared_value": 2500000
    }
  ],
  "reference": "ORDER-1042",
  "metadata": {
    "order_id": "1042"
  }
}'
200 answer
{
  "object": "rate_list",
  "environment": "sandbox",
  "reference": "ORDER-1042",
  "metadata": {
    "order_id": "1042"
  },
  "rates": [
    {
      "id": "rate_4pT9xQ2mLk8vNc3Rb7Wd1Hs5",
      "object": "rate",
      "carrier": {
        "code": "MOCK_STANDARD",
        "name": "Mock Standard (test)"
      },
      "service": {
        "code": "STANDARD",
        "name": "Standard",
        "description": "Regular door-to-door delivery"
      },
      "amount": 410000,
      "currency": "NGN",
      "charges": [
        {
          "type": "base",
          "label": "Shipping",
          "amount": 410000
        }
      ],
      "includes_insurance": false,
      "estimated_delivery": {
        "at": "2026-10-01T17:00:00.000Z",
        "transit_days": 3,
        "text": "3 business days"
      },
      "chargeable_weight_grams": 1800,
      "notices": [
        {
          "level": "info",
          "message": "Test rate — not a real carrier price"
        }
      ],
      "test": true,
      "created_at": "2026-09-28T09:15:00.000Z",
      "expires_at": "2026-09-28T09:45:00.000Z"
    }
  ],
  "messages": [],
  "created_at": "2026-09-28T09:15:00.000Z"
}

Shipments

Book, list, cancel and get labels.

get/v1/shipments

List shipments

The shipments this application booked in this environment, newest first. Pass next_cursor as cursor for the next page. With a production key, created_through=any also lists the shipments your store booked in the EviPostal dashboard or POS (created_through: "dashboard").

Scope
shipments:read
Idempotency-Key header
Not used

Parameters

List shipments parameters
FieldTypeDetails
limitOptionalquery · integer

1–100 · Default 20

cursorOptionalquery · string

1–200 characters

statusOptionalquery · enum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

referenceOptionalquery · string

Up to 64 characters

tracking_numberOptionalquery · string

Up to 64 characters

created_afterOptionalquery · string (date-time)—
created_beforeOptionalquery · string (date-time)—
created_throughOptionalquery · enum

One of: api, any

Answers

Fields in the answer
List shipments answer
FieldTypeDetails
objectRequired"list"—
has_moreRequiredboolean—
next_cursorRequiredstring or null—
dataRequiredarray of object—
data[].idRequiredstring—
data[].objectRequired"shipment"—
data[].environmentRequiredenum

One of: sandbox, production

data[].statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

data[].status_detailRequiredstring—
data[].status_updated_atRequiredstring (date-time)—
data[].tracking_numberRequiredstring or null—
data[].referenceRequiredstring or null—
data[].metadataRequiredobject of string—
data[].carrierRequiredobject—
data[].carrier.codeRequiredstring—
data[].carrier.nameRequiredstring—
data[].serviceRequiredobject—
data[].service.codeRequiredstring—
data[].service.nameRequiredstring—
data[].amountRequiredinteger

0–9,007,199,254,740,991

data[].currencyRequiredstring—
data[].fromRequiredobject—
data[].from.cityRequiredstring—
data[].from.stateRequiredstring—
data[].from.countryRequiredstring—
data[].toRequiredobject—
data[].to.cityRequiredstring—
data[].to.stateRequiredstring—
data[].to.countryRequiredstring—
data[].parcelsRequiredarray of object—
data[].parcels[].package_typeRequiredenum

One of: box, envelope, soft_pack

data[].parcels[].weight_gramsRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].parcels[].length_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].parcels[].width_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].parcels[].height_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].labelRequiredobject—
data[].label.statusRequiredenum

One of: ready, pending, failed, unavailable

data[].label.urlRequiredstring or null—
data[].label.formatRequired"pdf"—
data[].estimated_delivery_atRequiredstring (date-time) or null—
data[].booked_atRequiredstring (date-time) or null—
data[].cancelled_atRequiredstring (date-time) or null—
data[].testRequiredboolean—
data[].created_atRequiredstring (date-time)—
data[].created_throughRequiredenum

One of: api, dashboard · Default "api"

curl "https://api.evipostal.com/v1/shipments?limit=20&status=in_transit" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "object": "list",
  "data": [
    {
      "id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
      "object": "shipment",
      "environment": "sandbox",
      "status": "booked",
      "status_detail": "Booked with Mock Standard (test)",
      "status_updated_at": "2026-09-28T09:15:02.000Z",
      "tracking_number": "EVM-3F9A1C2B7D",
      "reference": "ORDER-1042",
      "metadata": {
        "order_id": "1042"
      },
      "carrier": {
        "code": "MOCK_STANDARD",
        "name": "Mock Standard (test)"
      },
      "service": {
        "code": "STANDARD",
        "name": "Standard"
      },
      "amount": 410000,
      "currency": "NGN",
      "from": {
        "city": "Ikeja",
        "state": "Lagos",
        "country": "NG"
      },
      "to": {
        "city": "Wuse",
        "state": "FCT",
        "country": "NG"
      },
      "parcels": [
        {
          "package_type": "box",
          "weight_grams": 1500,
          "length_cm": 30,
          "width_cm": 20,
          "height_cm": 15
        }
      ],
      "label": {
        "status": "ready",
        "url": "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label",
        "format": "pdf"
      },
      "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
      "booked_at": "2026-09-28T09:15:02.000Z",
      "cancelled_at": null,
      "test": true,
      "created_at": "2026-09-28T09:15:00.000Z",
      "created_through": "api"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

post/v1/shipments

Book a shipment

Books a rate from POST /rates. An Idempotency-Key header is required: retrying with the same key never books twice. In production the rate amount is paid from your EviPostal wallet; the sandbox moves no money. 201 means booked; 202 means EviPostal is still confirming with the carrier (status booking) and a shipment.booked or shipment.booking_failed event follows.

Scope
shipments:write
Idempotency-Key header
Required

Parameters

Book a shipment parameters
FieldTypeDetails
Idempotency-KeyRequiredheader · string

Required. The same key and body replays the first result for 24 hours; it never books twice.

Pattern ^[A-Za-z0-9_.:-]{1,255}$

Request body

Book a shipment request body
FieldTypeDetails
rate_idRequiredstring

At least 1 characters

referenceOptionalstring

Up to 64 characters

metadataOptionalobject of string—

Answers

Fields in the answer
Book a shipment answer
FieldTypeDetails
idRequiredstring—
objectRequired"shipment"—
environmentRequiredenum

One of: sandbox, production

statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

status_detailRequiredstring—
status_updated_atRequiredstring (date-time)—
tracking_numberRequiredstring or null—
referenceRequiredstring or null—
metadataRequiredobject of string—
carrierRequiredobject—
carrier.codeRequiredstring—
carrier.nameRequiredstring—
serviceRequiredobject—
service.codeRequiredstring—
service.nameRequiredstring—
amountRequiredinteger

0–9,007,199,254,740,991

currencyRequiredstring—
fromRequiredobject—
from.cityRequiredstring—
from.stateRequiredstring—
from.countryRequiredstring—
toRequiredobject—
to.cityRequiredstring—
to.stateRequiredstring—
to.countryRequiredstring—
parcelsRequiredarray of object—
parcels[].package_typeRequiredenum

One of: box, envelope, soft_pack

parcels[].weight_gramsRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].length_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].width_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].height_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

labelRequiredobject—
label.statusRequiredenum

One of: ready, pending, failed, unavailable

label.urlRequiredstring or null—
label.formatRequired"pdf"—
estimated_delivery_atRequiredstring (date-time) or null—
booked_atRequiredstring (date-time) or null—
cancelled_atRequiredstring (date-time) or null—
testRequiredboolean—
created_atRequiredstring (date-time)—
created_throughRequiredenum

One of: api, dashboard · Default "api"

curl -X POST "https://api.evipostal.com/v1/shipments" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "rate_id": "rate_4pT9xQ2mLk8vNc3Rb7Wd1Hs5",
  "reference": "ORDER-1042",
  "metadata": {
    "order_id": "1042"
  }
}'
201 answer
{
  "id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
  "object": "shipment",
  "environment": "sandbox",
  "status": "booked",
  "status_detail": "Booked with Mock Standard (test)",
  "status_updated_at": "2026-09-28T09:15:02.000Z",
  "tracking_number": "EVM-3F9A1C2B7D",
  "reference": "ORDER-1042",
  "metadata": {
    "order_id": "1042"
  },
  "carrier": {
    "code": "MOCK_STANDARD",
    "name": "Mock Standard (test)"
  },
  "service": {
    "code": "STANDARD",
    "name": "Standard"
  },
  "amount": 410000,
  "currency": "NGN",
  "from": {
    "city": "Ikeja",
    "state": "Lagos",
    "country": "NG"
  },
  "to": {
    "city": "Wuse",
    "state": "FCT",
    "country": "NG"
  },
  "parcels": [
    {
      "package_type": "box",
      "weight_grams": 1500,
      "length_cm": 30,
      "width_cm": 20,
      "height_cm": 15
    }
  ],
  "label": {
    "status": "ready",
    "url": "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label",
    "format": "pdf"
  },
  "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
  "booked_at": "2026-09-28T09:15:02.000Z",
  "cancelled_at": null,
  "test": true,
  "created_at": "2026-09-28T09:15:00.000Z",
  "created_through": "api"
}

get/v1/shipments/{id}

Get a shipment

One shipment of this application and environment. A production key can also read a shipment its store booked in the EviPostal dashboard or POS, for example one named in a webhook event.

Scope
shipments:read
Idempotency-Key header
Not used

Parameters

Get a shipment parameters
FieldTypeDetails
idRequiredpath · string

The shipment id (`shp_…`).

Answers

Fields in the answer
Get a shipment answer
FieldTypeDetails
idRequiredstring—
objectRequired"shipment"—
environmentRequiredenum

One of: sandbox, production

statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

status_detailRequiredstring—
status_updated_atRequiredstring (date-time)—
tracking_numberRequiredstring or null—
referenceRequiredstring or null—
metadataRequiredobject of string—
carrierRequiredobject—
carrier.codeRequiredstring—
carrier.nameRequiredstring—
serviceRequiredobject—
service.codeRequiredstring—
service.nameRequiredstring—
amountRequiredinteger

0–9,007,199,254,740,991

currencyRequiredstring—
fromRequiredobject—
from.cityRequiredstring—
from.stateRequiredstring—
from.countryRequiredstring—
toRequiredobject—
to.cityRequiredstring—
to.stateRequiredstring—
to.countryRequiredstring—
parcelsRequiredarray of object—
parcels[].package_typeRequiredenum

One of: box, envelope, soft_pack

parcels[].weight_gramsRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].length_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].width_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].height_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

labelRequiredobject—
label.statusRequiredenum

One of: ready, pending, failed, unavailable

label.urlRequiredstring or null—
label.formatRequired"pdf"—
estimated_delivery_atRequiredstring (date-time) or null—
booked_atRequiredstring (date-time) or null—
cancelled_atRequiredstring (date-time) or null—
testRequiredboolean—
created_atRequiredstring (date-time)—
created_throughRequiredenum

One of: api, dashboard · Default "api"

curl "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
  "object": "shipment",
  "environment": "sandbox",
  "status": "booked",
  "status_detail": "Booked with Mock Standard (test)",
  "status_updated_at": "2026-09-28T09:15:02.000Z",
  "tracking_number": "EVM-3F9A1C2B7D",
  "reference": "ORDER-1042",
  "metadata": {
    "order_id": "1042"
  },
  "carrier": {
    "code": "MOCK_STANDARD",
    "name": "Mock Standard (test)"
  },
  "service": {
    "code": "STANDARD",
    "name": "Standard"
  },
  "amount": 410000,
  "currency": "NGN",
  "from": {
    "city": "Ikeja",
    "state": "Lagos",
    "country": "NG"
  },
  "to": {
    "city": "Wuse",
    "state": "FCT",
    "country": "NG"
  },
  "parcels": [
    {
      "package_type": "box",
      "weight_grams": 1500,
      "length_cm": 30,
      "width_cm": 20,
      "height_cm": 15
    }
  ],
  "label": {
    "status": "ready",
    "url": "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label",
    "format": "pdf"
  },
  "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
  "booked_at": "2026-09-28T09:15:02.000Z",
  "cancelled_at": null,
  "test": true,
  "created_at": "2026-09-28T09:15:00.000Z",
  "created_through": "api"
}

post/v1/shipments/{id}/cancel

Cancel a shipment

Cancels a booked shipment before the carrier picks it up. Production charges go back to your wallet. No request body. A shipment booked in the EviPostal dashboard or POS is cancelled there, not through the API (409 conflict).

Scope
shipments:write
Idempotency-Key header
Optional, recommended

Parameters

Cancel a shipment parameters
FieldTypeDetails
idRequiredpath · string

The shipment id (`shp_…`).

Idempotency-KeyOptionalheader · string

Makes a retry safe: the same key and body replays the first result for 24 hours.

Pattern ^[A-Za-z0-9_.:-]{1,255}$

Answers

Fields in the answer
Cancel a shipment answer
FieldTypeDetails
idRequiredstring—
objectRequired"shipment"—
environmentRequiredenum

One of: sandbox, production

statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

status_detailRequiredstring—
status_updated_atRequiredstring (date-time)—
tracking_numberRequiredstring or null—
referenceRequiredstring or null—
metadataRequiredobject of string—
carrierRequiredobject—
carrier.codeRequiredstring—
carrier.nameRequiredstring—
serviceRequiredobject—
service.codeRequiredstring—
service.nameRequiredstring—
amountRequiredinteger

0–9,007,199,254,740,991

currencyRequiredstring—
fromRequiredobject—
from.cityRequiredstring—
from.stateRequiredstring—
from.countryRequiredstring—
toRequiredobject—
to.cityRequiredstring—
to.stateRequiredstring—
to.countryRequiredstring—
parcelsRequiredarray of object—
parcels[].package_typeRequiredenum

One of: box, envelope, soft_pack

parcels[].weight_gramsRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].length_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].width_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

parcels[].height_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

labelRequiredobject—
label.statusRequiredenum

One of: ready, pending, failed, unavailable

label.urlRequiredstring or null—
label.formatRequired"pdf"—
estimated_delivery_atRequiredstring (date-time) or null—
booked_atRequiredstring (date-time) or null—
cancelled_atRequiredstring (date-time) or null—
testRequiredboolean—
created_atRequiredstring (date-time)—
created_throughRequiredenum

One of: api, dashboard · Default "api"

curl -X POST "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/cancel" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
200 answer
{
  "id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
  "object": "shipment",
  "environment": "sandbox",
  "status": "cancelled",
  "status_detail": "This shipment was cancelled",
  "status_updated_at": "2026-09-28T10:02:00.000Z",
  "tracking_number": "EVM-3F9A1C2B7D",
  "reference": "ORDER-1042",
  "metadata": {
    "order_id": "1042"
  },
  "carrier": {
    "code": "MOCK_STANDARD",
    "name": "Mock Standard (test)"
  },
  "service": {
    "code": "STANDARD",
    "name": "Standard"
  },
  "amount": 410000,
  "currency": "NGN",
  "from": {
    "city": "Ikeja",
    "state": "Lagos",
    "country": "NG"
  },
  "to": {
    "city": "Wuse",
    "state": "FCT",
    "country": "NG"
  },
  "parcels": [
    {
      "package_type": "box",
      "weight_grams": 1500,
      "length_cm": 30,
      "width_cm": 20,
      "height_cm": 15
    }
  ],
  "label": {
    "status": "ready",
    "url": "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label",
    "format": "pdf"
  },
  "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
  "booked_at": "2026-09-28T09:15:02.000Z",
  "cancelled_at": "2026-09-28T10:02:00.000Z",
  "test": true,
  "created_at": "2026-09-28T09:15:00.000Z",
  "created_through": "api"
}

get/v1/shipments/{id}/label

Download the label

The shipping label as a PDF. While the carrier is still preparing it the answer is 409 label_not_ready with Retry-After.

Scope
labels:read
Idempotency-Key header
Not used

Parameters

Download the label parameters
FieldTypeDetails
idRequiredpath · string

The shipment id (`shp_…`).

Answers

curl "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY" \
  -o label.pdf

Tracking

Where a shipment is.

get/v1/shipments/{id}/tracking

Get tracking

Status and tracking history, newest first, in the same customer-safe words as the EviPostal tracking page.

Scope
tracking:read
Idempotency-Key header
Not used

Parameters

Get tracking parameters
FieldTypeDetails
idRequiredpath · string

The shipment id (`shp_…`).

Answers

Fields in the answer
Get tracking answer
FieldTypeDetails
objectRequired"tracking"—
environmentRequiredenum

One of: sandbox, production

shipment_idRequiredstring—
tracking_numberRequiredstring or null—
statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

status_detailRequiredstring—
next_stepRequiredstring or null—
status_updated_atRequiredstring (date-time)—
estimated_delivery_atRequiredstring (date-time) or null—
carrierRequiredobject—
carrier.codeRequiredstring—
carrier.nameRequiredstring—
testRequiredboolean—
eventsRequiredarray of object—
events[].typeRequiredenum

One of: booked, label_ready, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled, info

events[].descriptionRequiredstring—
events[].locationRequiredstring or null—
events[].occurred_atRequiredstring (date-time)—
curl "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/tracking" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "object": "tracking",
  "environment": "sandbox",
  "shipment_id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
  "tracking_number": "EVM-3F9A1C2B7D",
  "status": "picked_up",
  "status_detail": "The carrier has the package",
  "next_step": "It will move to the next stop soon",
  "status_updated_at": "2026-09-28T13:40:00.000Z",
  "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
  "carrier": {
    "code": "MOCK_STANDARD",
    "name": "Mock Standard (test)"
  },
  "test": true,
  "events": [
    {
      "type": "picked_up",
      "description": "Picked up by the carrier in Ikeja",
      "location": "Ikeja",
      "occurred_at": "2026-09-28T13:40:00.000Z"
    },
    {
      "type": "label_ready",
      "description": "Shipping label created",
      "location": null,
      "occurred_at": "2026-09-28T09:15:02.000Z"
    },
    {
      "type": "booked",
      "description": "Booked with Mock Standard (test) (Standard)",
      "location": null,
      "occurred_at": "2026-09-28T09:15:02.000Z"
    }
  ]
}

Webhooks

Events and the endpoints that receive them.

get/v1/events

List events

Every event of this application and environment, newest first — the same objects webhooks deliver. Use it to catch up on missed webhooks.

Scope
webhooks:read
Idempotency-Key header
Not used

Parameters

List events parameters
FieldTypeDetails
limitOptionalquery · integer

1–100 · Default 20

cursorOptionalquery · string

1–200 characters

typeOptionalquery · enum

One of: shipment.booked, shipment.booking_failed, shipment.updated, shipment.delayed, shipment.exception, shipment.delivered, shipment.cancelled, webhook.test

shipment_idOptionalquery · string

Up to 64 characters

Answers

Fields in the answer
List events answer
FieldTypeDetails
objectRequired"list"—
has_moreRequiredboolean—
next_cursorRequiredstring or null—
dataRequiredarray of object—
data[].idRequiredstring—
data[].objectRequired"event"—
data[].typeRequiredenum

One of: shipment.booked, shipment.booking_failed, shipment.updated, shipment.delayed, shipment.exception, shipment.delivered, shipment.cancelled, webhook.test

data[].api_versionRequired"v1"—
data[].environmentRequiredenum

One of: sandbox, production

data[].created_atRequiredstring (date-time)—
data[].dataRequiredobject—
data[].data.shipmentOptionalobject—
data[].data.shipment.idRequiredstring—
data[].data.shipment.objectRequired"shipment"—
data[].data.shipment.environmentRequiredenum

One of: sandbox, production

data[].data.shipment.statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

data[].data.shipment.status_detailRequiredstring—
data[].data.shipment.status_updated_atRequiredstring (date-time)—
data[].data.shipment.tracking_numberRequiredstring or null—
data[].data.shipment.referenceRequiredstring or null—
data[].data.shipment.metadataRequiredobject of string—
data[].data.shipment.carrierRequiredobject—
data[].data.shipment.carrier.codeRequiredstring—
data[].data.shipment.carrier.nameRequiredstring—
data[].data.shipment.serviceRequiredobject—
data[].data.shipment.service.codeRequiredstring—
data[].data.shipment.service.nameRequiredstring—
data[].data.shipment.amountRequiredinteger

0–9,007,199,254,740,991

data[].data.shipment.currencyRequiredstring—
data[].data.shipment.fromRequiredobject—
data[].data.shipment.from.cityRequiredstring—
data[].data.shipment.from.stateRequiredstring—
data[].data.shipment.from.countryRequiredstring—
data[].data.shipment.toRequiredobject—
data[].data.shipment.to.cityRequiredstring—
data[].data.shipment.to.stateRequiredstring—
data[].data.shipment.to.countryRequiredstring—
data[].data.shipment.parcelsRequiredarray of object—
data[].data.shipment.parcels[].package_typeRequiredenum

One of: box, envelope, soft_pack

data[].data.shipment.parcels[].weight_gramsRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].data.shipment.parcels[].length_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].data.shipment.parcels[].width_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].data.shipment.parcels[].height_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data[].data.shipment.labelRequiredobject—
data[].data.shipment.label.statusRequiredenum

One of: ready, pending, failed, unavailable

data[].data.shipment.label.urlRequiredstring or null—
data[].data.shipment.label.formatRequired"pdf"—
data[].data.shipment.estimated_delivery_atRequiredstring (date-time) or null—
data[].data.shipment.booked_atRequiredstring (date-time) or null—
data[].data.shipment.cancelled_atRequiredstring (date-time) or null—
data[].data.shipment.testRequiredboolean—
data[].data.shipment.created_atRequiredstring (date-time)—
data[].data.shipment.created_throughRequiredenum

One of: api, dashboard · Default "api"

data[].data.tracking_eventsOptionalarray of object—
data[].data.tracking_events[].typeRequiredenum

One of: booked, label_ready, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled, info

data[].data.tracking_events[].descriptionRequiredstring—
data[].data.tracking_events[].locationRequiredstring or null—
data[].data.tracking_events[].occurred_atRequiredstring (date-time)—
data[].data.messageOptionalstring—
curl "https://api.evipostal.com/v1/events?limit=20&type=shipment.updated" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "object": "list",
  "data": [
    {
      "id": "evt_2Wq7Er4Ty9Ui3Op6As1Df8Gh5",
      "object": "event",
      "type": "shipment.updated",
      "api_version": "v1",
      "environment": "sandbox",
      "created_at": "2026-09-28T13:40:00.000Z",
      "data": {
        "shipment": {
          "id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
          "object": "shipment",
          "environment": "sandbox",
          "status": "picked_up",
          "status_detail": "The carrier has the package",
          "status_updated_at": "2026-09-28T13:40:00.000Z",
          "tracking_number": "EVM-3F9A1C2B7D",
          "reference": "ORDER-1042",
          "metadata": {
            "order_id": "1042"
          },
          "carrier": {
            "code": "MOCK_STANDARD",
            "name": "Mock Standard (test)"
          },
          "service": {
            "code": "STANDARD",
            "name": "Standard"
          },
          "amount": 410000,
          "currency": "NGN",
          "from": {
            "city": "Ikeja",
            "state": "Lagos",
            "country": "NG"
          },
          "to": {
            "city": "Wuse",
            "state": "FCT",
            "country": "NG"
          },
          "parcels": [
            {
              "package_type": "box",
              "weight_grams": 1500,
              "length_cm": 30,
              "width_cm": 20,
              "height_cm": 15
            }
          ],
          "label": {
            "status": "ready",
            "url": "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label",
            "format": "pdf"
          },
          "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
          "booked_at": "2026-09-28T09:15:02.000Z",
          "cancelled_at": null,
          "test": true,
          "created_at": "2026-09-28T09:15:00.000Z",
          "created_through": "api"
        },
        "tracking_events": [
          {
            "type": "picked_up",
            "description": "Picked up by the carrier in Ikeja",
            "location": "Ikeja",
            "occurred_at": "2026-09-28T13:40:00.000Z"
          }
        ]
      }
    }
  ],
  "has_more": false,
  "next_cursor": null
}

get/v1/events/{id}

Get an event

One event by id (evt_…).

Scope
webhooks:read
Idempotency-Key header
Not used

Parameters

Get an event parameters
FieldTypeDetails
idRequiredpath · string

The event id (`evt_…`).

Answers

Fields in the answer
Get an event answer
FieldTypeDetails
idRequiredstring—
objectRequired"event"—
typeRequiredenum

One of: shipment.booked, shipment.booking_failed, shipment.updated, shipment.delayed, shipment.exception, shipment.delivered, shipment.cancelled, webhook.test

api_versionRequired"v1"—
environmentRequiredenum

One of: sandbox, production

created_atRequiredstring (date-time)—
dataRequiredobject—
data.shipmentOptionalobject—
data.shipment.idRequiredstring—
data.shipment.objectRequired"shipment"—
data.shipment.environmentRequiredenum

One of: sandbox, production

data.shipment.statusRequiredenum

One of: booking, booked, failed, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled

data.shipment.status_detailRequiredstring—
data.shipment.status_updated_atRequiredstring (date-time)—
data.shipment.tracking_numberRequiredstring or null—
data.shipment.referenceRequiredstring or null—
data.shipment.metadataRequiredobject of string—
data.shipment.carrierRequiredobject—
data.shipment.carrier.codeRequiredstring—
data.shipment.carrier.nameRequiredstring—
data.shipment.serviceRequiredobject—
data.shipment.service.codeRequiredstring—
data.shipment.service.nameRequiredstring—
data.shipment.amountRequiredinteger

0–9,007,199,254,740,991

data.shipment.currencyRequiredstring—
data.shipment.fromRequiredobject—
data.shipment.from.cityRequiredstring—
data.shipment.from.stateRequiredstring—
data.shipment.from.countryRequiredstring—
data.shipment.toRequiredobject—
data.shipment.to.cityRequiredstring—
data.shipment.to.stateRequiredstring—
data.shipment.to.countryRequiredstring—
data.shipment.parcelsRequiredarray of object—
data.shipment.parcels[].package_typeRequiredenum

One of: box, envelope, soft_pack

data.shipment.parcels[].weight_gramsRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data.shipment.parcels[].length_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data.shipment.parcels[].width_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data.shipment.parcels[].height_cmRequiredinteger

-9,007,199,254,740,991–9,007,199,254,740,991

data.shipment.labelRequiredobject—
data.shipment.label.statusRequiredenum

One of: ready, pending, failed, unavailable

data.shipment.label.urlRequiredstring or null—
data.shipment.label.formatRequired"pdf"—
data.shipment.estimated_delivery_atRequiredstring (date-time) or null—
data.shipment.booked_atRequiredstring (date-time) or null—
data.shipment.cancelled_atRequiredstring (date-time) or null—
data.shipment.testRequiredboolean—
data.shipment.created_atRequiredstring (date-time)—
data.shipment.created_throughRequiredenum

One of: api, dashboard · Default "api"

data.tracking_eventsOptionalarray of object—
data.tracking_events[].typeRequiredenum

One of: booked, label_ready, picked_up, in_transit, out_for_delivery, delivered, delayed, delivery_issue, cancelled, info

data.tracking_events[].descriptionRequiredstring—
data.tracking_events[].locationRequiredstring or null—
data.tracking_events[].occurred_atRequiredstring (date-time)—
data.messageOptionalstring—
curl "https://api.evipostal.com/v1/events/evt_2Wq7Er4Ty9Ui3Op6As1Df8Gh5" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "id": "evt_2Wq7Er4Ty9Ui3Op6As1Df8Gh5",
  "object": "event",
  "type": "shipment.updated",
  "api_version": "v1",
  "environment": "sandbox",
  "created_at": "2026-09-28T13:40:00.000Z",
  "data": {
    "shipment": {
      "id": "shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As",
      "object": "shipment",
      "environment": "sandbox",
      "status": "picked_up",
      "status_detail": "The carrier has the package",
      "status_updated_at": "2026-09-28T13:40:00.000Z",
      "tracking_number": "EVM-3F9A1C2B7D",
      "reference": "ORDER-1042",
      "metadata": {
        "order_id": "1042"
      },
      "carrier": {
        "code": "MOCK_STANDARD",
        "name": "Mock Standard (test)"
      },
      "service": {
        "code": "STANDARD",
        "name": "Standard"
      },
      "amount": 410000,
      "currency": "NGN",
      "from": {
        "city": "Ikeja",
        "state": "Lagos",
        "country": "NG"
      },
      "to": {
        "city": "Wuse",
        "state": "FCT",
        "country": "NG"
      },
      "parcels": [
        {
          "package_type": "box",
          "weight_grams": 1500,
          "length_cm": 30,
          "width_cm": 20,
          "height_cm": 15
        }
      ],
      "label": {
        "status": "ready",
        "url": "https://api.evipostal.com/v1/shipments/shp_8Jk2Lm9Qw3Er5Ty7Ui1Op4As/label",
        "format": "pdf"
      },
      "estimated_delivery_at": "2026-10-01T17:00:00.000Z",
      "booked_at": "2026-09-28T09:15:02.000Z",
      "cancelled_at": null,
      "test": true,
      "created_at": "2026-09-28T09:15:00.000Z",
      "created_through": "api"
    },
    "tracking_events": [
      {
        "type": "picked_up",
        "description": "Picked up by the carrier in Ikeja",
        "location": "Ikeja",
        "occurred_at": "2026-09-28T13:40:00.000Z"
      }
    ]
  }
}

get/v1/webhook-endpoints

List webhook endpoints

The webhook endpoints of this application and environment.

Scope
webhooks:read
Idempotency-Key header
Not used

Answers

Fields in the answer
List webhook endpoints answer
FieldTypeDetails
objectRequired"list"—
has_moreRequiredboolean—
next_cursorRequiredstring or null—
dataRequiredarray of object—
data[].idRequiredstring—
data[].objectRequired"webhook_endpoint"—
data[].environmentRequiredenum

One of: sandbox, production

data[].urlRequiredstring—
data[].descriptionRequiredstring or null—
data[].event_typesRequiredarray of enum

Each one of: shipment.booked, shipment.booking_failed, shipment.updated, shipment.delayed, shipment.exception, shipment.delivered, shipment.cancelled, webhook.test

data[].enabledRequiredboolean—
data[].created_atRequiredstring (date-time)—
curl "https://api.evipostal.com/v1/webhook-endpoints" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"
200 answer
{
  "object": "list",
  "data": [
    {
      "id": "we_6Zx3Cv8Bn1Mq4Wr7Te2Yu9Io0",
      "object": "webhook_endpoint",
      "environment": "sandbox",
      "url": "https://example.com/webhooks/evipostal",
      "description": "Order system",
      "event_types": [],
      "enabled": true,
      "created_at": "2026-09-28T09:15:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

post/v1/webhook-endpoints

Add a webhook endpoint

Adds an https URL that receives signed events. The response is the only time the signing secret is shown: store it. Up to 5 endpoints per application and environment. Leave event_types empty to receive every event type.

Scope
webhooks:write
Idempotency-Key header
Optional, recommended

Parameters

Add a webhook endpoint parameters
FieldTypeDetails
Idempotency-KeyOptionalheader · string

Makes a retry safe: the same key and body replays the first result for 24 hours.

Pattern ^[A-Za-z0-9_.:-]{1,255}$

Request body

Add a webhook endpoint request body
FieldTypeDetails
urlRequiredstring

Up to 2048 characters · A full URL

descriptionOptionalstring

Up to 200 characters

event_typesOptionalarray of enum

Each one of: shipment.booked, shipment.booking_failed, shipment.updated, shipment.delayed, shipment.exception, shipment.delivered, shipment.cancelled, webhook.test · Up to 8 items · Default []

Answers

Fields in the answer
Add a webhook endpoint answer
FieldTypeDetails
idRequiredstring—
objectRequired"webhook_endpoint"—
environmentRequiredenum

One of: sandbox, production

urlRequiredstring—
descriptionRequiredstring or null—
event_typesRequiredarray of enum

Each one of: shipment.booked, shipment.booking_failed, shipment.updated, shipment.delayed, shipment.exception, shipment.delivered, shipment.cancelled, webhook.test

enabledRequiredboolean—
created_atRequiredstring (date-time)—
secretRequiredstring—
curl -X POST "https://api.evipostal.com/v1/webhook-endpoints" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/webhooks/evipostal",
  "description": "Order system",
  "event_types": []
}'
201 answer
{
  "id": "we_6Zx3Cv8Bn1Mq4Wr7Te2Yu9Io0",
  "object": "webhook_endpoint",
  "environment": "sandbox",
  "url": "https://example.com/webhooks/evipostal",
  "description": "Order system",
  "event_types": [],
  "enabled": true,
  "created_at": "2026-09-28T09:15:00.000Z",
  "secret": "whsec_EXAMPLEdoNotUseThisSecretValue00"
}

delete/v1/webhook-endpoints/{id}

Delete a webhook endpoint

Stops deliveries to the endpoint. Pending deliveries to it are marked failed.

Scope
webhooks:write
Idempotency-Key header
Not used

Parameters

Delete a webhook endpoint parameters
FieldTypeDetails
idRequiredpath · string

The endpoint id (`we_…`).

Answers

curl -X DELETE "https://api.evipostal.com/v1/webhook-endpoints/we_6Zx3Cv8Bn1Mq4Wr7Te2Yu9Io0" \
  -H "Authorization: Bearer $EVIPOSTAL_API_KEY"

Reference

This document.

get/v1/openapi.json

This OpenAPI document

The OpenAPI 3.1 description of the EviPostal API v1. No API key needed.

Scope
None needed
Idempotency-Key header
Not used

Answers

curl "https://api.evipostal.com/v1/openapi.json"

Webhook events

Sent to your endpoints as a POST with the event as the body. See Webhooks for signing and retries. The body is the same Event object that GET /events returns.

  • shipment.bookedThe carrier confirmed the booking (immediately, or after a booking status).
  • shipment.booking_failedA booking that was being confirmed did not happen. Nothing was charged.
  • shipment.updatedA new tracking update arrived (picked up, in transit, out for delivery, or a timeline note).
  • shipment.delayedThe carrier reported a delay.
  • shipment.exceptionThe carrier reported a problem: failed pickup, failed delivery or an address issue.
  • shipment.deliveredThe package was delivered.
  • shipment.cancelledThe shipment was cancelled.
  • webhook.testSent only when you press "Send test event" in the developer portal.