Skip to main content

Update Content

Modify existing content items. Update metadata, pricing, access settings, files, or any other content attributes.


Endpoint​

PUT /api/v3/content/{content_id}

Path Parameters​

ParameterTypeDescription
content_idstringContent internal ID or external ID

Query Parameters​

ParameterTypeDefaultDescription
id_typestringinternalinternal for numeric ID, external for external ID
includestring-Comma-separated: prices, description, metadata, geographic_restrictions
fieldsstring-Comma-separated list of fields to return

Request Body​

All fields are optional. Only include fields you want to update. Omitted fields are left unchanged.

Array Replacement Behavior

All array and object fields use full replacement semantics. When you include an array field in the request, it replaces all existing values — including when you send an empty array [], which removes all existing values for that field.

For example, sending "keywords": [] will clear all keywords from the content item. Only include array fields you intend to update.

Core Fields​

FieldTypeDescription
namestringContent title (max 255 chars)
descriptionstringFull content description (HTML allowed)
published_atstringPublication date (YYYY-MM-DD only)
langstringLanguage code
audiencestringTarget audience
subtitlestringContent subtitle (max 255 chars)
publication_placestringPlace of publication (max 255 chars)
edition_yearintegerEdition year (4 digits, e.g., 2025)

File Update​

FieldTypeDescription
filestringStorage path to new content file (mutually exclusive with file_url)
file_urlstringExternal URL for new content file (mutually exclusive with file)
coverstringStorage path to new cover image (mutually exclusive with cover_url)
cover_urlstringExternal URL for new cover (mutually exclusive with cover)
File Upload Options
  • file_url / cover_url: Provide a publicly accessible URL. The platform will download the file automatically.
  • file / cover: Provide a storage path from SFTP upload. Contact support to enable SFTP access for your account.
File Replacement Behavior

When you update a content file, the platform creates a new version of the file. Previous versions are retained internally. The content will be re-processed after the file update, and the conversion_status will change to reflect the processing state. Only PDF and EPUB content types support file updates. For audiobooks, use the Audiobook Tracks API to manage audio files.

File Type Constraint

The replacement file must match the original content type. For example, you cannot replace a PDF with an EPUB. To change the content type, delete and recreate the content item.

Pricing​

FieldTypeDescription
pricesarrayComplete price array (replaces all prices)
Price Replacement

The prices array replaces all existing prices. Include all currencies you want to keep. Sending an empty array [] removes all prices.

Scheduled Pricing

Prices support starts_at and ends_at fields for scheduled pricing: [{currency_id, amount, starts_at, ends_at}]. Dates should be in YYYY-MM-DD format.

Access Settings​

FieldTypeDescription
freebooleanEnable/disable free access
free_untilstring|nullFree access expiration (YYYY-MM-DD or null to remove)
require_loginbooleanRequire login for free access
previewbooleanEnable/disable preview
preview_require_loginbooleanRequire login for preview

DRM Print Quota​

FieldTypeDescription
drm_print_limitinteger|nullMaximum number of pages a user can print in a single print job (0 to 100)
drm_print_lifetime_percentageinteger|nullMaximum percentage of the book's pages a user can print in total, across all print jobs (0 to 100)

See DRM Print Quota for the full semantics: the quota applies to pdf and epub content, and printing stays disabled unless both values are positive.

Updating the Print Quota

Each field follows partial-update semantics: an omitted field keeps its current value. Send both fields as null to remove the quota and disable printing. Quota changes take effect immediately and are not validated against pages users have already printed.

Subscribers-Only Access​

FieldTypeDescription
subscribers_onlybooleanRestrict purchase to users with an active plan

See Subscribers-Only Access for rules on the retail license interaction.

Marketplace​

FieldTypeDescription
show_in_marketplacebooleanMake content available in the Publica.la marketplace. When true, the content is listed for other tenants to discover and add to their stores. Send false to remove from marketplace.

Metadata​

FieldTypeDescription
authorarrayAuthor names: [{first_name, last_name?, title?}] (replaces all). See Author names
publisherarrayPublisher names (replaces all, max 200 chars each)
keywordsarrayKeywords (replaces all, max 200 chars each)
bisacarrayBISAC codes (replaces all, max 4 codes)
themaarrayThema subject codes (replaces all, strings max 200 chars each)
categoryarrayCategory names (replaces all, max 200 chars each)
collectionarrayCollection names (replaces all, max 200 chars each)
seriesarraySeries names (replaces all, max 200 chars each)
countryarrayCountry names (replaces all, max 200 chars each)
editionarrayEdition names (replaces all, max 200 chars each)
narratorarrayNarrator names (replaces all, max 200 chars each)
publishing_grouparrayPublishing group names (replaces all, max 200 chars each)
accessibility_featuresarrayAccessibility features (replaces all): [{code: "04", description?: "..."}] (code max 3 chars, description max 5000 chars)
custom_metadataobjectCustom taxonomy groups: {"group_slug": ["value1"]}. Sending {"group_slug": []} clears that group
share_with_tenants_idsarrayTenant IDs (strings) to share this content with. See Content Sharing
format_group_idsarrayFormat group IDs (strings) to associate this content with
pagesintegerNumber of pages (min: 0). Applies to any file_type. For PDF and audio content the value is derived from the file during processing; input is ignored for those types.

