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_v3.md
- Reference v1 guide: content.md
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
page
parameter. - Use
links.next
token and checkmeta.has_more
.
- No numeric
- Filters: the overloaded
query
parameter 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:ss
format.
- Use
- Sorting: v3 introduces
sort
with allowed fieldscreated_at
,updated_at
(prefix with-
for descending). - Response shaping:
- Use
include=prices,description,metadata
to request optional blocks. - Use
fields=
to trim the returned attributes for bandwidth efficiency.
- Use
- Schema differences:
cover_image_path
(v1) →cover_url
(v3).published_at
structure (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-Token
header over HTTPS.
- Endpoints
- Replace v1 listing endpoint with
GET /api/v3/content
.
- Replace v1 listing endpoint with
- Pagination
- Implement cursor pagination.
- Use
links.next
for the next request andmeta.has_more
to detect completion.
- Filters
- Replace
query
withfilter[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
sort
when you need ordering other than the default (published_at
desc).
- 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
prices
object →prices
array. - Update timestamp parsing to ISO 8601 strings.
- Handle
free
andpreview
objects.
- 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_page
from 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_page
bounds.
- Check date formats/ranges, allowed includes (
- Do I have to include metadata?
- No. Only request
include=metadata
when you need it. Trim withfields
to keep responses small.
- No. Only request
References
- v3 Reference: Content API v3
- v1 Reference: Content API v1 (Deprecated)