API reference
Tracking
Shipment statuses, delivery events, ETAs, proof of delivery, public tracking and cancelling.
Last updated
After a shipment is created you can follow it in three ways: read it with your API key, give your customer the public tracking link, or receive webhooks as it moves. Statuses update automatically from our delivery network every few minutes.
Shipment statuses
pending → assigned → picked_up → in_transit → delivered
status | Meaning |
|---|---|
pending | Created and charged. The pickup is being booked |
assigned | A rider has been assigned to collect the package |
picked_up | The package has been collected from the sender |
in_transit | On its way: at a sorting centre, in transit between hubs, or out for delivery |
delivered | Delivered to the recipient. Terminal |
failed | The delivery could not be completed. Terminal |
cancelled | Cancelled before pickup and refunded. Terminal |
Every shipment keeps a statusHistory array of { status, at } entries, oldest first.
Delivery events
Status changes are deliberately coarse. For finer progress, shipments carry deliveryEvents: a list of { description, at } entries, newest first, written in plain language. The descriptions you will see include:
- Pickup booked
- Rider assigned for pickup
- Picked up
- Received at sorting centre
- Departed sorting centre
- Arrived at destination hub
- Out for delivery
- Delivery attempt unsuccessful
- Delivered
- Cancelled
Each new event is also sent as a shipment.tracking_update webhook.
Shipments also carry two flags:
| Field | Type | Description |
|---|---|---|
pickupBooked | boolean | true once the pickup is confirmed on our delivery network |
proofOfDeliveryAvailable | boolean | true when a delivery photo or signature can be downloaded |
Check a shipment's status
Auth: API key. A lightweight read that returns only trackingCode, status, statusHistory and etaAt. Use it when polling instead of fetching the whole shipment.
| Path parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The shipment _id returned by POST /shipments |
curl "https://api.7feastr.com/api/v1/logistics/v1/shipments/6716a3f2c9e77b0012a4d5e1/status" \
-H "Authorization: Bearer $SEVENFEASTR_API_KEY"
// Node.js 18+ (run as an ES module, or inside an async function)
const BASE_URL = "https://api.7feastr.com/api/v1/logistics/v1";
const shipmentId = "6716a3f2c9e77b0012a4d5e1";
const res = await fetch(`${BASE_URL}/shipments/${shipmentId}/status`, {
headers: { Authorization: `Bearer ${process.env.SEVENFEASTR_API_KEY}` },
});
const { data } = await res.json();
console.log(data.status, data.etaAt);
import os
import requests
BASE_URL = "https://api.7feastr.com/api/v1/logistics/v1"
shipment_id = "6716a3f2c9e77b0012a4d5e1"
res = requests.get(
f"{BASE_URL}/shipments/{shipment_id}/status",
headers={"Authorization": f"Bearer {os.environ['SEVENFEASTR_API_KEY']}"},
timeout=30,
)
data = res.json()["data"]
print(data["status"], data["etaAt"])
200 OK
{
"success": true,
"message": "OK",
"sandbox": true,
"data": {
"_id": "6716a3f2c9e77b0012a4d5e1",
"trackingCode": "7F-20261021-4F91A2C8",
"status": "in_transit",
"statusHistory": [
{ "status": "pending", "at": "2026-10-21T09:32:10.000Z" },
{ "status": "assigned", "at": "2026-10-21T10:05:42.000Z" },
{ "status": "picked_up", "at": "2026-10-21T11:20:03.000Z" },
{ "status": "in_transit", "at": "2026-10-21T13:47:19.000Z" }
],
"etaAt": "2026-10-22T09:30:00.000Z"
}
}
Errors: 404 not_found for an unknown shipment, 401 authentication_error.
Current ETA
Auth: API key. Returns the current estimated delivery time and where it came from.
curl "https://api.7feastr.com/api/v1/logistics/v1/shipments/6716a3f2c9e77b0012a4d5e1/eta" \
-H "Authorization: Bearer $SEVENFEASTR_API_KEY"
200 OK
{
"success": true,
"message": "OK",
"sandbox": true,
"data": { "etaAt": "2026-10-22T09:30:00.000Z", "source": "estimated", "status": "in_transit" }
}
| Field | Type | Description |
|---|---|---|
etaAt | ISO 8601 string | The current estimate |
source | string | estimated (the estimate made at booking) or live (recalculated from the rider's position) |
status | string | The shipment's current status |
Errors: 404 not_found for an unknown shipment, 401 authentication_error.
Proof of delivery
Auth: API key. When proofOfDeliveryAvailable is true, these return the delivery photo or the recipient's signature as an image (for example image/jpeg), not as JSON.
curl "https://api.7feastr.com/api/v1/logistics/v1/shipments/6716a3f2c9e77b0012a4d5e1/proof-of-delivery/photo" \
-H "Authorization: Bearer $SEVENFEASTR_API_KEY" \
--output delivery-photo.jpg
| HTTP | error.code | When |
|---|---|---|
| 404 | not_found | Unknown shipment, or no photo / signature is available for it |
| 401 | authentication_error | Missing, invalid or revoked API key |
Public tracking
Auth: none. Safe to call from a customer-facing page. It exposes only what a recipient needs: never the price, your business details or the pickup contact.
curl "https://api.7feastr.com/api/v1/logistics/v1/track/7F-20261021-4F91A2C8"
// Node.js 18+ (run as an ES module, or inside an async function)
const trackingCode = "7F-20261021-4F91A2C8";
const res = await fetch(`https://api.7feastr.com/api/v1/logistics/v1/track/${trackingCode}`);
const { data } = await res.json();
for (const event of data.events ?? []) {
console.log(event.at, event.description);
}
import requests
tracking_code = "7F-20261021-4F91A2C8"
res = requests.get(f"https://api.7feastr.com/api/v1/logistics/v1/track/{tracking_code}", timeout=30)
data = res.json()["data"]
for event in data.get("events", []):
print(event["at"], event["description"])
200 OK
{
"success": true,
"message": "OK",
"sandbox": false,
"data": {
"trackingCode": "7F-20261021-4F91A2C8",
"status": "in_transit",
"statusHistory": [
{ "status": "pending", "at": "2026-10-21T09:32:10.000Z" },
{ "status": "assigned", "at": "2026-10-21T10:05:42.000Z" },
{ "status": "picked_up", "at": "2026-10-21T11:20:03.000Z" },
{ "status": "in_transit", "at": "2026-10-21T13:47:19.000Z" }
],
"recipientName": "Tunde B.",
"dropoffAddress": "8 Admiralty Way, Lekki Phase 1, Lagos, Nigeria",
"etaAt": "2026-10-22T09:30:00.000Z",
"events": [
{ "description": "Out for delivery", "at": "2026-10-22T07:15:00.000Z" },
{ "description": "Received at sorting centre", "at": "2026-10-21T13:47:19.000Z" },
{ "description": "Picked up", "at": "2026-10-21T11:20:03.000Z" },
{ "description": "Rider assigned for pickup", "at": "2026-10-21T10:05:42.000Z" },
{ "description": "Pickup booked", "at": "2026-10-21T09:32:11.000Z" }
]
}
}
| Field | Type | Description |
|---|---|---|
trackingCode | string | The tracking code |
status | string | The current status |
statusHistory | array | { status, at } entries, oldest first |
recipientName | string | The recipient's name, masked (first name and last initial) |
dropoffAddress | string | The delivery address |
etaAt | ISO 8601 string | Estimated delivery time |
events | array | Delivery events as { description, at }, newest first |
Errors: 404 not_found for an unknown tracking code, 429 rate_limited above 30 requests per minute per IP.
Your customers can also follow a shipment in the browser at https://7feastr.com/logistics/track/<trackingCode>, for example https://7feastr.com/logistics/track/7F-20261021-4F91A2C8.
Cancel a shipment
Auth: API key. Cancels a shipment while it is still pending, before a rider is assigned. The full price is refunded to your wallet automatically. No request body is needed.
curl -X POST "https://api.7feastr.com/api/v1/logistics/v1/shipments/6716a3f2c9e77b0012a4d5e1/cancel" \
-H "Authorization: Bearer $SEVENFEASTR_API_KEY"
200 OK. The response is the updated shipment (abridged here):
{
"success": true,
"message": "OK",
"sandbox": true,
"data": {
"_id": "6716a3f2c9e77b0012a4d5e1",
"trackingCode": "7F-20261021-4F91A2C8",
"status": "cancelled",
"price": 8492.5,
"isRefunded": true
}
}
You also receive the shipment.cancelled and shipment.refunded webhooks if you subscribe to them.
| HTTP | error.code | When |
|---|---|---|
| 400 | invalid_request | The shipment is no longer pending, for example a rider has been assigned |
| 404 | not_found | Unknown shipment |
| 409 | invalid_request | The shipment changed at the same moment and can no longer be cancelled |
| 503 | service_unavailable | Cancellation is temporarily unavailable. Retry shortly |
If something goes wrong after a rider is assigned, open a dispute instead.