Skip to main content

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

At-a-Glance Comparison

Topicv1v3
Base pathGET /integration-api/v1/dashboard/issuesGET /api/v3/content
AuthAPI token in query stringAPI token in X-User-Token header or request body (no query string)
PaginationPage-based paginator (page, last_page, etc.)Cursor pagination with links.next/links.prev and meta.has_more
Search/filterOverloaded query param (state, name, id)Structured filters: filter[query], filter[external_id], filter[created_at], filter[updated_at]
Date filtersN/AStrict ranges, 1-month span rules, format YYYY-MM-DD HH:mm:ss
SortingNot standardizedsort on created_at/updated_at
ShapingNot supportedinclude blocks (prices, description, metadata) + fields selection
Prices shapeObject keyed by currency (e.g., { "USD": 25 })Array of objects ([{ "currency_id": "USD", "amount": 25 }])
TimestampsMixed structures (e.g., published_at.timestamp + date)ISO 8601 strings (e.g., published_at: "2019-09-13T00:00:00Z")
Cover URLcover_image_pathcover_url
Error handlingJSON with CODE and payloadSame CODE with improved message

Breaking Changes for Integrators

  1. Endpoint change: GET /integration-api/v1/dashboard/issuesGET /api/v3/content.
  2. Pagination: switch from page-based to cursor-based.
    • No numeric page parameter.
    • Use links.next token and check meta.has_more.
  3. 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] or filter[created_at][from|to] with strict 1-month span rules and YYYY-MM-DD HH:mm:ss format.
  4. Sorting: v3 introduces sort with allowed fields created_at, updated_at (prefix with - for descending).
  5. Response shaping:
    • Use include=prices,description,metadata to request optional blocks.
    • Use fields= to trim the returned attributes for bandwidth efficiency.
  6. 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 (with publisher, author, bisac, keywords, metrics).
  7. 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

  1. Authentication
    • Keep using your store API token.
    • For v3, send it in the X-User-Token header over HTTPS.
  2. Endpoints
    • Replace v1 listing endpoint with GET /api/v3/content.
  3. Pagination
    • Implement cursor pagination.
    • Use links.next for the next request and meta.has_more to detect completion.
  4. Filters
    • Replace query with filter[query].
    • Use filter[external_id] for ISBN/external ID lookups.
    • Add date-windowed sync via filter[updated_at] or filter[created_at] with the 1‑month rules.
  5. Sorting
    • Add sort when you need ordering other than the default (published_at desc).
  6. Response shaping
    • Add include= for optional blocks (prices, description, metadata).
    • Trim with fields= to reduce payloads.
  7. Schema updates
    • Map cover_image_pathcover_url.
    • Map prices object → prices array.
    • Update timestamp parsing to ISO 8601 strings.
    • Handle free and preview objects.
  8. Error handling
    • Handle 422 validation errors (e.g., invalid includes, date formats, ranges) and 401 for auth.
  9. 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.
  • 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), 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.

References

X

Graph View