Idempotency & retries

Network errors and timeouts happen. When a request times out, you can't tell whether Helthjem received it. This page explains how to retry safely, especially for bookings.

Why it matters for bookings

POST /parcels/v1/bookings creates a real shipment. If a booking request times out and you simply send it again, you can end up with two shipments for one order: two labels, two deliveries and two invoice lines.

To prevent this, send an idempotency-key header with every booking request.

The idempotency-key header

If Helthjem receives a second booking request with the same idempotency-key within {N hours} of a successful booking, it returns the original response and does not create a new shipment.

curl -X POST "https://api.pre.helthjem.no/parcels/v1/bookings" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "idempotency-key: 3f1b2c9e-8a7d-4e21-9c55-0a1b2c3d4e5f" \
  -d @booking.json

Choosing a key

  • Use a value that is unique per shipment you intend to create. A UUID works well.
  • Keep it to 40 characters or fewer. Longer keys are rejected with 400 and errorKey: over.max.length.of.idempotency.key.
  • Store the key with your order before you send the request, so that a crash or restart reuses the same key.
  • Don't reuse a key for a different shipment. If one order needs two separate shipments, use two keys.
  • If you change the request body, for example to fix a validation error, use a new key.

Without a key, every request is new

If you don't send an idempotency-key, each request is treated as a new booking. A retry after a timeout can create a duplicate shipment, which you then need to cancel.

When to retry

Response Retry? What to do
Timeout, connection reset or no response ✅ Yes Retry with the same key. The booking may or may not exist; the key makes the retry safe.
5xx ✅ Yes Retry with the same key, with exponential backoff, e.g. after 1 s, 2 s, 4 s and 8 s. Stop after about 5 attempts.
401 ✅ After refreshing the token Request a new token, then retry with the same key.
400, 403, 404 ❌ No The request itself is wrong. Fix it first, and use a new key if you change the body.

Retrying other endpoints

Endpoint Safe to retry?
GET labels and tracking Yes. They don't change anything.
POST Single Address Check, pickup dates, nearby service points Yes. They only read data, even though they use POST.
POST /auth/oauth2/v1/token Yes. Each call issues a new token.
DELETE cancel a booking Yes in effect. Cancelling a booking that is already cancelled returns an error that you can treat as success.

Your own shipmentId as a second safeguard

If you set your own shipmentId in the booking request, Helthjem rejects a second booking with the same value (400, errorKey: shipment.id.already.exists). Treat this error as "already booked" rather than as a failure. See Identifiers.

Last updated