Migration Guide: Content API v1 → v3
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).
Related Documentation:
Endpoint Mapping
Content CRUD
| Operation | v1 Endpoint | v3 Endpoint |
|---|---|---|
| List | GET /integration-api/v1/dashboard/issues | GET /api/v3/content |
| Get single | GET /integration-api/v1/dashboard/issues/{id} | GET /api/v3/content/{id} |
| Create | POST /integration-api/v1/dashboard/issues | POST /api/v3/content |
| Bulk create | N/A | POST /api/v3/content/bulk |
| Update | PUT /integration-api/v1/dashboard/issues/{id} | PUT /api/v3/content/{id} |
| Delete | DELETE /integration-api/v1/dashboard/issues/{id} | DELETE /api/v3/content/{id} |
Audiobook Tracks
| Operation | v1 Endpoint | v3 Endpoint |
|---|---|---|
| List tracks | GET /integration-api/v1/dashboard/issues/{id}/tracks | GET /api/v3/content/{id}/tracks |
| Add track | POST /integration-api/v1/dashboard/issues/{id}/tracks | POST /api/v3/content/{id}/tracks |
| Update track | PUT /integration-api/v1/dashboard/issues/{id}/tracks/{track} | PUT /api/v3/content/{id}/tracks/{track} |
| Reorder tracks | PUT /integration-api/v1/dashboard/issues/{id}/tracks-orders | PUT /api/v3/content/{id}/tracks/order |
| Delete track | DELETE /integration-api/v1/dashboard/issues/{id}/tracks/{track} | DELETE /api/v3/content/{id}/tracks/{track} |
At-a-Glance Comparison
| Topic | v1 | v3 |
|---|---|---|
| Base path | /integration-api/v1/dashboard/issues | /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,country,edition,narrator,category,collection,metrics),geographic_restrictions.
- 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 GET /api/v3/content/{id} for direct lookup. Supports both internal and external IDs via the id_type parameter.
What's the difference between filter[external_id] and id_type=external?
filter[external_id]on list endpoint returns items matching that IDid_type=externalon single-item endpoints (GET,PUT,DELETE) allows using external ID in the path
What page size should I use?
v3 supports per_page from 1 to 500 (default 100). Use higher values for faster syncs when appropriate.
Why am I getting a 422 error?
Check date formats/ranges, allowed includes (prices, description, metadata, geographic_restrictions), and per_page bounds.
Do I have to include metadata?
No. Only request include=metadata when you need it. Trim with fields to keep responses small.
How do I migrate bulk imports to v3?
Use POST /api/v3/content/bulk with up to 100 items per request. The response includes partial success handling with detailed errors for any failed items.
Can I still use the old v1 endpoints? Yes, v1 endpoints remain available during the migration period. We recommend starting with v3 for new integrations.
What about audiobook track endpoints?
Track endpoints have moved from /issues/{id}/tracks-orders to /content/{id}/tracks/order. The structure is otherwise similar.
See Also
- Content API v3 Overview
- List Content
- Get Content
- Create Content
- Bulk Operations
- Update Content
- Delete Content
- Audiobook Tracks
- Content API v1 (Deprecated)