Geographic Restrictions​

FieldTypeDescription
geographic_restrictionsobject|null{included: [...], excluded: [...]} or null to remove

Identifiers​

FieldTypeDescription
identifiersarrayArray of identifier objects (replaces all, max 20)
identifiers[].typestringIdentifier type: isbn_digital, isbn_printed, uuid, ddc, external_id
identifiers[].valuestringIdentifier value (max 255 chars). Validated per type (e.g., ISBN-10/ISBN-13 checksum)
identifiers[].is_primarybooleanMark as primary identifier (optional, defaults to false)
Identifier Replacement Behavior

The identifiers array uses full replacement semantics, just like other array fields. Sending "identifiers": [] will remove all identifiers and clear external_id. Only include identifiers you want to keep. Omitting identifiers from the request preserves existing identifiers unchanged.

Uniqueness

Types isbn_digital, isbn_printed, uuid, and external_id require tenant-level uniqueness — two content items cannot share the same identifier of these types, regardless of which is primary. Only one identifier can be marked as primary. If none is marked, the first one is auto-promoted.

Physical Product Fields​

FieldTypeDescription
binding_typestringBinding type
heightfloatHeight in cm
widthfloatWidth in cm
weightfloatWeight in grams
stock_quantityintegerUnits available for sale (min: 0). 0 sells the product out and blocks purchases
editing_locationstringEditing/printing location
thicknessfloatThickness in cm (min: 0)

A product with no quantity is untracked: it stays on sale and nothing is enforced. Sending null, or omitting the field, leaves the product as it was, so this API can start tracking a product but cannot stop.


Request Examples​

Update Basic Information​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Book Title",
"description": "<p>Updated description with more details...</p>"
}'

Update by External ID​

curl -X PUT "https://yourstore.publica.la/api/v3/content/9781234567890?id_type=external" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Revised Edition",
"published_at": "2025-01-15"
}'

Update Pricing​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"prices": [
{ "currency_id": "USD", "amount": 24.99 },
{ "currency_id": "EUR", "amount": 21.99 },
{ "currency_id": "GBP", "amount": 19.99 }
]
}'

Enable Free Access​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"free": true,
"free_until": "2025-06-30",
"require_login": true
}'

Disable Free Access​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"free": false,
"free_until": null
}'

Set or Update the Print Quota​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"drm_print_limit": 15,
"drm_print_lifetime_percentage": 80
}'

Remove the Print Quota​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"drm_print_limit": null,
"drm_print_lifetime_percentage": null
}'

Update Metadata​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"author": [
{ "first_name": "Jane", "last_name": "Smith" },
{ "first_name": "John", "last_name": "Doe" }
],
"publisher": ["New Publisher Name"],
"keywords": ["updated", "keywords", "list"],
"bisac": [
{ "code": "FIC000000" },
{ "code": "FIC019000" }
]
}'

Update Cover Image​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"cover_url": "https://example.com/new-cover.jpg"
}'

Replace Content File​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://example.com/files/updated-book-v2.pdf"
}'

Replace Content File via SFTP​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"file": "uploads/updated-book-v2.pdf"
}'

Update Identifiers​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"identifiers": [
{ "type": "isbn_digital", "value": "978-0-306-40615-7", "is_primary": true },
{ "type": "ddc", "value": "823.914" }
]
}'

Update Geographic Restrictions​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"geographic_restrictions": {
"included": ["US", "CA", "GB"],
"excluded": []
}
}'

Remove Geographic Restrictions​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"geographic_restrictions": null
}'

Update Physical Product​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"stock_quantity": 48,
"pages": 380,
"weight": 520
}'

Sell a Physical Product Out​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"stock_quantity": 0
}'

Combined Update​

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166?include=prices,metadata" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Complete Updated Title",
"description": "<p>Fully revised and updated edition...</p>",
"published_at": "2025-02-01",
"prices": [
{ "currency_id": "USD", "amount": 29.99 }
],
"author": [{ "first_name": "Updated", "last_name": "Author" }],
"keywords": ["revised", "updated", "2025"],
"preview": true
}'

