Skip to main content

Bulk Create Add-ons

Create up to 100 add-ons on one publication in a single request. Bulk items are pure database writes: attach images through the single add-on endpoints.

Endpoint

POST /api/v3/content/{content}/add-ons/bulk

{content} is the publication's internal ID, or any of its identifiers with id_type=external. The publication must be a PDF or an EPUB, and numbered (422 otherwise, with the reasons listed in the overview).

Each item names its position the same way a single create does: start_page (plus an optional location_in_start_page) on a PDF, or an anchor on either format. On an EPUB an item without an anchor fails on its own, with An add-on on an EPUB publication must carry an anchor. under its index. The rest of the batch is still written.


Request Body

FieldTypeRequiredDescription
add_onsarrayYes1 to 100 add-on objects, same fields as single creation except image_from_url, which bulk items reject

Limits

LimitValue
Maximum add-ons per request100
Minimum add-ons per request1
Requests per minute10

Per-item validation

Each item is validated individually: an invalid item is reported in errors with its index and never aborts the rest of the batch.

There is one exception, and it is about shape rather than field values: if any entry of add_ons is not a JSON object, the whole request is rejected with 422 before any item is processed and nothing is created. add_ons itself must also be a JSON array. An object keyed by strings is rejected the same way, because the index correlation depends on it. Once every entry is a well-formed object, an invalid field inside one only ever affects that one.


Request Example

curl -X POST "https://yourstore.publica.la/api/v3/content/123/add-ons/bulk" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"add_ons": [
{ "title": "Front page piece", "body": "<p>…</p>", "start_page": 1 },
{ "title": "Center spread", "body": "<p>…</p>", "start_page": 8, "status": "published" },
{ "title": "Back page piece", "body": "<p>…</p>", "start_page": 32 },
{ "title": "Piece in an EPUB", "body": "<p>…</p>", "anchor": { "type": "page", "page": 14 } }
]
}'

Response

200 OK with a per-batch summary:

{
"data": {
"total": 3,
"created": 2,
"failed": 1,
"add_ons": [
{
"index": 0,
"id": "1044",
"title": "Front page piece",
"status": "draft",
"discarded": []
},
{
"index": 1,
"id": "1045",
"title": "Center spread",
"status": "published",
"discarded": [
{ "node": "h2", "reason": "tag_not_allowed", "detail": null }
]
}
],
"errors": [
{
"index": 2,
"errors": {
"start_page": ["The start page field must be at least 1."]
}
}
]
}
}
  • add_ons carries one entry per created piece, each with the zero-based index of the item that produced it. Match on index rather than on position: it is the only correlation between a returned id and your own record.
  • errors carries one entry per failed item, with the same zero-based index. The key is omitted when every item succeeds.
  • discarded on each created item lists what the body sanitizer removed from that item's body. An item whose body sanitizes to nothing fails on its own: it joins errors under body, with its discarded list, and its neighbours are still created.

Batches are not atomic

A 500 means an unexpected failure (storage, database), not a rejected item. Items processed before it stay created, and the response carries no summary telling you which ones. Retrying the same batch re-creates them, because the endpoint has no idempotency key yet. After a 500, list the publication's add-ons and reconcile before retrying.

Errors

StatusCondition
401Missing or invalid X-User-Token
403Add-ons feature not enabled, non-administrator token, or the publication is not owned by your store
404Publication not found
422add_ons missing, empty or over 100 items; the publication takes no add-ons, or is not numbered yet
500Unexpected failure. Earlier items stay created (see above)
429Rate limit exceeded (10 bulk requests per minute)
X

Graph View