Recover a Label Purchase After 202
A 202 from a Label purchase means the purchase is still running. Read the
Order to find out how it ended.
What you'll build
- The one recovery path the public contract supports: reading the Order.
- A check for the Label identifier appearing on that Order.
- A completion signal you never have to set yourself.
Prerequisites
- An access token — see Authentication.
- A
202from Buy a Label from a Selected Rate. - The
orderIdof the Order that owns the Shipment — from Create an Order and Get Rates in One Call, or fromdata.orderIdon a200purchase response. - Python examples use the
requestspackage.
What a 202 gives you
{
"success": true,
"data": {
"operationId": "...",
"shipmentId": "b91a2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"status": "Processing",
"correlationId": "..."
},
"errors": null
}
Step 1 — Read the Order
GET/api/v1/orders/{orderId}
- cURL
- JavaScript
- Python
- Java
curl -s "${MAILHUB_API_BASE_URL}/api/v1/orders/${ORDER_ID}" \
-H "Authorization: Bearer ${MAILHUB_ACCESS_TOKEN}"
const response = await fetch(
`${process.env.MAILHUB_API_BASE_URL}/api/v1/orders/${orderId}`,
{headers: {Authorization: `Bearer ${process.env.MAILHUB_ACCESS_TOKEN}`}},
);
const {data: order} = await response.json();
// Absent while the purchase is still running. Your application decides when to
// look again; the contract defines no interval.
const labelId = order.labelId ?? null;
import os
import requests
response = requests.get(
f"{os.environ['MAILHUB_API_BASE_URL']}/api/v1/orders/{order_id}",
headers={"Authorization": f"Bearer {os.environ['MAILHUB_ACCESS_TOKEN']}"},
)
order = response.json()["data"]
# Absent while the purchase is still running. Your application decides when to
# look again; the contract defines no interval.
label_id = order.get("labelId")
// Java 11+ java.net.http — no MailHub package to install and no third-party client.
var request = HttpRequest.newBuilder()
.uri(URI.create(System.getenv("MAILHUB_API_BASE_URL") + "/api/v1/orders/" + orderId))
.header("Authorization", "Bearer " + System.getenv("MAILHUB_ACCESS_TOKEN"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// Parse response.body() with your own JSON library. data.labelId is absent while
// the purchase is still running. Your application decides when to look again;
// the contract defines no interval.
Response
Once the purchase has completed:
{
"success": true,
"data": {
"id": "5f2c1a10-2b3d-4e5f-8a9b-0c1d2e3f4a5b",
"labelId": "f6c7d8e9-0a1b-4c2d-8e3f-4a5b6c7d8e9f",
"shipmentId": "b91a2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"status": 8,
"...": "..."
},
"errors": null
}
status is the numeric public Order status enum; 8 is LabelCreated. See
Order Lifecycle for the full membership.
Use this next
data.labelId — the same identifier a 200 purchase returns as
data.postageLabel.id. Carry it into
Download a Label File.
Expected result
An Order carrying a labelId, and a status of 8.
Common outcomes
| What you see | What it means | What to do |
|---|---|---|
labelId is null or absent | The purchase has not completed yet. | Read the Order again later. Choose a polling cadence appropriate for your application — the contract defines none. |
labelId is present, status is 8 | The purchase completed. | Use labelId to download the Label. |
409 on a further purchase attempt | Another purchase for that Shipment is still being resolved. | Keep reading the Order. Do not start a competing purchase. |
Next steps
- Download a Label File — spend the
labelIdyou just read. - Get order by ID in the API Reference — the complete Order response schema.
- Buy a Label — the bounded window behind the
202and the repeat semantics. - Retries and Ambiguous Outcomes — the cross-operation policy for lost and ambiguous responses.