MyCourier Order API#
The MyCourier Order API lets your own system (an online store, an ERP or warehouse software) place deliveries with MyCourier, follow them and cancel them. Orders placed through the API show up in your MyCourier portal like any other order, so your team and your API can work side by side.How it fits together#
A typical integration follows this order:1.
Check coverage for the customer's address and pick a service and delivery date (optional but recommended).
2.
Place the order with Place orders. Keep the trackingNumber from the reply.
3.
Get the label and attach it to the parcel.
4.
Follow the order with Get last status or, better, let MyCourier tell you through the status webhook.
5.
Cancel the order if it is no longer needed and has not been planned yet.
Base address#
https://flype-mycourier-project.web.app
Every path in this documentation starts with /api. All requests and replies use JSON (Content-Type: application/json).Authentication#
Every request carries a short-lived token in the Authorization header:Authorization: Bearer <token>
The token is a standard JWT that you create with two values from your MyCourier account:| Part | Value |
|---|
| Header | {"alg": "HS256", "typ": "JWT"}. Only HS256 is accepted. |
Payload sub | Your Merchant ID. |
Payload iat | The time you create the token, in seconds since 1970 (UTC). |
Payload exp | When the token ends, in the same unit. At most 15 minutes after iat. |
| Signature | HMAC-SHA256 of header and payload, using your API key as the secret. |
Your API key is only used to sign the token. It is never sent to MyCourier, so keep it on your server and never place it in a web page or mobile app. A clock difference of up to 60 seconds is tolerated.| Status | Meaning |
|---|
401 | The token is missing, expired, signed with another key, or valid for more than 15 minutes. |
403 | API access is switched off for your account, or the account is not active. |
Identifiers#
| Name | What it is |
|---|
shipperRef | Your own order reference. You choose it, and it must be unique. Placing an order with a reference that already exists is denied, so a repeated request never creates the same order twice. |
trackingNumber | The 12-character code MyCourier gives the order. It is used in every request about that order. |
orderNumber | MyCourier's numeric order number, the one shown in the portal. |
externalLocationId | The code of one of your pickup locations. |
Service types and dates#
| Service type | Delivery |
|---|
SAME_DAY | On the day of pickup. |
NEXT_DAY | On the following delivery day. |
Times such as statusUpdatedAt and pickupTime are UTC in ISO 8601, for example 2026-10-28T04:30:00.000Z. pickupDate and expectedDeliveryDate are calendar days (2026-10-28) in the time zone of the order.If a service is no longer possible for the day (the cut-off has passed), Place orders denies the order and lists the options that are still open. Send the order again with one of them.Placing many orders#
Place orders accepts up to 1,000 orders per request. Each order is judged on its own, so one refused order never blocks the rest: look at both acceptedOrders and deniedOrders in the reply.Only one Place orders request per account runs at a time. If you send a second one while the first is still running, you receive 429 with a Retry-After header. Wait that many seconds and send it again.Large requests can take a while. If a request times out on your side, it may still be completed: read the result with List shipments or send the same request again, since existing shipperRef values are denied rather than duplicated.Field limits#
| Field | Limit |
|---|
| Recipient name | 255 characters |
| Email | 255 characters |
| Other text fields | 255 characters |
| Remarks | 500 characters |
| Items per order | 1 to 100 |
| Quantity per item | 1 to 999 |
| Packages per order | 1 to 9999 |
| Item weight | up to 30 kg per unit |
| Item length, width, height | up to 300 cm per unit |
Phone numbers and postal codes must be Canadian, and coordinates must be inside Canada. Weight is in kilograms and sizes in centimetres, always for one unit of the item.Order statuses#
| Status | Meaning |
|---|
booked | The order is placed. |
to_dc_truck_transit | On its way to the MyCourier hub by truck. |
at_dc | At the MyCourier hub. |
to_dc_driver_pickup | A driver is on the way to collect it for the hub. |
at_dc_driver_pickup | The driver has collected it for the hub. |
to_delivery | Out for delivery. |
at_delivery | The driver is at the delivery address. |
delivered | Delivered. |
delivery_attempt_failed | A delivery attempt did not succeed. |
delivery_reattempt | Another attempt is planned. |
delayed | The delivery is delayed. |
undeliverable | The order could not be delivered. |
denied | The order was refused and will not be delivered. |
to_return | On its way back. |
returned | Returned. |
to_return_origin | Being sent back to the pickup location. |
in_transit_to_return_origin | In transit back to the pickup location. |
returned_origin | Back at the pickup location. |
cancelled | Cancelled. |
Status webhook#
Instead of asking for the status again and again, you can let MyCourier call your server whenever the status of one of your orders changes. This covers every order of your account, whether it came from the API, the portal or a file import.1.
Build an endpoint on your server that accepts a POST with a JSON body. It must be a public HTTPS address.
2.
Give that address to MyCourier.
3.
Answer every call with a 2xx status within 10 seconds.
Each call carries these headers:| Header | Value |
|---|
Content-Type | application/json |
User-Agent | MyCourier-Webhook/1.0 |
X-MyCourier-Event-Id | The same value as eventId in the body. |
The body looks like this (see Shipment status update for every field):{
"eventId": "evt_3f9a1c7e5b2d48a09c6e1f73b2d4a8c5",
"trackingNumber": "FQ3UFIZ6RQWU",
"orderNumber": 2902924,
"shipperRef": "SHOP-10458",
"status": "delivered",
"statusUpdatedAt": "2026-10-28T20:41:09.000Z",
"serviceType": "NEXT_DAY",
"orderDate": "2026-10-27T13:40:20.000Z",
"expectedDeliveryDate": "2026-10-28"
}
If your server does not answer. A timeout, a 5xx, 408 or 429 is tried again later, for up to 24 hours. Any other 4xx is treated as final and is not tried again.Duplicates. A retry carries the same eventId. Store the ids you have handled and ignore any you have seen before.Security. The calls are not signed. Use an address that is hard to guess, and match the trackingNumber against your own orders before acting on a call.Errors#
Most replies use this shape:{ "status": "error", "message": "Shipment not found" }
| Status | When |
|---|
400 | The request is not valid. The message says what to fix. |
401 | Token missing or not accepted. |
403 | API access off or account not active. |
404 | No order of yours has this tracking number. |
409 | The order cannot be cancelled in its current status. |
422 | Too many orders in one Place orders request. |
429 | Another Place orders request is still running. |
Two endpoints use their own shape, so check their pages: Check coverage adds serviceable and reasonCode, and Place orders returns acceptedOrders and deniedOrders even for refused requests.Support#
Questions about the API or your account? Contact MyCourier Support and include your Merchant ID and, where relevant, the trackingNumber or shipperRef involved. Never send your API key.Modified at 2026-11-03 12:55:34