Response​

Success Response (200 OK)​

{
"data": {
"id": "468166",
"external_id": "9781234567890",
"name": "Updated Book Title",
"slug": "updated-book-title",
"lang": "en",
"file_type": "pdf",
"audience": "adult",
"subtitle": null,
"publication_place": null,
"edition_year": 2025,
"cover_url": "https://cdn.publica.la/covers/468166.jpg",
"reader_url": "https://yourstore.publica.la/reader/updated-book-title",
"product_url": "https://yourstore.publica.la/library/publication/updated-book-title",
"created_at": "2021-03-19T00:00:00.000000Z",
"updated_at": "2025-12-23T14:30:00.000000Z",
"published_at": "2025-01-15T00:00:00.000000Z",
"license": "retail",
"free": {
"enabled": false,
"until": null,
"require_login": false
},
"preview": {
"enabled": true,
"require_login": false
},
"subscribers_only": false,
"conversion_status": "done",
"identifiers": []
}
}
Conversion Status After File Update

When updating content files, the response will show an updated conversion_status. Use Get Content to poll for processing completion, just as you would after creating new content.

Response with Includes​

{
"data": {
"id": "468166",
"external_id": "9781234567890",
"name": "Updated Book Title",
"slug": "updated-book-title",
"lang": "en",
"file_type": "pdf",
"audience": "adult",
"subtitle": null,
"publication_place": null,
"edition_year": 2025,
"cover_url": "https://cdn.publica.la/covers/468166.jpg",
"reader_url": "https://yourstore.publica.la/reader/updated-book-title",
"product_url": "https://yourstore.publica.la/library/publication/updated-book-title",
"created_at": "2021-03-19T00:00:00.000000Z",
"updated_at": "2025-12-23T14:30:00.000000Z",
"published_at": "2025-01-15T00:00:00.000000Z",
"license": "retail",
"free": {
"enabled": false,
"until": null,
"require_login": false
},
"preview": {
"enabled": true,
"require_login": false
},
"subscribers_only": false,
"conversion_status": "done",
"prices": [{ "currency_id": "USD", "amount": 29.99 }],
"description": "<p>Fully revised and updated edition...</p>",
"publisher": ["New Publisher Name"],
"author": ["Updated Author"],
"bisac": [{ "code": "FIC000000", "label": "Fiction > General" }],
"keywords": ["revised", "updated", "2025"],
"country": [],
"edition": [],
"narrator": [],
"publishing_group": [],
"thema": [],
"series": [],
"category": [],
"collection": [],
"metrics": {
"total_pages": 320,
"total_words": 85000,
"total_seconds": 0
},
"custom_metadata": {},
"geographic_restrictions": null,
"identifiers": [
{
"type": "isbn_digital",
"value": "978-0-306-40615-7",
"is_primary": true
}
]
}
}

Error Handling​

Content Not Found (404)​

{
"message": "Content not found."
}

Validation Errors (422)​

{
"message": "The given data was invalid.",
"errors": {
"name": ["The name may not be greater than 255 characters."],
"prices.0.currency_id": ["The selected prices.0.currency_id is invalid."]
}
}

Duplicate Identifier (422)​

{
"message": "The given data was invalid.",
"errors": {
"identifiers.0.value": [
"This isbn_digital identifier is already in use as primary for another content."
]
}
}

Authentication Error (401)​

{
"message": "Unauthenticated."
}

Common Error Causes​

ErrorCause
Content not foundInvalid ID or wrong id_type
Duplicate identifierAnother content has this identifier as primary
Invalid currencyCurrency code not in system
Invalid BISAC codeBISAC code doesn't exist
File URL inaccessibleCannot download from provided URL
Invalid date formatDate not in YYYY-MM-DD or ISO 8601 format
File update not allowedFile updates only supported for PDF and EPUB content types

Best Practices​

1. Use Partial Updates​

Only include fields you're changing:

// Good - minimal payload
{ "name": "New Title" }

// Avoid - unnecessary fields
{
"name": "New Title",
"description": "Same description",
"prices": [...],
"author": [...]
}

2. Retrieve Before Update​

For complex updates, get current state first:

# Get current prices
curl -X GET "https://yourstore.publica.la/api/v3/content/468166?include=prices"

# Then update with new price added
curl -X PUT "https://yourstore.publica.la/api/v3/content/468166" \
-d '{ "prices": [existing_prices + new_price] }'

3. Use Include for Verification​

Request includes in response to verify update:

curl -X PUT "https://yourstore.publica.la/api/v3/content/468166?include=prices,metadata" \
-d '{ "prices": [...], "author": [...] }'

See Also​


X

Graph View