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 
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)