Update & Delete Add-ons
Correct an add-on's content, publish or unpublish it, or remove it.
Update
PUT /api/v3/content/{content}/add-ons/{id}
Updates are partial: only the fields present in the payload are validated and written. Updating a title never blanks the type, position or any other field you did not send.
The verb is PUT, but the semantics are a merge, not a replacement: fields absent from the payload are left untouched rather than cleared. If you read this as strict REST, PATCH is the behaviour you should expect.
Request Body
Any subset of the creation fields:
| Field | Notes |
|---|---|
title, body, type | Same rules as creation; when present they cannot be null. body is sanitized on save |
status | draft or published. Publish a draft or pull a published add-on back to draft |
start_page, end_page | end_page is validated against the stored start_page when only one of the two is sent |
location_in_start_page | Same {x, y} format and validation as creation; send null to remove the marker |
anchor | Re-anchors the piece. Complete when present: the type and page always, the coordinates of a point. Not accepted together with start_page or location_in_start_page, and not nullable |
image_from_url | Downloads, validates and stores a new image, replacing image_url. Cannot be null |
pretitle, author, by_line, image_caption | Same rules as creation; send null to clear one |
source, body_format | Not accepted. Both are set by the system. Sending either returns 422 |
Clearing a field and omitting it are different: an omitted key is left as it is, an explicit null writes null. Only the fields marked nullable above accept it. title, body, type, status, start_page, end_page and anchor are required columns or positions, so null on any of those returns 422.
There is no way to remove an add-on's image through this API. image_url is a response field and is rejected if you send it, and image_from_url only accepts a URL, so a null there returns 422 rather than answering 200 to a clear it would not perform. Replace the image by sending a new image_from_url. To remove one entirely, use the dashboard editor.
Re-anchoring
Sending an anchor replaces the position whole, and the page range follows it: end_page collapses onto the anchor's page unless the same payload names another end. A piece is never left spanning the pages it used to sit on.
curl -X PUT "https://yourstore.publica.la/api/v3/content/456/add-ons/1044" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{ "anchor": { "type": "page", "page": 22 } }'
An anchor that travels must be complete: { "anchor": { "type": "page" } } is refused under errors.anchor.page rather than storing a position with no page. An explicit "anchor": null is refused too. Removing a position is not part of the contract, re-anchoring is.
A piece the reader anchored to a passage or a figure keeps that anchor when an update moves only its page: the page changes, the selection stays. Moving such a piece through start_page on a fixed-layout EPUB drops the locator of the page it left, which is why the anchor is the way to move it.
Moving a position (start_page, end_page or anchor) needs the publication's page count, so an update that carries any of them answers 422 while a PDF is still converting, or on an EPUB the platform has not numbered. Every other field stays editable meanwhile. On a publication that takes no add-ons at all (an audiobook holding a record created before the format rule) the same update answers 422 with Add-ons are only supported on PDF and EPUB publications.
Example: publish a draft
curl -X PUT "https://yourstore.publica.la/api/v3/content/123/add-ons/1044" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{ "status": "published" }'
200 OK with the updated add-on object under data. When the payload carried a body, the response also carries sanitization.discarded with what the sanitizer removed; a body that sanitizes to nothing is refused with 422 under errors.body and the stored body is kept.
Delete
DELETE /api/v3/content/{content}/add-ons/{id}
Deletes the add-on and its stored image. Readers stop seeing it immediately.
curl -X DELETE "https://yourstore.publica.la/api/v3/content/123/add-ons/1044" \
-H "X-User-Token: your-api-token"
204 No Content on success.
Errors
| Status | Condition |
|---|---|
401 | Missing or invalid X-User-Token |
403 | Add-ons feature not enabled, non-administrator token, or the publication is not owned by your store |
404 | Publication or add-on not found, or the add-on belongs to a different publication than the URL claims |
422 | Validation failure (see creation errors), or source/body_format provided |
429 | Rate limit exceeded (20 requests per minute, shared with create) |