Quick start
Three steps from zero to a printed label. Bearer-token auth, one rate-then-buy round-trip, label PDF in hand.
1. Sign up + create a token
Sign up at shiponline.app (free, no card required) and visit Settings → API tokens to mint a token. Tokens carry scopes; the simplest one is write:shipments, which is enough to quote rates and buy labels. The token is shown once on creation — copy it before you navigate away.
Token format
shp_test_… in test mode and shp_live_…in production. Both are 64 characters after the prefix and behave identically; the prefix tells you which mode is in scope, so it's safe to log + paste into secrets management.2. Quote rates
Every label starts with a rate fetch. POST /api/v1/labels/quote takes a sender address, a recipient address, and a parcel; it returns one or more carrier rates sorted by price. You can pick any of the returned rates and pass its rateId to the buy endpoint.
curl -X POST https://shiponline.app/api/v1/labels/quote \
-H "Authorization: Bearer shp_test_..." \
-H "Content-Type: application/json" \
-d '{
"fromAddress": {
"street1": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip": "94103",
"country": "US"
},
"toAddress": {
"street1": "350 Fifth Avenue",
"city": "New York",
"state": "NY",
"zip": "10118",
"country": "US"
},
"parcel": {
"lengthIn": 10,
"widthIn": 8,
"heightIn": 4,
"weightOz": 16
}
}'Example response
{
"providerShipmentId": "shp_AAA...",
"rates": [
{
"rateId": "rate_BBB...",
"carrier": "USPS",
"service": "Priority",
"serviceCategory": "express",
"shippingCents": 820,
"platformFeeCents": 8,
"customerPriceCents": 828,
"estDeliveryDays": 2,
"estDeliveryDate": "2026-06-29"
},
...
]
}What each field means. rateId is the identifier you pass to /labels/create. customerPriceCents is what your account will be charged in cents. shippingCents is the shipping portion of that total; platformFeeCents is the explicit per-label API fee ($0.08 = 8 cents) broken out so you can itemise on your own receipts (the two always sum to customerPriceCents). serviceCategory is one of standard, express, overnight, or international for smart-rate filtering.
3. Buy a label
Hand the chosen rateId back through POST /api/v1/labels/create. The endpoint reuses the provider-side shipment you got from the quote, so you don't re-send addresses. The response is HTTP 202 Acceptedwith the new label's id + a status of paying while the carrier processes the purchase asynchronously.
curl -X POST https://shiponline.app/api/v1/labels/create \
-H "Authorization: Bearer shp_test_..." \
-H "Content-Type: application/json" \
-d '{
"rateId": "rate_BBB...",
"idempotencyKey": "order-12345"
}'Response shape (202)
{
"id": "lbl_CCC...",
"status": "paying",
"carrier": "USPS",
"service": "Priority",
"trackingNumber": null,
"labelUrl": null,
"chargeAmountCents": 828
}Idempotency keys are required on buy
/labels/create call requires a stable idempotencyKey in the body. Use the customer order id or anything else that stays consistent across retries — a duplicate call with the same key returns the same label instead of double-charging. See Errors → Idempotency for the full semantics.4. Wait for the carrier (or subscribe to webhooks)
The label takes 2–10 seconds to print on the carrier side after you call /labels/create. You have two ways to find out when it's ready:
- Poll
GET /api/v1/labels/<id>untilstatusbecomespurchased. The response will then containlabelUrl(a 24h carrier-hosted PDF) andtrackingNumber. - Subscribe to webhooks and listen for the
shipment.purchasedevent. Recommended for production — see Webhooks.
Most production integrations subscribe to shipment.purchased + shipment.failed and only fall back to polling on missed deliveries.
What to read next
- Authentication — scopes, rotation, test vs live mode.
- Labels — the full Create / Get / List / Refund reference.
- Webhooks — event types, signature verification, replay protection.
- Errors — status codes, retry semantics, idempotency edge cases.