Skip to content

Get started ​

Use this page to set the API boundary and make the four customer-journey decisions before you write integration code.

Establish the boundary ​

The production API host is https://mexpress.nz/api/v1. The documentation host https://docs.mexpress.nz never handles API requests.

Keep webhook signing secrets and the POD Bearer token in server-side secret storage. Your receiver validates Content-Type and all four X-Delivery-Webhook-* headers, then uses X-Delivery-Webhook-Key-Id to look up the matching webhook secret. Your backend sends the POD token only to M Express. For EVT430 media links, use the composite Authorization: Bearer <signing_key_id>.<signing_secret> credential; rotation, deactivation, or deletion invalidates the prior credential. Do not place either credential in browser code, URLs, HTML, logs, support material, mobile storage, or a CDN.

Use HTTPS for API requests and for your webhook receiver. Keep the raw webhook bytes until signature verification finishes.

Use the shared fixture ​

Use only this synthetic fixture while you build and test the journey:

IdentifierValue
Tracking numberMX123456789
Package sequence numbers1, 2
Newer POD batch11111111-1111-4111-8111-111111111111, 2026-07-02T03:04:05.000000Z, sequence 1, captured with latitude "-36.8484600", longitude "174.7633320", accuracy_meters "4.50"
Older POD batch22222222-2222-4222-8222-222222222222, 2026-07-01T03:04:05.000000Z, sequence 2, unavailable status with all location values null
Package UUIDs33333333-3333-4333-8333-333333333333, 44444444-4444-4444-8444-444444444444

The POD response keeps two completed batches separate and orders them newest first. A package row maps the requested shipment tracking_number to the related Package's positive integer sequence_number; it is never a scan-code projection. Visible pending shipments return an empty delivery_batches array.

Captured coordinates are projected only when all three persisted values are present, finite, and within the existing bounds. Missing, incomplete, invalid, out-of-range, and non-captured values are represented by all-null location coordinates.

Implement in this order ​

  1. Add Public Tracking. Handle 200, neutral detail-only 404, and 429 with a positive Retry-After.
  2. Add Webhooks. Verify raw bytes, persist event_id, deduplicate, and acknowledge before asynchronous work.
  3. Add POD API when you have a token with pod:read. Resolve media only from the manifest and proxy bytes through your backend.
  4. Exercise the empty, unavailable, duplicate, out-of-order, retry, and forbidden paths.

The Node.js and Python pages import the canonical runnable regions. They use standard-library cryptography and fake-client tests; they do not add a runtime dependency to your service.

End-to-end acceptance ​

  • [ ] Every request uses https://mexpress.nz/api/v1 and a path-encoded tracking number.
  • [ ] Tracking renders only its documented projection; 404 remains one neutral unavailable outcome.
  • [ ] Tracking waits for a positive Retry-After and never tight-loops.
  • [ ] The webhook receiver verifies timestamp, event ID, v1= HMAC, and raw bytes before JSON parsing.
  • [ ] The webhook receiver validates Content-Type and all four X-Delivery-Webhook-* headers, selecting the signing secret by X-Delivery-Webhook-Key-Id.
  • [ ] The receiver persists event_id before business effects and treats duplicate delivery as safe.
  • [ ] The receiver returns any timely, normal-sized 2xx; slow processing happens after acknowledgement.
  • [ ] The POD token is server-only and has pod:read.
  • [ ] The media proxy accepts only an application-owned mediaKey that was derived from the current manifest.
  • [ ] EVT430 media is fetched server-side with the current composite webhook credential; the prior credential is rejected after rotation, deactivation, or deletion.
  • [ ] The proxy validates the current shipment POD URL prefix, accepts only image/png, image/jpeg, and image/svg+xml, and requires normalized upstream Content-Type to match the manifest before preserving it with Cache-Control: private, no-store.
  • [ ] Synthetic data is used in local checks, and secrets never enter browser, URL, HTML, logs, mobile storage, or CDN.

Next step ​

Implement Public Tracking first, then connect Webhooks and POD API to the same shipment fixture.

M Express server-to-server integration guide