Manage List Items
Add and remove products in any list of any user of your store: the favorites list, a custom list the user created, or a list the user collaborates on. What you write here is what the user sees in the storefront and in the reader.
Both endpoints require an administrator token. See the Lists API Overview for authentication, the target user parameters and how a list is addressed.
These endpoints write the contents of lists. To create, rename or delete a list, see Manage Lists. Sharing a list, changing its privacy and managing collaborators exist only in the storefront.
Both operations are idempotent
These endpoints are not toggles. Repeating a call leaves the list in the same state as the first call did, which makes them safe to retry:
| Call | Result |
|---|---|
| Add a product that is not in the list | 200, the product is added |
| Add a product that is already there | 200 with the same body, nothing changes and nothing is duplicated |
| Remove a product that is in the list | 204, the product is removed |
| Remove a product that is not there | 204, nothing changes |
Add a product to a list
Adds the product to one of the target user's lists.
Endpoint
POST /api/v3/lists/{list}/items
Path parameters
| Parameter | Type | Description |
|---|---|---|
list | string | The favorites slug, or the id of one of the user's lists. See Addressing a list |
Headers
| Header | Required | Description |
|---|---|---|
X-User-Token | Yes | API token of a store administrator |
Content-Type | Yes | application/json |
Accept | No | application/json |
Body parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
user_external_id | string | Conditional | - | Your identifier for the user. Required unless user_email is sent |
user_email | string | Conditional | - | Email of the user. Required unless user_external_id is sent |
content_id | string | Yes | - | The product identifier, read according to id_type |
id_type | string | No | internal | internal reads content_id as the publica.la id; external reads it as one of the product identifiers (ISBN among them) |
Exactly one of user_external_id and user_email must be sent.
Request example
{
"user_external_id": "student-1042",
"content_id": "9781234567890",
"id_type": "external"
}
Response
Success (200):
The added product, in the same shape the items endpoints return.
{
"data": {
"content_id": "468166",
"isbn": "9781234567890",
"title": "Conversations with Donald Hall",
"reader_url": "https://yourstore.publica.la/reader/conversations-with-donald-hall",
"added_at": "2026-08-27T12:00:00.000000Z"
}
}
The response is 200 whether this call added the product or found it already there. content_id in the response is always the publica.la id, even when you addressed the product by ISBN. added_at is null when the product was already in the list from before the platform started recording that timestamp.
Examples
Add to favorites by ISBN
curl -X POST "https://yourstore.publica.la/api/v3/lists/favorites/items" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"user_external_id": "student-1042", "content_id": "9781234567890", "id_type": "external"}'
Add to favorites by publica.la id
curl -X POST "https://yourstore.publica.la/api/v3/lists/favorites/items" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"user_external_id": "student-1042", "content_id": "468166"}'
Identify the user by email
curl -X POST "https://yourstore.publica.la/api/v3/lists/favorites/items" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"user_email": "[email protected]", "content_id": "468166"}'
Add to any other list, by id
curl -X POST "https://yourstore.publica.la/api/v3/lists/9f2d4b1e-6c3a-4f58-9b77-1d0a2e5c8b34/items" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"user_external_id": "student-1042", "content_id": "468166"}'
Errors
| Status | Message | Cause |
|---|---|---|
401 | Unauthenticated. | Missing or invalid X-User-Token |
403 | This store cannot access the integrations API. | The store does not have the integrations API enabled |
403 | This token cannot operate on other users' lists. | The token does not belong to a store administrator |
404 | The specified user does not exist in this store. | No user matches the identifier sent |
404 | The specified publication does not exist in this store. | No product matches content_id under the given id_type |
404 | Not found | {list} is not a list of the target user, an unknown slug, or a reserved storefront collection |
422 | First validation error | Neither or both user identifiers, missing content_id, or an unknown id_type |
429 | Too Many Requests | Rate limit exceeded |
An unknown id_type returns:
{
"message": "The selected id type is invalid.",
"errors": {
"id_type": ["The selected id type is invalid."]
}
}
Remove a product from a list
Removes the product from one of the target user's lists.
Endpoint
DELETE /api/v3/lists/{list}/items/{content_id}
Path parameters
| Parameter | Type | Description |
|---|---|---|
list | string | The favorites slug, or the id of one of the user's lists. See Addressing a list |
content_id | string | The product identifier, read according to id_type |
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
user_external_id | string | - | Your identifier for the user. Required unless user_email is sent |
user_email | string | - | Email of the user. Required unless user_external_id is sent |
id_type | string | internal | internal reads content_id as the publica.la id; external reads it as one of the product identifiers (ISBN among them) |
Exactly one of user_external_id and user_email must be sent.
Response
Success (204):
No body. The response is 204 whether the product was in the list or not.
Examples
Remove from favorites by ISBN
curl -X DELETE "https://yourstore.publica.la/api/v3/lists/favorites/items/9781234567890?user_external_id=student-1042&id_type=external" \
-H "X-User-Token: your-api-token" \
-H "Accept: application/json"
Remove from favorites by publica.la id
curl -X DELETE "https://yourstore.publica.la/api/v3/lists/favorites/items/468166?user_external_id=student-1042" \
-H "X-User-Token: your-api-token" \
-H "Accept: application/json"
Identify the user by email
curl -X DELETE "https://yourstore.publica.la/api/v3/lists/favorites/items/468166?user_email=student%40example.com" \
-H "X-User-Token: your-api-token" \
-H "Accept: application/json"
Remove from any other list, by id
curl -X DELETE "https://yourstore.publica.la/api/v3/lists/9f2d4b1e-6c3a-4f58-9b77-1d0a2e5c8b34/items/468166?user_external_id=student-1042" \
-H "X-User-Token: your-api-token" \
-H "Accept: application/json"
Errors
| Status | Message | Cause |
|---|---|---|
401 | Unauthenticated. | Missing or invalid X-User-Token |
403 | This store cannot access the integrations API. | The store does not have the integrations API enabled |
403 | This token cannot operate on other users' lists. | The token does not belong to a store administrator |
404 | The specified user does not exist in this store. | No user matches the identifier sent |
404 | The specified publication does not exist in this store. | No product matches content_id under the given id_type |
404 | Not found | {list} is not a list of the target user, an unknown slug, or a reserved storefront collection |
422 | First validation error | Neither or both user identifiers, or an unknown id_type |
429 | Too Many Requests | Rate limit exceeded |
Working with favorites
Favorites is the list most integrations write to, and the only one with a slug: address it as favorites instead of its id, so no lookup is needed.
POST /api/v3/lists/favorites/items
DELETE /api/v3/lists/favorites/items/{content_id}
A user who has never favorited anything has no favorites list yet. The endpoints hide that:
- Add creates the favorites list on first use, so there is no separate create step. It is not created when the user or the product does not exist.
- Remove returns
204when the user has no favorites list, the same as removing a product that is not there.
Custom lists have no slug. Read their id from List Lists, or from the response of Create a list.