Feeef Cloud
Parcels API

Create

The create payload, destination resolution, and idempotent retries.

POST /parcels

Honors Idempotency-Key — safe to retry a create call that timed out without risking a duplicate shipment.

curl -X POST "https://apis.cloud.feeef.org/v1/parcels" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $REQUEST_KEY" \
  -d '{
    "carrierAccountId": "ca_9f2k…",
    "submit": false,
    "reference": "ORDER-4812",
    "recipient": { "name": "Amine B.", "phone": "0550111213" },
    "destination": { "country": "DZ", "state": "Blida", "city": "beni tamou", "address": "Rue des Frères…", "deliveryType": "stopdesk" },
    "codAmount": 3900,
    "weightKg": 1.2
  }'
{ "data": { "id": "pcl_8Xw…", "status": "created",
  "destination": { "stateCode": "09", "cityName": "Beni Tamou",
    "resolved": { "method": "exact", "confidence": 1 } } } }

Destination resolution

state and city accept dirty labels — the same Atlas resolver behind POST /geo/resolve runs on them here, automatically, every time. You don't call resolve yourself first; create does it inline and returns the resolution alongside the created parcel in destination.resolved.

If it cannot auto-accept the destination, you get 422 unresolvable_geo with alternatives[] instead of a silently wrong shipment — the same contract resolve has on its own. Check destination.resolved.method if you want to know how confident the match was even when it succeeded (exact vs fuzzy, for instance) — useful for flagging orders worth a human glance before they ship.

Submitting immediately vs. staging

submit: false (the default) writes the parcel to the platform without contacting the carrier — useful when you want to validate a destination or preview a label before committing. submit: true does both in one call. If you go the two-step route, POST /:id/send is the second step. Check an uncertain carrier outcome before retrying — see Lifecycle.

Check the commune before choosing stop-desk

deliveryType: "stopdesk" only works where the carrier accepts it, which is decided per commune, not per wilaya. Confirm with GET /geo/couriers/{courierId}/cities?state=<code>&city=<commune> and read hasPickup before you submit — otherwise the carrier rejects the parcel with carrier_error and the call is spent. hasPickup=true on the same endpoint lists the communes in that wilaya that would work, which is what you want to offer as alternatives.

Idempotency-Key is a 24-hour window

Replaying the same key with the same payload within 24 hours returns the original result rather than creating a second parcel. Replaying it with a different payload is a 409 idempotency_conflict — the platform assumes that's a bug in your retry logic, not an intentional overwrite.

Generate REQUEST_KEY="$(uuidgen)" once before a write and reuse $REQUEST_KEY with the identical body on retries.

On this page