Feeef Cloud
Parcels API

Lifecycle

Send, read, list, edit, and cancel a parcel after it's created.

Send

POST /parcels/:id/send

Submits a created parcel to its carrier. 409 if the parcel isn't created (already sent, cancelled, etc.). A 502 carrier_error leaves status at created. A timeout can still leave the carrier outcome uncertain; check tracking and carrier state before resubmitting. It does not get stuck half-submitted.

curl -X POST "https://apis.cloud.feeef.org/v1/parcels/pcl_8Xw…/send" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY"

Validate (NOEST)

POST /parcels/:id/validate

Locks a carrier parcel after create when the adapter exposes capabilities.validate (NOEST today). Returns 501 carrier_unsupported otherwise. Already-validated parcels succeed as a no-op. On send, NOEST accounts auto-validate unless config.autoValidate is set to false.

curl -X POST "https://apis.cloud.feeef.org/v1/parcels/pcl_8Xw…/validate" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY"

Read

GET /parcels/:id

Includes the full events[] timeline in the same response — usually enough that you don't need a separate call to /parcels/:id/events unless you specifically need pagination over a long history.

curl "https://apis.cloud.feeef.org/v1/parcels/pcl_8Xw…" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY"

List

GET /parcels?status=&carrier=&stateCode=&createdAfter=&q=&limit=&cursor=

Cursor-paginated — see Conventions. Both SDKs ship a pagination helper that walks every page for you:

import { CloudClient, iteratePages } from '@cloud/sdk'

const client = new CloudClient({ apiKey: process.env.FEEEF_API_KEY! })

for await (const parcel of iteratePages((cursor) =>
  client.parcels.list({ status: 'in_transit', cursor }),
)) {
  console.log(parcel.trackingId)
}

Edit

PATCH /parcels/:id

Free-form while the parcel is still created. After submission, edits are capability-checked per carrier — an unsupported field comes back as 501 carrier_unsupported, naming the field in error.details. Check /geo/couriers if you need to know ahead of time whether a carrier account supports post-submission edits at all.

curl -X PATCH "https://apis.cloud.feeef.org/v1/parcels/pcl_8Xw…" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "recipient": { "phone": "0551222333" } }'

Remarks, return & redelivery (NOEST)

POST /parcels/:id/remarks

Adds a carrier-side update note (add/maj). Body: { "content": "…" } (max 255).

POST /parcels/:id/request-return

Asks NOEST to return the parcel to the partner (ask/return).

POST /parcels/:id/request-redelivery

Asks NOEST for another delivery attempt (ask/new-tentative).

All three require a submitted parcel with a tracking id and a carrier that declares the matching capability — otherwise 501 carrier_unsupported.

Cancel

POST /parcels/:id/cancel

Cancels at the carrier where supported. { "force": "local" } detaches the parcel locally when the carrier has no cancel operation at all — the platform record moves to cancelled even though nothing was told to the carrier, which is the honest outcome when there's genuinely no API for it.

curl -X POST "https://apis.cloud.feeef.org/v1/parcels/pcl_8Xw…/cancel" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "force": "local" }'

On this page