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:
| Identifier | Value |
|---|---|
| Tracking number | MX123456789 |
| Package sequence numbers | 1, 2 |
| Newer POD batch | 11111111-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 batch | 22222222-2222-4222-8222-222222222222, 2026-07-01T03:04:05.000000Z, sequence 2, unavailable status with all location values null |
| Package UUIDs | 33333333-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
- Add Public Tracking. Handle
200, neutral detail-only404, and429with a positiveRetry-After. - Add Webhooks. Verify raw bytes, persist
event_id, deduplicate, and acknowledge before asynchronous work. - Add POD API when you have a token with
pod:read. Resolve media only from the manifest and proxy bytes through your backend. - 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/v1and a path-encoded tracking number. - [ ] Tracking renders only its documented projection;
404remains one neutral unavailable outcome. - [ ] Tracking waits for a positive
Retry-Afterand never tight-loops. - [ ] The webhook receiver verifies timestamp, event ID,
v1=HMAC, and raw bytes before JSON parsing. - [ ] The webhook receiver validates
Content-Typeand all fourX-Delivery-Webhook-*headers, selecting the signing secret byX-Delivery-Webhook-Key-Id. - [ ] The receiver persists
event_idbefore 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
mediaKeythat 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, andimage/svg+xml, and requires normalized upstreamContent-Typeto match the manifest before preserving it withCache-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.