Retries and Ambiguous Outcomes
Outcome
Classify the operation and certainty of its prior outcome before issuing another request. Retry budgets, timing, and operational review are client-owned policy.
What the public contract does not provide
The current public contract has no public idempotency key, no blanket safe-repeat guarantee, no public 429 or Retry-After, no public reconciliation operation, and no public correlation-ID contract. Label purchase is the single documented exception to blind-repeat danger, and it is bounded — see Label purchase below.
Read-only operations
Reissuing a read request may be reasonable after a transport failure, but the client should still apply its own retry budget and avoid unbounded loops. This does not make every GET universally safe under all conditions.
Authentication operations
For a protected operation with an unusable access token, attempt one refresh and retry the original request once only after refresh succeeds. If refresh fails, stop and authenticate again. Never create an infinite refresh/retry loop. See Token recovery.
Order creation
V1 Create Order is state-changing. After an ambiguous timeout or lost response, a duplicate Order cannot be ruled out. Do not blindly repeat the request.
Create-and-rate no-Rate 422
Create an Order with Rates creates one Order. A no-Rate 422 may be returned after that Order has already been created. Do not retry the entire request or blindly repeat it. The current public contract does not define idempotency or reconciliation for this outcome.
This differs from invalid-input 422; the public response does not define a
universal persisted-Order identifier or recovery sequence. See
Create an Order with Rates.
Rate retrieval
Rate retrieval does not purchase a Label. A client may choose a bounded, application-owned reissue policy, but must not expect the same Rates, ordering, values, carrier availability, or eventual success.
Label purchase
This is the one state-changing operation with a documented repeat contract, and
it is the exception to the section above. There is still no idempotency key;
instead, Mailhub recognizes a repeat from the Shipment's purchase operation and
the request that started it. Sending the same purchase request again replays its
outcome — it does not buy a second Label. A 202 means the purchase is still
running, not that it failed.
After a timeout or lost response you therefore have two safe moves: reissue the
same request within your own bounded budget, or read the Order, which carries
labelId and a LabelCreated status once the purchase completes. A request
that is not the same purchase is refused with 409 rather than starting a
competing one.
Two bounded conditions remain: a Label cancelled before its result reached you is not replaced by a repeat, and an unresolved carrier outcome is reconciled server-side and refuses a new purchase until it settles. See Buy a Label.
Label download
200 is binary; 202 means pending/still generating; other documented status
codes are not binary success. There is no retry interval, no Retry-After, and
no eventual-success guarantee. Avoid tight loops; retry cadence is
application-owned. See Binary Labels.
Label cancellation
After a timeout or lost response, provider, local-state, and financial outcomes may be ambiguous. Do not blindly repeat the cancellation request. The public contract does not define universal cancellation idempotency, refund, provider-confirmation, or eligibility-window behavior.
Checklist
- Correct invalid input before resubmitting it.
- Use the bounded refresh flow only for authentication recovery.
- Keep V1/V2 creation and cancellation out of blind-repeat paths.
- Repeat a Label purchase only as the same request, within a bounded budget.
- Branch Label downloads by status and actual
Content-Type. - Review Authentication Errors, Validation Errors, Order State Errors, Rate Errors, and Label Errors.
Next steps
- Use Diagnostics to record safe evidence for an application-owned investigation.
- Complete the Go-Live Checklist before relying on a production integration.