Create
The create payload, destination resolution, and idempotent retries.
/parcelsHonors 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.