Skip to main content
Reporting API turns your Shippo account data into downloadable CSV or Parquet files. Reports run asynchronously, so you create a run, poll until it finishes, then download the file. All endpoints live under https://api.goshippo.com/v2/reporting. Pass Authorization: ShippoToken <API_TOKEN> on every request. See the Authentication guide for token setup. All timestamps are integer UTC epoch seconds.

1. Discover a report type

A report type is a predefined report identified by a versioned key like invoice.v1. List the catalog:
This abbreviated response shows one report type and three of its available columns:
Two fields drive how you build a run:
  • The available_columns field lists the column names you can request. Submit each column’s name. Omit columns on create and you get the report’s default set.
  • The data_availability field tells you the window you can query. When status is ready, your interval must fall inside the start and end window, and updated shows when those bounds were last checked (UTC epoch seconds). When status is pending, a create request returns 404 data-unavailable.
To inspect a single report type, call GET /v2/reporting/reports/{report_type}.

2. Create a run

A run is one async execution of a report type over a time interval. Set interval to {start, end} in epoch seconds.
  • end must be strictly greater than start, or you get a 422.
  • A run can span up to 92 days. Going past a report type’s limit returns 400 invalid-parameter.
You get 201 Created with status: QUEUED. Keep the id; you need it to poll and download.
  • output_format accepts csv, csv_gzip (the default), or parquet.
  • columns is optional. If you include it, it can’t be empty.
  • Unknown body fields are rejected with 422.
Safe retries with idempotency_key. This field is optional: a string of 1 to 128 characters that you choose. Send a new key, or none at all, and you get 201 Created with a brand-new run. Retry with the same key and the same request body, and you get the original run back as 200 OK instead of a duplicate. Reuse a key with a different body and you get a 409 with the idempotency-conflict type. Without a key, every create makes a new run, so set one whenever a retry might fire twice.

3. Poll until the run finishes

A run moves through these states: Poll until the run reaches SUCCEEDED or FAILED.
A run with status: FAILED comes back as HTTP 200 with status: FAILED, not an HTTP error. Read error.code to handle it.
On failure, error.code is one of:

4. Download the file

On SUCCEEDED, result.download takes one of two shapes:
  • { "status": "available", "url": "...", "expires": <epoch_s> } means the file is ready. Send a GET request to url; a Shippo Authorization header is not required.
  • { "status": "unavailable" } means a signed URL is not currently available. Fetch the run again to obtain a new URL.
The URL is time-limited. Read its expires field for the exact cutoff. Fetch the run again to obtain a new URL and expiry.

List your runs

Runs come back newest-first. limit defaults to 50 and ranges from 1 to 500. List responses don’t include signed download URLs. GET a succeeded run by id to mint one.

Error reference

Reporting API 4xx and 5xx responses use application/problem+json, except authentication failures, which use 401 application/json with a detail field. Match problem responses on the last path segment of type, not its full URL.

Next steps

Reporting API reference

Full endpoint, schema, and field reference for every Reporting API call.

Authentication

How to generate and use your Shippo API token.
Last modified on September 16, 2026