Ecotrack API — DHD, Anderson, World Express… for Node.js and PHP

Ecotrack is the platform behind DHD, Anderson, World Express and dozens of other Algerian couriers. With dz-delivery, a single ecotrack provider covers them all.

Install

TypeScript · npm
npm install @dz-delivery/core
PHP · Composer
composer require dz-delivery/sdk

Node.js ≥ 18 (zero dependencies) or PHP ≥ 8.2 (Guzzle 7). Every carrier implements the same interface, so the same code works with the others once the client is configured; some operations are not available on every carrier and throw NOT_SUPPORTED (see the capability matrix).

Ecotrack credentials

OptionValueNotes
tokenAPI token from the courier’s dashboardSent as Authorization: Bearer <token>
courierBuilt-in key (dhd, anderson, …)Exactly one of courier / baseUrl
baseUrlTenant HTTPS URL, e.g. https://xyz.ecotrack.dzFor any other Ecotrack courier
autoValidatefalse by defaulttrue: validates the order right after it is created

Ecotrack with TypeScript / Node.js

TypeScript
import { createClient, isShippingError } from '@dz-delivery/core';

const dhd = createClient('ecotrack', {
  token: process.env.ECOTRACK_TOKEN!,
  courier: 'dhd',              // or baseUrl: 'https://<tenant>.ecotrack.dz'
  autoValidate: true,          // hand the order over to the courier right away
});

try {
  const wilayas = await dhd.getWilayas();        // wilayas served by this courier
  const desks = await dhd.getStopDesks({ wilayaId: 16 });
  const quote = await dhd.getFees({ toWilayaId: 16 });

  const parcel = await dhd.createParcel({
    recipientName: 'Mohamed Amine',
    phone: '0550123456',
    address: 'Cité 221 lots, n°98',
    wilayaId: 16,
    communeName: 'Bab Ezzouar',
    productName: 'T-shirt',
    price: 2500,
    orderId: 'ORDER-1001',
  });

  const { parcel: current, events } = await dhd.track(parcel.trackingNumber);
} catch (err) {
  if (isShippingError(err)) console.error(err.code, err.message);
}

Ecotrack with PHP / Laravel

PHP
use DzDelivery\ClientFactory;
use DzDelivery\Errors\ShippingError;

$dhd = ClientFactory::create('ecotrack', [
    'token'        => getenv('ECOTRACK_TOKEN'),
    'courier'      => 'dhd',  // or 'baseUrl' => 'https://<tenant>.ecotrack.dz'
    'autoValidate' => true,
]);

try {
    $quote = $dhd->getFees(['toWilayaId' => 16]);

    $parcel = $dhd->createParcel([
        'recipientName' => 'Mohamed Amine',
        'phone'         => '0550123456',
        'address'       => 'Cité 221 lots, n°98',
        'wilayaId'      => 16,
        'communeName'   => 'Bab Ezzouar',
        'productName'   => 'T-shirt',
        'price'         => 2500,
        'orderId'       => 'ORDER-1001',
    ]);

    $result = $dhd->track($parcel->trackingNumber);
} catch (ShippingError $e) {
    echo "{$e->code}: {$e->getMessage()}";
}

Installation, Laravel, errors and testing: see the full PHP guide.

Supported methods

MethodSupportNotes
createParcelyesStays pending until validated (see autoValidate).
trackyesUnified status + history.
getFeesyesRates per wilaya.
getWilayas / getCommunesyesOnly the wilayas served by the tenant.
getStopDesksyesCommunes with a stop desk (id = Ecotrack postal code).
listParcelsNOT_SUPPORTEDNot implemented in the SDK yet.
cancelParcelyesOnly before the order is validated.
healthCheckyesChecks the token (real API call).

Built-in Ecotrack couriers

These courier keys work out of the box. For any other Ecotrack courier, pass its URL as baseUrl (HTTPS only).

CouriercourierDomain
DHDdhdplatform.dhd-dz.com
Anderson Deliveryandersonanderson-ecommerce.ecotrack.dz
World Expressworldexpressworld-express.ecotrack.dz
48Hr Express48hrexpress48hr.ecotrack.dz
EcoRapidecorapidecorapide-express.ecotrack.dz
Conexlogconexlogapp.conexlog-dz.com
MSM Gomsmgomsmgo.ecotrack.dz
Packerspackerspackers.ecotrack.dz
Rocket Deliveryrocketdeliveryrocketdelivery.ecotrack.dz

Ecotrack statuses → unified statuses

The SDK only maps Ecotrack’s stable keys (activity keys and order status keys), case-insensitively. The French display labels vary from one courier to another and map to unknown.

Ecotrack keyUnified status
prete_a_expedier, prete_a_preparerpending
order_information_received_by_carrier, en_preparation_stock, en_ramassagecreated
picked, accepted_by_carrier, dispatched_to_driver, attempt_delivery, vers_hub, en_hub, vers_wilaya, en_preparation, en_livraison, suspenduin_transit
livred, encaissed, payed, livre_non_encaisse, encaisse_non_paye, paiements_prets, paye_et_archivedelivered
return_asked, return_in_transit, return_received, retour_chez_livreur, retour_transit_entrepot, retour_en_traitement, retour_recu, retour_archivereturned
annulecancelled
Any other value (including notification_on_order and French labels)unknown

What each unified status means: full list of unified statuses.

Good to know about the Ecotrack API

  • Validation: without autoValidate: true, orders stay on hold until they are validated in the courier’s dashboard.
  • cancelParcel only works before validation; after that the API returns VALIDATION_ERROR.
  • The id of communes and stop desks is the Ecotrack postal code (“station code”): use it as-is for stopDeskId.
  • A baseUrl ending in /api/v1 is accepted (the suffix is stripped automatically).

Detailed native mapping (endpoints, fields, statuses): PROVIDERS.md.

Ecotrack FAQ

How do I integrate the DHD API?

DHD runs on Ecotrack: create an ecotrack client with your DHD token and courier: 'dhd'.

My courier uses Ecotrack but is not in the list?

Pass its tenant URL as baseUrl (e.g. https://mycourier.ecotrack.dz); the API is identical.

Why do my Ecotrack parcels stay on hold?

Ecotrack creates orders unvalidated. Turn on autoValidate: true or validate them from the courier’s dashboard.

Other carriers

Same interface, same unified statuses (pending, in_transit, delivered…).