Migrating from create-article
The legacy POST /integration-api/v1/create-article endpoint is deprecated and will be sunset. The Add-ons API v3 replaces it with a complete resource: listing, creation (single and bulk), correction, deletion and a review lifecycle.
At-a-Glance Comparison
| Feature | v1 create-article | Add-ons API v3 |
|---|---|---|
| Base path | POST /integration-api/v1/create-article | /api/v3/content/{content}/add-ons |
| Authentication | X-User-Token header | X-User-Token header (unchanged) |
| Operations | Create only | List, create, bulk create, update, delete |
| Publication ref | issue_id in the body | {content} in the path (internal or external id) |
| Review lifecycle | None. Always visible immediately | draft (default) / published |
| Provenance | Not recorded | Stamped internally from the creation channel |
| Body sanitization | Stored as sent | Sanitized to a fixed HTML subset; removals reported |
| Bulk | Sequential requests | Dedicated bulk endpoint, up to 100 items (without images) |
| Marker position | Accepted without validation | Validated {x: 0-100, y: 0-100}; malformed input rejected |
| Image input | image_from_url, unvalidated download | image_from_url, validated (JPEG/PNG/GIF/WebP, max 10 MB) |
| Ownership check | None | Only the content owner manages add-ons |
| Response | { "CODE": "success", "data": {…} } | Standard v3 envelope { "data": {…} } |
Breaking Changes
1. The publication moves from body to path
- POST /integration-api/v1/create-article
- { "issue_id": 123, "title": "…", … }
+ POST /api/v3/content/123/add-ons
+ { "title": "…", … }
External identifiers work in the path with ?id_type=external.
2. New add-ons default to draft
create-article made every article visible to readers instantly. The v3 resource creates drafts by default. To keep the old publish-immediately behavior, pass:
{ "status": "published" }
3. Marker positions are validated
location_in_start_page was stored as-is, and malformed values put the marker at the page border instead of where intended. v3 rejects anything that is not { "x": 0-100, "y": 0-100 } with 422.
4. Images are validated on download
URLs that do not point to a real JPEG, PNG, GIF or WebP under 10 MB are rejected with 422 instead of failing later in the image pipeline.
5. Response envelope
- { "CODE": "success", "data": { … } }
+ { "data": { … } }
The v3 add-on object exposes new fields (status, content_id) and ISO 8601 timestamps. See the add-on object.
6. PDF and EPUB publications only
create-article accepted any issue_id. v3 creates add-ons on PDF and EPUB publications that are numbered (a PDF by its finished conversion, an EPUB by its page markers), because every position is validated against the publication's page count (422 otherwise, with the reason under errors.content). An EPUB is addressed with an anchor; create-article has no way to send one, so it stays a PDF-only path.
7. Feature flag and administrator token
The v3 resource requires the Add-ons API feature enabled for your store and a token belonging to an administrator user (403 otherwise). The feature gates only this API; managing add-ons manually from the dashboard never requires it. Contact support before migrating.
8. Bodies are sanitized
create-article stores body as sent. v3 always runs it through the rich text sanitizer: event handlers, inline styles, scripts, tables and unknown tags are removed, headings are flattened to paragraphs, and the response lists every removal under sanitization.discarded. If your articles rely on <h2>–<h4> structure, expect it to come back as paragraphs.
Field Mapping
| v1 field | v3 field | Notes |
|---|---|---|
issue_id | {content} path segment | Or an external identifier with id_type=external |
title | title | Unchanged |
pretitle | pretitle | Unchanged |
body | body | Same length limit; now sanitized on save |
author | author | Unchanged |
by_line | by_line | Now validated (max 1,000) |
type | type | Same values, defaults to article |
start_page / end_page | start_page / end_page | Unchanged semantics |
location_in_start_page | location_in_start_page | Now validated |
| (none) | anchor | New. Derived from the pair above when you send the legacy fields, so a PDF migration needs no change; required to place a piece in an EPUB |
image_from_url | image_from_url | Now validated |
image_caption | image_caption | Now validated (max 2,000) |
| (none) | status | New: draft (default) or published |
| (none) | source | Not part of the contract: provenance is stamped internally from the creation channel |
| (none) | body_format | New, read-only: html once a body went through the sanitizer |
Side-by-Side Example
v1:
curl -X POST "https://yourstore.publica.la/integration-api/v1/create-article" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"issue_id": 123,
"title": "Interview with the author",
"body": "<p>…</p>",
"start_page": 12
}'
v3:
curl -X POST "https://yourstore.publica.la/api/v3/content/123/add-ons" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"title": "Interview with the author",
"body": "<p>…</p>",
"start_page": 12,
"status": "published"
}'