Skip to main content
Reporting API is an API to export your Shippo account data as files. Reports run asynchronously: create a run, poll until it reaches SUCCEEDED, then download the file. Authenticate with a Shippo API token.

Create a run

POST /v2/reporting/runs returns right away with status: QUEUED and a run id. Reporting API builds the file in the background. The interval is the only way to scope a report. It bounds the run to a UTC date range. Unknown body fields return 422. The interval must fall inside the report type’s data_availability window. An out-of-window interval returns 404 data-unavailable. See Discover report types for columns and availability.
201 Created:
Keep the id. You need it to poll and download.

Safe retries

Use idempotency_key to make creates safe to retry. The key is your own string, so pick one per run you intend to create.
  • No key, or a new key you haven’t used: 201 Created, a brand-new run.
  • The same key with the same request body: 200 OK, the existing run handed back. Resend after a network blip and you won’t get a duplicate.
  • The same key with a different request body: 409 with type segment idempotency-conflict. Use a fresh key for a different run.
Without a key, every create makes a new run. There’s no automatic deduplication. If create returns a transient 503 service-unavailable, resend the same request.

Poll status

There’s no webhook. Poll GET /v2/reporting/runs/{run_id} until status is terminal.
Poll until the run reaches SUCCEEDED or FAILED. An unknown run id returns 404 run-not-found. To list your recent runs, use GET /v2/reporting/runs (limit defaults to 50, range 1 to 500).

Handle a run with status: SUCCEEDED

Download the file with a GET request to result.download.url; a Shippo Authorization header is not required. If download.status is unavailable, fetch the run again to request a new URL.
The download URL is time-limited. The expires field contains its expiry as a UTC epoch second. If it expires, fetch the run again for a new URL.

Handle a run with status: FAILED

A run with status: FAILED returns HTTP 200 with status: FAILED, not an HTTP error. It also carries completed and an error object. A timeout is a FAILED run, not a separate state.

HTTP errors

Reporting API errors use application/problem+json with type, title, status, and detail, except authentication failures, which use 401 application/json with a detail field. Match problem responses on the trailing segment of type, since its host can change without changing the error code.

Next steps

Discover report types

Read columns and the data-availability window before creating a run.

Reporting API reference

Full request and response schemas for every endpoint.
Last modified on September 16, 2026