Content API v1 → v3 Migration Guide and Comparison
Overview
This document compares Content API v1 and v3 and provides a practical migration guide for integrators. The v3 feed is designed for speed, bandwidth efficiency, and flexibility via cursor pagination and response shaping (fields and includes).
- Reference v3 guide: Content API v3
- Reference v1 guide: Content API v1
At-a-Glance Comparison
| Topic | v1 | v3 |
|---|---|---|
| Base path | GET /integration-api/v1/dashboard/issues | GET /api/v3/content |
| Auth | API token in query string | API token in X-User-Token header or request body (no query string) |
| Pagination | Page-based paginator (page, last_page, etc.) | Cursor pagination with links.next/links.prev and meta.has_more |
| Search/filter | Overloaded query param (state, name, id) | Structured filters: filter[query], filter[external_id], filter[created_at], filter[updated_at] |
| Date filters | N/A | Strict ranges, 1-month span rules, format YYYY-MM-DD HH:mm:ss |
| Sorting | Not standardized | sort on created_at/updated_at |
| Shaping | Not supported | include blocks (prices, description, metadata) + fields selection |
| Prices shape | Object keyed by currency (e.g., { "USD": 25 }) | Array of objects ([{ "currency_id": "USD", "amount": 25 }]) |
| Timestamps | Mixed structures (e.g., published_at.timestamp + date) | ISO 8601 strings (e.g., published_at: "2019-09-13T00:00:00Z") |
| Cover URL | cover_image_path | cover_url |
| Error handling | JSON with CODE and payload | Same CODE with improved message |
Breaking Changes for Integrators
- Endpoint change:
GET /integration-api/v1/dashboard/issues→GET /api/v3/content. - Pagination: switch from page-based to cursor-based.
- No numeric
pageparameter. - Use
links.nexttoken and checkmeta.has_more.
- No numeric
- Filters: the overloaded
queryparameter is deprecated in v3.- Use
filter[query]for free-text search by title/name. - Use
filter[external_id]for exact ISBN/external ID matches. - Use
filter[updated_at][from|to]orfilter[created_at][from|to]with strict 1-month span rules andYYYY-MM-DD HH:mm:ssformat.
- Use
- Sorting: v3 introduces
sortwith allowed fieldscreated_at,updated_at(prefix with-for descending). - Response shaping:
- Use
include=prices,description,metadatato request optional blocks. - Use
fields=to trim the returned attributes for bandwidth efficiency.
- Use
- Schema differences:
cover_image_path(v1) →cover_url(v3).published_atstructure (v1 object) → ISO 8601 string (v3).prices(v1 object by currency) →prices(v3 array of{currency_id, amount}).free(v1 boolean) →free(v3 object:{enabled, until, require_login}).- New optional blocks:
description,metadata(withpublisher,author,bisac,keywords,metrics).
- Validation: invalid includes or parameters return 422 with detailed error messages in v3.
Response Differences
v1 (example excerpt)
{
"CODE": "success",
"data": {
"paginator": {
"current_page": 1,
"data": [
{
"id": 468166,
"external_id": "9781496822482",
"name": "Conversations with Donald Hall",
"cover_image_path": "https://.../cover.jpg",
"free": false,
"prices": { "USD": 25 }
}
],
"last_page": 6
}
}
}
v3 (example excerpt)
{
"data": [
{
"id": 468166,
"external_id": "9781496822482",
"name": "Conversations with Donald Hall",
"file_type": "epub",
"cover_url": "https://.../468166.jpg",
"published_at": "2019-09-13T00:00:00Z",
"license": "retail",
"free": { "enabled": false, "until": "2025-12-12T00:00:00Z", "require_login": false },
"preview": { "enabled": true, "require_login": false }
}
],
"links": { "next": "https://.../content?cursor=abc123&per_page=100", "prev": null },
"meta": { "has_more": true }
}
Prices shape
// v1
{"prices": {"USD": 9.99, "EUR": 8.50}}
// v3
{"prices": [{"currency_id": "USD", "amount": 9.99}, {"currency_id": "EUR", "amount": 8.50}]}
Migration Checklist
- Authentication
- Keep using your store API token.
- For v3, send it in the
X-User-Tokenheader over HTTPS.
- Endpoints
- Replace v1 listing endpoint with
GET /api/v3/content.
- Replace v1 listing endpoint with
- Pagination
- Implement cursor pagination.
- Use
links.nextfor the next request andmeta.has_moreto detect completion.
- Filters
- Replace
querywithfilter[query]. - Use
filter[external_id]for ISBN/external ID lookups. - Add date-windowed sync via
filter[updated_at]orfilter[created_at]with the 1‑month rules.
- Replace
- Sorting
- Add
sortwhen you need ordering other than the default (published_atdesc).
- Add
- Response shaping
- Add
include=for optional blocks (prices,description,metadata). - Trim with
fields=to reduce payloads.
- Add
- Schema updates
- Map
cover_image_path→cover_url. - Map
pricesobject →pricesarray. - Update timestamp parsing to ISO 8601 strings.
- Handle
freeandpreviewobjects.
- Map
- Error handling
- Handle 422 validation errors (e.g., invalid includes, date formats, ranges) and 401 for auth.
- Rollout
- Run v1 and v3 in parallel behind a feature flag.
- Monitor logs and payload sizes; switch traffic when stable.
Practical Examples
Minimal listing with search (v3)
GET /api/v3/content?filter[query]=harry&per_page=100 HTTP/1.1
Host: {store_final_domain}
X-User-Token: sk_live_xxx
Incremental sync by update date (v3)
GET /api/v3/content?filter[updated_at][from]=2024-12-25 00:00:00&filter[updated_at][to]=2024-12-31 23:59:59&sort=-updated_at HTTP/1.1
Host: {store_final_domain}
X-User-Token: sk_live_xxx
Shape response with fields and includes (v3)
GET /api/v3/content?include=prices,description&fields=id,name,description,prices&per_page=100 HTTP/1.1
Host: {store_final_domain}
X-User-Token: sk_live_xxx
Fetch by ISBN/external_id (v3)
GET /api/v3/content?filter[external_id]=9781496822482 HTTP/1.1
Host: {store_final_domain}
X-User-Token: sk_live_xxx
Troubleshooting FAQ
- How do I request a single item in v3?
- Use
filter[external_id]to retrieve an exact match by ISBN/external reference.
- Use
- What page size should I use?
- v3 supports
per_pagefrom 1 to 500 (default 100). Use higher values for faster syncs when appropriate.
- v3 supports
- Why am I getting a 422 error?
- Check date formats/ranges, allowed includes (
prices,description,metadata), andper_pagebounds.
- Check date formats/ranges, allowed includes (
- Do I have to include metadata?
- No. Only request
include=metadatawhen you need it. Trim withfieldsto keep responses small.
- No. Only request
References
- v3 Reference: Content API v3
- v1 Reference: Content API v1 (Deprecated)