API reference · Try it now · Couriers · Wilaya dataset · freeship.dzbuild.com
Create and track cash-on-delivery parcels with 99 Algerian couriers through one API — Yalidine, ZR Express, Maystro, NOEST, and every courier running on Ecotrack. Plus the field notes on how each one actually behaves, and the complete wilaya + commune dataset.
The code examples run against dzship, the free hosted API at freeship.dzbuild.com. No signup, no API key. You bring your own courier account credentials per call and they are never stored.
Maintained by DZBuild, the e-commerce platform that moves real COD orders across all wilayas every day. These guides are the field notes from that shipping engine.
Every other courier needs a merchant contract before you can send one request. This one doesn't exist, so you can start in ten seconds — it validates exactly what a real courier validates, and creates nothing:
curl -X POST https://freeship.dzbuild.com/v1/orders \
-H 'Content-Type: application/json' \
-d '{
"courier": "sandbox",
"order": {
"recipient": { "fullName": "Amine Bouzid", "phone": "0551234567",
"wilayaCode": 16, "communeName": "Bab Ezzouar" },
"deliveryType": "home", "productList": "Sneakers x1", "codAmount": 4500
}
}'{ "trackingNumber": "DZTEST-1A2B3C", "status": "created", "reference": "FS-…" }When your Yalidine (or DHD, or Maystro…) credentials arrive, change two fields.
curl -X POST https://freeship.dzbuild.com/v1/orders \
-H 'Content-Type: application/json' \
-d '{
"courier": "yalidine",
"credentials": { "apiId": "YOUR_API_ID", "apiToken": "YOUR_API_TOKEN" },
"options": { "fromWilaya": 16 },
"order": {
"recipient": {
"fullName": "Amine Bouzid",
"phone": "0551234567",
"wilayaCode": 16,
"communeName": "Bab Ezzouar"
},
"deliveryType": "home",
"productList": "Sneakers Air x1",
"codAmount": 4500
}
}'{ "trackingNumber": "yal-ABC123", "status": "created", "reference": "FS-…" }Swap "courier" and "credentials" to ship with any other courier. The request
shape stays the same. Full reference: docs/endpoints.md.
| Guide | What it answers |
|---|---|
| API reference | Every endpoint and field, errors, rate limits |
| Integrating dzship | Ready-made clients (Node, PHP, Python) and copy-paste snippets for every stack |
| Choosing a courier | Which delivery company fits your project: coverage, stop-desk, exchanges, API quality |
| Wilayas & communes | The complete dataset, and why Algeria's new 69-wilaya division must not reach a courier yet |
| Yalidine | The biggest network. Also Yalitec, Guepex, Easy & Speed, Economiqua, We Can |
| ZR Express | Procolis. Strong in the center, simple credential model |
| Maystro | Fulfillment-style courier with a strict duplicate policy |
| NOEST | Why parcels get stranded if you skip the validation step |
| Ecotrack couriers | DHD, Conexlog, MSM Go, Rocket, World Express and 78 more — one key each |
| Delivery statuses | One status vocabulary for all couriers, with French and Arabic UI labels |
| Cash on delivery | COD mechanics: fees, returns, the deep-south surcharge, confirmation calls |
curl 'https://freeship.dzbuild.com/v1/couriers?q=rocket'| Family | courier keys |
Credentials |
|---|---|---|
| Yalidine | yalidine yalitec guepex easyandspeed economiqua wecan |
apiId, apiToken |
| ZR Express (Procolis) | zrexpress — also answers to abexexpress, leopardexpress, colilog, flashdelivery |
token, key |
| ZR Express (new platform) | zrexpressnew |
apiKey, tenantId |
| Maystro | maystro |
apiKey |
| NOEST | noest |
apiToken, guid |
| Ecotrack (82 couriers) | dhd conexlog msmgo rocketdelivery worldexpress andersondelivery … |
token |
| Zimou Express | zimou |
token |
| Colivraison | colivraison |
publicKey, token |
| Ecom Delivery | ecomdelivery |
apiKey, apiToken |
| Elogistia | elogistia |
apiKey |
| Near Delivery | neardelivery |
apiKey, apiSecret |
| MDM Express | mdm |
apiKey |
| Test courier | sandbox |
none |
You name the courier; dzship keeps the address. Nothing to look up, nothing to configure — and no way for a request to point the server at somewhere a courier does not own.
The clients/ directory has MIT-licensed clients that wrap the same
calls, with typed errors and retry-after handling built in:
-
Node.js —
npm install dzship(zero dependencies, TypeScript types included):import dzship from 'dzship'; const client = dzship({ courier: 'yalidine', credentials: { apiId: '…', apiToken: '…' } }); const { trackingNumber } = await client.createOrder({ /* recipient, productList, codAmount… */ }); const communes = await client.communes(16);
-
PHP — copy the single file
clients/php/Dzship.php(ext-curl only, shared-hosting friendly). -
Python — copy the single file
clients/python/dzship.py(standard library only, 3.8+).
The integration guide has full examples for Laravel, WooCommerce, Django, Google Sheets and raw HTTP in any language.
Most Algerian projects rebuild this list by hand, badly. It is in
data/ as JSON and CSV — French + Arabic names, numeric codes:
| File | Contents |
|---|---|
wilayas.json |
The 58 wilayas couriers deliver to |
communes.json · .csv |
All 1,541 communes |
wilayas-2026.json |
All 69 wilayas of the 2026 division, each with courierSupported and shipAs |
new-wilayas-2026.json |
The 11 new wilayas with the 108 communes transferred into them |
communes-moved-2026.csv |
Old code → new code, as a flat join |
const wilayas = await fetch(
"https://raw.githubusercontent.com/DZBuild-com/dzship/main/data/wilayas.json"
).then((r) => r.json());Free to use in any project, no attribution needed.
Algeria became 69 wilayas in April 2026 — and no courier accepts a code
above 58 yet, because the parent wilayas keep running the new territories until
the handover completes. Send wilayaCode: 60 today and the parcel is rejected.
So the two lists are kept apart on purpose, and every new wilaya tells you what
to ship it as:
curl https://freeship.dzbuild.com/v1/wilayas?68
# { "code": 68, "nameFr": "Bou Saâda", "courierSupported": false, "shipAs": 28, … }The wilayas & communes guide has the gazette
references, the full table, and the spelling traps (Aïn Ouessara in the law,
Ain Oussera in every courier's database).
Every Algerian courier ships its own API: different auth, different field names, statuses in French, Arabic, or bare numbers, and documentation that ranges from thin to wrong. The failure modes are quiet ones. A commune spelled differently than the courier's list, a validation step the docs never mention, a status code that looks inverted. Your integration works in the demo and strands parcels in production.
These guides exist so you don't relearn each trap the expensive way. Where a trap is already handled by the dzship API, the guide says so and you can stop worrying about it.
The hosted API is free and stays free: 200 orders/hour per IP, 60 tracking calls per minute, and reference data you should cache rather than poll. The full table is in docs/endpoints.md. Call it from a server — courier credentials in browser JavaScript are public credentials.
If the shipping integration is part of a bigger build for a merchant, look at DZBuild before writing more code: Arabic/French storefronts, landing pages, COD order management with confirmation workflows, 100+ couriers pre-wired, stock and analytics. You keep dzship for the custom pieces.
Courier missing, commune misspelled, status mapped wrong? That is the most useful issue you can open — see CONTRIBUTING.md. Security reports go to SECURITY.md.
© DZBuild. The guides, clients and datasets here are MIT licensed — the datasets are public domain on top of that. The hosted service itself is proprietary and is not in this repository; see NOTICE.md.