Delivery
Carrier integrations (12 carriers), the generic parcel bridge, inbound tracking webhooks, Ecotrack sync, and shipping prices.
Feeef ships COD orders through carrier integrations — one config per carrier under
store.integrations.{carrier} (see Integrations for the config
API). Once a carrier is configured, you can quote fees, create shipments from orders, print
labels, and receive status updates pushed back by the carrier.
All merchant operations require a Bearer token unless marked Public. Inbound carrier
webhook receivers are public by design — the carrier calls them, authenticated by store id +
payload semantics.
Carrier catalog
Key ({carrier}) | Carrier | Credentials in config |
|---|---|---|
yalidine | Yalidine / Guepex | id, token, agent (yalidine or guepex) |
ecotrack | Ecotrack (multi-brand) | baseUrl, token |
zrexpress | ZR Express | ZR/Procolis token pair |
procolis | Procolis | key, token |
noest | Noest Express | guid, token |
maystroDelivery | Maystro Delivery | API token |
zimou | Zimou Express | apiKey |
mdmExpress | MDM Express | API key (see token exchange below) |
ecomanager | EcoManager | baseUrl, token |
codpilot | COD Pilot | API credentials |
feeefDelivery | Feeef Delivery (white-label partner) | provisioned via enable |
orderdz | OrderDZ (order forwarding) | API credentials |
Carriers are credential-required integrations: subscribing
never stubs a config — write credentials first, then set active: true.
Generic carrier bridge
The bridge exposes one canonical surface over eight carriers (ecotrack, yalidine,
zrexpress, mdmExpress, feeefDelivery, maystroDelivery, noest, procolis), so you
don't need per-carrier request shapes. Aliases maystro, zr, and mdm are accepted for
{carrierCode}.
| Method | Path | Description | Auth |
|---|---|---|---|
POST | /v1/stores/{storeId}/integrations/{carrierCode}/parcels/send | Create a shipment from a ParcelCreate body | Bearer |
POST | /v1/stores/{storeId}/integrations/{carrierCode}/parcels/sendMany | Bulk — body { "parcels": [...] } | Bearer |
POST | /v1/stores/{storeId}/orders/{orderId}/carriers/{carrierCode}/send | Build the parcel from the order, merge optional body patch, send | Bearer |
POST | /v1/stores/{storeId}/orders/{orderId}/carriers/{carrierCode}/unsend | Cancel/remove the carrier shipment — body { "tracking": "…" } | Bearer |
POST | /v1/stores/{storeId}/orders/{orderId}/carriers/{carrierCode}/delete | Alias of unsend | Bearer |
A ParcelCreate needs at minimum reference, items[], and total (the COD amount; legacy
codAmount is normalized). Useful optional fields: contact (firstName, phones[]),
address (street, cityCode, stateCode), shippingType (home | pickup | store),
freeShipping, pickupId (stop-desk id), fromStock, package (weight/dimensions), and
carrier-specific extensions.
Send an order to a carrier
# From an existing order (parcel is derived from the order, body patches it)
curl -X POST "https://api.feeef.org/v1/stores/{storeId}/orders/{orderId}/carriers/yalidine/send" \
-H "Authorization: Bearer $FEEEF_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "shippingType": "pickup", "pickupId": "163" }'
# Or standalone from a ParcelCreate
curl -X POST "https://api.feeef.org/v1/stores/{storeId}/integrations/ecotrack/parcels/send" \
-H "Authorization: Bearer $FEEEF_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reference": "ORD-1042",
"total": 4500,
"items": [{ "name": "Montre X", "quantity": 1 }],
"contact": { "firstName": "Amine", "phones": ["0550000000"] },
"address": { "street": "Cité 20 Août", "stateCode": "16", "cityCode": "1601", "country": "DZ" }
}'Common per-carrier operations
Carrier-native routes live under /v1/stores/{storeId}/integrations/{carrier}/…. Not every
carrier implements every operation — the accordions below list exact support.
| Method | Path | Description | Auth |
|---|---|---|---|
GET | …/{carrier}/fees (some also …/rates) | Delivery fee matrix — legacy shape: one row per wilaya, [desk, home] | Bearer |
POST | …/{carrier}/send | Send one order (body usually { "orderId": … } or carrier-specific) | Bearer |
POST | …/{carrier}/sendMany | Bulk send | Bearer |
GET | …/{carrier}/orders/{tracking} | Fetch one parcel | Bearer |
DELETE | …/{carrier}/orders/{tracking} | Delete/cancel one parcel | Bearer |
POST | …/{carrier}/orders/deleteMany | Bulk delete — body { "trackings": [...] } | Bearer |
GET | …/{carrier}/orders/{tracking}/label | Single label (PDF/URL) | Bearer |
POST | …/{carrier}/labels | Bulk labels — body { "trackings": [...] } | Bearer |
ANY | …/{carrier}/webhook | Inbound status webhook (carrier → Feeef) | Public |
GET | …/{carrier}/webhook/url | The URL to register at the carrier | Bearer |
POST | …/{carrier}/webhook/setup | Register the webhook at the carrier for you | Bearer |
Inbound carrier webhooks
yalidine, zimou, ecotrack, zrexpress, maystroDelivery, feeefDelivery, and
ecomanager accept inbound webhooks. They update the order's deliveryStatus /
paymentStatus (and customStatus rules) from carrier events — parcel status changes,
payments, deletions. Yalidine additionally answers the CRC subscription challenge
(subscribe + crc_token). For ZR Express and Maystro, use webhook/url + webhook/setup
to register; EcoManager uses POST …/ecomanager/setup.
Get a carrier fee matrix
curl -H "Authorization: Bearer $FEEEF_TOKEN" \
"https://api.feeef.org/v1/stores/{storeId}/integrations/ecotrack/fees"Ecotrack sync
Ecotrack has a server-side sync engine (rate-limited to one run per ~2 hours per store) that pulls parcel statuses and COD cash-in history back into orders, and posts customer payments into Finance when active. A push notification is sent when a run finishes.
| Method | Path | Description | Auth |
|---|---|---|---|
GET | /v1/stores/{storeId}/integrations/ecotrack/sync/status | Cooldown state: canSync, lastSyncAt, nextSyncAvailableAt | Bearer |
POST | /v1/stores/{storeId}/integrations/ecotrack/sync | Sync order statuses — optional startDate / endDate | Bearer |
POST | /v1/stores/{storeId}/integrations/ecotrack/sync/cashin | Sync COD payouts only — optional forceAll | Bearer |
POST | /v1/actions/syncEcotrackOrders | Legacy one-shot sync action | Bearer |
POST | /v1/actions/createTokenForEcotrackByEmailAndPassword | Exchange Ecotrack email/password for an api_token (server-side proxy) | Bearer |
POST | /v1/actions/createMdmExpressApiKeyFromUserLogin | Same idea for MDM Express | Bearer |
Ecotrack also exposes extra reads: GET …/ecotrack/orders (parcel list), GET …/ecotrack/finance,
GET …/ecotrack/statistics, GET …/ecotrack/stock/products, POST …/ecotrack/orders/{tracking}/validate,
and POST …/ecotrack/scoring.
Trigger a sync
curl -X POST "https://api.feeef.org/v1/stores/{storeId}/integrations/ecotrack/sync" \
-H "Authorization: Bearer $FEEEF_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "startDate": "2026-08-01T00:00:00Z" }'Per-carrier specifics
Extras beyond the common set: POST …/yalidine/resolve (resolve state/city names to Yalidine
territory ids before sending), GET …/yalidine/centers (stop-desk center ids per state).
GET …/yalidine/fees accepts id/token/agent overrides as query params, otherwise the
stored config is used. Legacy paths …/parcels/{tracking} (GET/DELETE) mirror
…/orders/{tracking}. The webhook handles parcel_deleted, parcel_status_updated, and
parcel_payment_updated events.
Full common set plus the sync engine, finance/statistics reads, stock products, parcel
validation and scoring (see Ecotrack sync). GET …/ecotrack/list is a
legacy alias of GET …/ecotrack/orders.
GET …/zrexpress/rates (alias …/fees), send/sendMany, DELETE …/zrexpress/orders
(tracking in body), orders/deleteMany, single + bulk labels, and
POST …/zrexpress/label/individual (alias labelIndividual) for one-off label generation.
Webhook registration via webhook/url + webhook/setup (aliases webhookUrl,
setupWebhook).
GET …/procolis/fees, POST …/procolis/send (body { "orderId": … }), and
POST …/procolis/list (parcel listing/read from Procolis).
POST …/noest/send (body { "orderId": … }). The GET …/noest/fees endpoint is declared but
not implemented server-side — rely on shipping prices for quoting.
GET …/maystroDelivery/rates (alias …/fees), send/sendMany, DELETE …/maystroDelivery/orders,
orders/deleteMany, labels (single, bulk, individual), webhook registration via
webhook/url + webhook/setup, public inbound webhook.
Send/sendMany plus geo lookups: GET …/zimou/wilayas, GET …/zimou/communes,
GET …/zimou/states, GET …/zimou/cities, and GET …/zimou/statistics.
POST …/zimou/test (alias testConnection) validates the API key. Zimou has no fees API —
GET …/zimou/fees returns an empty list; use shipping prices instead.
GET …/mdmExpress/fees (alias …/rates) and GET …/mdmExpress/service-fees (per-service
pricing), send/sendMany. Mint an API key from a user login with
POST /v1/actions/createMdmExpressApiKeyFromUserLogin.
GET …/ecomanager/fees, POST …/ecomanager/send, inbound POST …/ecomanager/webhook
(Public), and POST …/ecomanager/setup (alias setupWebhook) to register the webhook.
Configs with an empty baseUrl/token are sanitized away server-side.
POST …/codpilot/ping (credential check), POST …/codpilot/send,
POST …/codpilot/sendMany (body { "orderIds": [...] }).
Provisioned carrier — start with POST …/feeefDelivery/enable, verify with
GET …/feeefDelivery/ping. Quoting via fees + rates, geo data via
GET …/feeefDelivery/geo/{kind}. Parcels: send/sendMany, GET …/parcels/{tracking},
GET …/parcels/{tracking}/label. COD payouts (encaissements):
GET …/encaissements/preview, GET …/encaissements/batches,
GET …/encaissements/batches/{batchId}, POST …/encaissements/batches/confirm. Public
inbound webhook.
POST …/orderdz/send forwards an order to OrderDZ (order-confirmation service rather than a
physical carrier).
Dispatcher
Related to fulfillment ops: POST /v1/stores/{storeId}/integrations/dispatcher/dispatch
(Bearer) manually assigns orders to confirmers — body
{ "orderIds": [...], "strategy": "roundRobin" } with strategies random, weightedRandom,
roundRobin, priority.
Shipping prices
Structured, geo-aware shipping pricing (per country/state/city, home vs desk) — the successor
to the legacy per-store rate arrays. Storefronts read a single price document to compute
shipping at checkout; the store references it via shippingPriceId.
| Method | Path | Description | Auth |
|---|---|---|---|
GET | /v1/shipping_prices?store_id={storeId} | List price documents for a store | Bearer |
GET | /v1/shipping_prices/{id} | One price document (public so storefronts can quote) | Public |
POST | /v1/shipping_prices | Create | Bearer |
PUT | /v1/shipping_prices/{id} | Update | Bearer |
DELETE | /v1/shipping_prices/{id} | Delete | Bearer |
Legacy shipping methods (/v1/shipping_methods resource + POST /v1/shipping_methods/{id}/fork)
remain for older stores — wilaya-indexed [desk, home] arrays, same shape as the carrier
fees endpoints.
List a store's shipping prices
curl -H "Authorization: Bearer $FEEEF_TOKEN" \
"https://api.feeef.org/v1/shipping_prices?store_id={storeId}"Related
- Integrations — configure carrier credentials, billing/entitlement
- Webhooks — outbound order and product events (Feeef → your server)
- API conventions — errors, pagination, batch envelopes