API reference

Partner events

Report lifecycle events for the packages you handle — as a carrier, PUDO point, customs broker or a foreign Starmile organization on the next leg. Each event you send moves the package forward in its flow. We validate every event before accepting it, so a doomed update is rejected immediately with a reason and a fix.

One event per status the package reaches

An accepted event returns 202 with result: "applied" and the new order_status. A rejected event returns 422 with result, an error and a hint. Requires an event scope (events:transport, events:pudo, events:customs or leg:handoff).

You send the events your scopesallow (see below). The endpoint defines the full menu; you use the subset you are granted. If a step in a package’s flow needs an event you do not send, the package simply does not move forward.

Validate before accept

Before an event is accepted, it is checked synchronously. Only a valid event is enqueued for the destination — we never accept an update that cannot be applied:

  • Scope — your credential is allowed to send this event type.
  • Resolve — the package and the destination organization (tenant) that owns it are found.
  • Step order— the event is a valid next transition for the package’s current status in its flow (an out-of-order event, e.g. delivered before out_for_delivery, is rejected).
  • Smoke test — we dry-run the transition the destination would apply (guards pass, target step exists, context present).
  • On failure → 422 with an error (what is wrong) and a hint (how to fix). On success → the event is routed to the destination organization, which advances the package.

Delivery is idempotent: re-sending the same event_id is safe and applied once.

Report an event

POST/api/v1/partner/events

Body

event_idstringrequired
Your unique id for this event — the idempotency key. Re-sending it is safe.
typestringrequired
The event type, from the catalogue below. Must be within your granted scope.
tracking_numberstringrequired
The Starmile tracking number (or parcel / bag reference) the event applies to.
occurred_atstringrequired
ISO-8601 timestamp of when the event actually happened.
dataobjectoptional
Optional event-specific payload. Its allowed fields are fixed per event type (see the catalogue below) and type-checked; every event also accepts a free-text note. Any field the event does not define is rejected 422.
curl -X POST https://api.starmile.io/api/v1/partner/events \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "event_id": "evt-7f3a-0001",
    "type": "shipment.out_for_delivery",
    "tracking_number": "STM000123",
    "occurred_at": "2026-06-20T15:02:00Z",
    "data": {
      "driver": "Rashad",
      "eta": "2026-06-20T17:30:00Z"
    }
  }'

Scopes

Access is granted as scopes on your credential — not by a partner “type”. You may hold any combination; a party that is both a carrier and a PUDO simply gets both event scopes on one credential. An event outside your granted scope is rejected 422.

Event catalogue

The events the platform models today, grouped by the scope that grants them. Each is accepted only when its status is a legal next step for the package — otherwise you get a 422 listing the statuses expected next. The data fields column lists exactly what each event’s data object may carry — all optional and type-checked; every event also accepts a free-text note, and any other field is rejected.

events:transport — carrier

EventSets statusdata fieldsDescription
shipment.accepted_by_carriercustoms_releasednotecarrier_referenceawbThe carrier has taken custody of the shipment for the line haul.
shipment.arrived_at_terminalarrived_at_terminalnoteterminalThe shipment reached the destination-country terminal.
shipment.out_for_deliveryout_for_deliverynotedriveretaA driver is carrying the parcel to the recipient.
shipment.delivereddeliverednoterecipient_namesigned_byproof_of_deliveryHanded over to the recipient — the delivery is complete.
shipment.delivery_faileddelivery_failednotereasonattemptA delivery attempt did not succeed (e.g. recipient absent).
shipment.returnedreturnednotereasonThe shipment is being returned to origin.

events:pudo — pick-up / drop-off point

EventSets statusdata fieldsDescription
parcel.acceptedaccepted_at_pudonotepoint_codeshelfAccepted at the PUDO point — for a delivery it is now held for the recipient to collect; for a return it is held to go back. The hold window follows the order's service direction.
parcel.ready_for_driverparcel_racked_at_hubnotepoint_codeStaged and ready for your driver to collect from the point.
parcel.receivedreceived_at_pudonotepoint_codeParcel received at the PUDO point.
parcel.delivereddeliverednoterecipient_namesigned_byproof_of_deliveryHanded over to the recipient at the point.
parcel.timeoutundeliverednoteUncollected past the point's storage window.
parcel.dropoff_cancelleddropoff_cancellednotereasonA scheduled drop-off at the point was cancelled.

events:customs — customs broker (not on Smart Customs)

EventSets statusdata fieldsDescription
customs.heldcustoms_holdnotereasonreferenceCustoms placed the parcel on hold pending review or documents.

leg:handoff — foreign Starmile organization on the next leg

EventSets statusdata fieldsDescription
leg.receivedreceived_at_hubnotereferenceThe destination organization received the package for its leg.
leg.out_for_deliveryout_for_deliverynotedriveretaOut for delivery on the destination organization's leg.
leg.delivereddeliverednoterecipient_namesigned_byproof_of_deliveryDelivered on the destination organization's leg.
leg.delivery_faileddelivery_failednotereasonattemptA delivery attempt on the destination leg did not succeed.
leg.returnedreturnednotereasonThe package is being returned on the destination leg.