One integration for USPS, FedEx and DHL. Create an order and get every carrier’s rate back in the same response, with the discounted price and a delivery estimate where the carrier provides one.
curl -X POST https://api.mailhub.com/api/v2/orders \
-H "Authorization: Bearer <accessToken>" \
-H "Content-Type: application/json" \
-d '{ "order": { "toAddress": { ... }, "shipments": [ ... ] } }'
A shipping API connects your application straight to carrier networks, pulling live rates, buying labels and returning tracking numbers in code rather than through a dashboard. Mailhub returns every carrier in one response with the same shape, so adding a carrier never means writing another integration.
Quote live rates at checkout, then buy the label the moment an order is confirmed.
Run shipping for every business you serve from one connection, separated by sub-account.
Give sellers real carrier rates and labels without each opening their own accounts.

If you ship on behalf of other businesses, every call can carry a sub-account ID, so each client’s orders and labels sit under their own sub-account. You write the code once, not once per client.
1
3
3
$0
Exchange your API key for an access token that authorises every call after it.
One request creates the order and returns every carrier’s rate, with a delivery estimate where there is one.
Pick a rate, then get back a tracking code and a label file ready to print.
curl -X POST https://api.mailhub.com/api/v2/orders \
-H "Authorization: Bearer $MAILHUB_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"order": {
"toAddress": { "name": "John Doe", "street1": "123 Main St",
"city": "Springfield", "state": "IL",
"zip": "62701", "country": "US" },
"shipments": [ { "parcel": { "weight": 2.5 } } ]
}
}'import os, requests
response = requests.post(
"https://api.mailhub.com/api/v2/orders",
headers={
"Authorization": f"Bearer {os.environ['MAILHUB_ACCESS_TOKEN']}",
"Content-Type": "application/json",
},
json={
"order": {
"toAddress": {
"name": "John Doe", "street1": "123 Main St",
"city": "Springfield", "state": "IL",
"zip": "62701", "country": "US",
},
"shipments": [{"parcel": {"weight": 2.5}}],
}
},
)
for rate in response.json()["data"]["shipmentRates"][0]["rates"]:
print(rate["carrier"], rate["serviceName"], rate["rate"])Written from the documented request contract and not yet run against a live endpoint.
const response = await fetch("https://api.mailhub.com/api/v2/orders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MAILHUB_ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
order: {
toAddress: {
name: "John Doe", street1: "123 Main St",
city: "Springfield", state: "IL",
zip: "62701", country: "US",
},
shipments: [{ parcel: { weight: 2.5 } }],
},
}),
});
const { data } = await response.json();
data.shipmentRates[0].rates.forEach((r) => console.log(r.carrier, r.serviceName, r.rate));Written from the documented request contract and not yet run against a live endpoint.
<?php
$payload = [
'order' => [
'toAddress' => [
'name' => 'John Doe', 'street1' => '123 Main St',
'city' => 'Springfield', 'state' => 'IL',
'zip' => '62701', 'country' => 'US',
],
'shipments' => [['parcel' => ['weight' => 2.5]]],
],
];
$ch = curl_init('https://api.mailhub.com/api/v2/orders');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('MAILHUB_ACCESS_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = json_decode(curl_exec($ch), true);
foreach ($body['data']['shipmentRates'][0]['rates'] as $rate) {
echo $rate['carrier'], ' ', $rate['serviceName'], ' ', $rate['rate'], PHP_EOL;
}Written from the documented request contract and not yet run against a live endpoint.
{
"success": true,
"data": {
"status": "created",
"order": { ... },
"shipmentRates": [
{
"shipmentId": "8f2c...",
"rates": [
{
"id": "a1b2c3d4-0000-0000-0000-000000000001",
"carrier": "USPS",
"serviceName": "USPS Priority Mail",
"rate": 7.35,
"currency": "USD",
"deliveryDays": 2,
"estimatedDeliveryDate": "2026-04-04T23:59:59Z",
"deliveryDateGuaranteed": false
},
{
"id": "b2c3d4e5-0000-0000-0000-000000000002",
"carrier": "FedEx",
"serviceName": "FedEx Ground",
"rate": 9.12,
"currency": "USD"
}
]
}
],
"errors": []
},
"errors": null
}ratedeliveryDays and estimatedDeliveryDatedeliveryDateGuaranteed| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/auth/token | Exchange an API key for an access token |
| POST | /v1/auth/token/refresh | Get a new token pair |
| POST | /v2/orders | Create an order and return carrier rates |
| POST | /v1/orders | Create an order |
| GET | /v1/orders | List orders, paginated and filterable |
| POST | /v1/shipments/{shipmentId}/rates | Get carrier rate quotes |
| POST | /v1/shipments/{shipmentId}/labels | Buy a shipping label |
| GET | /v1/labels/{labelId}/download | Download the label as a PDF or ZPL file |
| DELETE | /v1/labels/{labelId} | Void a label |
| Comparison criteria | Mailhub Shipping API | Carrier APIs direct |
|---|---|---|
| Integrations to build | One | One per carrier |
| Response format | Same shape for every carrier | Different for each carrier |
| Adding a carrier | Nothing to build | A new integration to write and maintain |
| Carrier accounts needed | None | One contract per carrier |
| Discounted rates | Returned on every quote, from your first call | Only once you qualify and negotiate |
| Delivery estimates | Included when the carrier returns one | Varies by carrier, sometimes a separate call |
| Cost | Free to call, pay per label | Free to call, at your contracted rates |
Three calls gets you a label. Authenticate, create the order, buy the label, and rates come back with the order rather than needing a separate request. Because every carrier returns in the same shape, adding one later costs you nothing in code.
Calls are free. You pay per label at the discounted carrier rate, with no monthly platform fee and no minimum volume, so you can build and test the whole integration before any commercial conversation.
No. Mailhub’s negotiated rates with USPS, FedEx and DHL are available from your first call. There is nothing to sign with the carriers.
Yes. Order, rate and label calls all take an X-SubAccount-Id header, so each client’s orders and labels sit under their own sub-account through a single integration.