# ZoomHub API reference: Collection items Part of the [ZoomHub API reference](https://zoomhub.net/docs/api.md), whose index covers authentication, errors and the other resources. > **Beta:** The v2 API is in beta: endpoints, attributes and error codes may still change before it is final. Questions or feedback: [daniel@zoomhub.net](mailto:daniel@zoomhub.net). Base URL: `https://api.zoomhub.net`. Send your API key as `Authorization: Bearer `; see [Authentication](https://zoomhub.net/docs/api.md#authentication). ## Collection items A collection item is an image’s membership in a collection: its place in the order and, for a PDF’s page, its page number. Removing an item takes the image out of the collection; the image itself stays. Only a collection made with [Create a collection](https://zoomhub.net/docs/api/collections.md#collections-create) takes new members: a PDF’s collection holds its pages in page order, and answers `404` to an add. Every write here requires the collection’s owner, or an admin. ### The collection item object An image’s place in a collection. **Attributes** - `object` (string): Always `collection_item`. - `asset_id` (string): The image’s asset ID. Fetch the image with [Retrieve an asset](https://zoomhub.net/docs/api/assets.md#assets-retrieve). - `position` (integer): Its place in the display order, counting from `0`. Positions have no gaps, so a member’s position changes as others are added, removed or moved before it. - `page_number` (integer, nullable): Its page in the PDF the collection was made from, counting from `1`, or `null` for an image added on its own. **Example** ```json { "asset_id": "smpAsset1", "object": "collection_item", "page_number": 1, "position": 0 } ``` ### The added items object What a batch add did. **Attributes** - `object` (string): Always `added_items`. - `items` (array of objects): The members this batch added, in the order they joined. To take the batch back, [remove](https://zoomhub.net/docs/api/collection-items.md#collection-items-remove-batch) exactly these. - `object` (string): Always `collection_item`. - `asset_id` (string): The image’s asset ID. Fetch the image with [Retrieve an asset](https://zoomhub.net/docs/api/assets.md#assets-retrieve). - `position` (integer): Its place in the display order, counting from `0`. Positions have no gaps, so a member’s position changes as others are added, removed or moved before it. - `page_number` (integer, nullable): Its page in the PDF the collection was made from, counting from `1`, or `null` for an image added on its own. - `num_skipped` (integer): How many listed images were members already, a listed collection’s members counted one by one. - `num_failed` (integer): How many of a listed collection’s members were left out because they failed to process. **Example** ```json { "items": [ { "asset_id": "smpAsset1", "object": "collection_item", "page_number": null, "position": 0 } ], "num_failed": 1, "num_skipped": 2, "object": "added_items" } ``` ### List a collection’s items — `GET /v2/collections/{id}/items` **Authentication:** API key optional. Works without a key; a key opens your own Protected items. Returns every member of a collection, in display order. The list isn’t paginated: a collection holds at most 10,000 members. Like [Retrieve a collection](https://zoomhub.net/docs/api/collections.md#collections-retrieve), it needs no key unless a member is Protected. > **Note:** Reading what isn’t Protected needs no key: leave out the `Authorization` header. A key that fails to verify counts as no key: what’s public answers as usual, and what’s Protected answers `403` `forbidden`. **Path parameters** - `id` (string, required): The collection’s ID. **Responses** - `200 OK`: A list object whose `data` holds the collection item objects. - `403 Forbidden`, error code `forbidden`: The collection is Protected and the key’s account may not view it. The answer is the same whatever the reason, so it doesn’t reveal which rule refused. - `404 Not Found`, error code `not_found`: No collection has this ID, or it was deleted. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items" ``` **Response** `200 OK` ```json { "data": [ { "asset_id": "smpAsset1", "object": "collection_item", "page_number": 1, "position": 0 }, { "asset_id": "smpAsset2", "object": "collection_item", "page_number": 2, "position": 1 } ], "has_more": false, "object": "list" } ``` ### Add an item — `POST /v2/collections/{id}/items` **Authentication:** API key. Send an API key. Adds one image to a collection. Adding an image that is already a member changes nothing and answers `200` with its membership, so a retry is safe. The image must be done processing: [add a batch](https://zoomhub.net/docs/api/collection-items.md#collection-items-add-batch) to add images that are still processing. **Path parameters** - `id` (string, required): The collection’s ID. **Body parameters** - `asset_id` (string, required): The image’s content ID. - `position` (integer, optional): Where to insert it, counting from `0`: at most the number of members, which appends it. Without it, the image is appended. **Responses** - `201 Created`: The new membership. - `200 OK`: The image was a member already; its membership, unchanged. - `400 Bad Request`, error code `bad_request`: The body isn’t JSON, misses a required key, has a key the endpoint doesn’t know, or breaks a limit. The detail says which. - `400 Bad Request`, error code `asset_not_ready`: The image is still processing. - `400 Bad Request`, error code `asset_processing_failed`: The image’s processing failed. - `400 Bad Request`, error code `bad_request`: `position` is past the end. - `401 Unauthorized`, error code `not_authenticated`: No `Authorization` header. - `401 Unauthorized`, error code `invalid_api_key`: The key is unknown or revoked, or the header isn’t a `Bearer` key. - `403 Forbidden`, error code `plan_required`: The key is valid, but its account’s plan doesn’t include the API. - `403 Forbidden`, error code `forbidden`: The key’s account neither owns the collection nor is an admin. - `403 Forbidden`, error code `forbidden`: The key’s account doesn’t own the image. - `403 Forbidden`, error code `forbidden`: The image belongs to someone other than the collection’s owner. Only the owner’s images can join. - `404 Not Found`, error code `not_found`: No collection has this ID, it was deleted or was made from a PDF. - `404 Not Found`, error code `content_not_found`: The image doesn’t exist. - `422 Unprocessable Entity`, error code `collection_full`: The collection is full. - `503 Service Unavailable`, error code `protection_pending`: The change involves a Protected image and the CDN couldn’t be updated; nothing was saved. Retry. - `503 Service Unavailable`, error code `service_unavailable`: The collection is busy updating its protection; nothing was saved. Retry after the seconds the `Retry-After` header gives. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items" \ --header "Authorization: Bearer $ZOOMHUB_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "asset_id": "smpAsset1", "position": 0 }' ``` **Response** `201 Created` ```json { "asset_id": "smpAsset1", "object": "collection_item", "page_number": null, "position": 0 } ``` **Response** `200 OK` ```json { "asset_id": "smpAsset1", "object": "collection_item", "page_number": null, "position": 0 } ``` ### Add items — `POST /v2/collections/{id}/items/batch` **Authentication:** API key. Send an API key. Appends images, or the members of other collections, to a collection in one step. The batch is all or nothing: every image is checked before anything is written. New members are appended after the last member, in the order the entries name them. Members already there are skipped and counted, so a retry after a timeout adds nothing twice. Images still processing join too, and are composited once they are done. Name a collection to add its members as they are now: a PDF’s collection adds its pages, in page order. A collection can’t add its own members. > **Note:** The answer is `200`, not `201`: a batch whose images are all members already creates nothing. **Path parameters** - `id` (string, required): The collection’s ID. **Body parameters** - `items` (array of objects, required): The images to add, or collections whose members to add. At least one. At most 10,000 entries, none listed twice. An image that is also a member of a listed collection, or of two, joins once. - `asset_id` (string, optional): An image to add, by its content ID. Send this or `collection_id`, not both. - `collection_id` (string, optional): A collection whose members to add, in its order, as they are now: a PDF’s collection adds its pages. Members it gains or loses later don’t follow. A listed collection’s members that failed to process are left out. **Responses** - `200 OK`: The added items object. - `400 Bad Request`, error code `bad_request`: The body isn’t JSON, misses a required key, has a key the endpoint doesn’t know, or breaks a limit. The detail says which. - `400 Bad Request`, error code `bad_request`: The batch names the collection itself. - `400 Bad Request`, error code `asset_processing_failed`: A listed image failed to process. - `401 Unauthorized`, error code `not_authenticated`: No `Authorization` header. - `401 Unauthorized`, error code `invalid_api_key`: The key is unknown or revoked, or the header isn’t a `Bearer` key. - `403 Forbidden`, error code `plan_required`: The key is valid, but its account’s plan doesn’t include the API. - `403 Forbidden`, error code `forbidden`: The key’s account neither owns the collection nor is an admin. - `403 Forbidden`, error code `forbidden`: The key’s account doesn’t own a listed image. - `403 Forbidden`, error code `forbidden`: The image belongs to someone other than the collection’s owner. Only the owner’s images can join. - `404 Not Found`, error code `not_found`: No collection has this ID, it was deleted or was made from a PDF, or a listed `collection_id` isn’t a collection the key’s account owns. - `404 Not Found`, error code `content_not_found`: A listed image doesn’t exist. - `422 Unprocessable Entity`, error code `collection_full`: The batch would take the collection past its limit. Nothing was added; the detail says how many fit. - `503 Service Unavailable`, error code `protection_pending`: The change involves a Protected image and the CDN couldn’t be updated; nothing was saved. Retry. - `503 Service Unavailable`, error code `service_unavailable`: The collection is busy updating its protection; nothing was saved. Retry after the seconds the `Retry-After` header gives. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items/batch" \ --header "Authorization: Bearer $ZOOMHUB_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "items": [ { "asset_id": "smpAsset1" }, { "collection_id": "Smp7Pdf9Doc" } ] }' ``` **Response** `200 OK` ```json { "items": [ { "asset_id": "smpAsset1", "object": "collection_item", "page_number": null, "position": 0 } ], "num_failed": 1, "num_skipped": 2, "object": "added_items" } ``` ### Remove items — `POST /v2/collections/{id}/items/removal` **Authentication:** API key. Send an API key. Removes images from a collection in one step. An image that isn’t a member is skipped, so a retry after a timeout is harmless. To undo [Add items](https://zoomhub.net/docs/api/collection-items.md#collection-items-add-batch), send the `items` it answered with. The images themselves stay. **Path parameters** - `id` (string, required): The collection’s ID. **Body parameters** - `asset_ids` (array of strings, required): The images to remove, by content ID. At least one and at most 10,000, none listed twice. **Responses** - `204 No Content`: Removed. - `400 Bad Request`, error code `bad_request`: The body isn’t JSON, misses a required key, has a key the endpoint doesn’t know, or breaks a limit. The detail says which. - `401 Unauthorized`, error code `not_authenticated`: No `Authorization` header. - `401 Unauthorized`, error code `invalid_api_key`: The key is unknown or revoked, or the header isn’t a `Bearer` key. - `403 Forbidden`, error code `plan_required`: The key is valid, but its account’s plan doesn’t include the API. - `403 Forbidden`, error code `forbidden`: The key’s account neither owns the collection nor is an admin. - `404 Not Found`, error code `not_found`: No collection has this ID, or it was deleted. - `503 Service Unavailable`, error code `service_unavailable`: The collection is busy updating its protection; nothing was saved. Retry after the seconds the `Retry-After` header gives. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items/removal" \ --header "Authorization: Bearer $ZOOMHUB_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "asset_ids": [ "smpAsset1", "smpAsset2" ] }' ``` ### Order items — `PUT /v2/collections/{id}/items/order` **Authentication:** API key. Send an API key. Moves the listed members to the front of a collection, in the order listed. Every member you leave out follows, in its current order, so listing the members you show is enough. An image that isn’t a member is skipped. Only positions change: no tile is redrawn. **Path parameters** - `id` (string, required): The collection’s ID. **Body parameters** - `asset_ids` (array of strings, required): The members to put first, in their new order, by content ID. At least one and at most 10,000, none listed twice. **Responses** - `204 No Content`: Ordered. - `400 Bad Request`, error code `bad_request`: The body isn’t JSON, misses a required key, has a key the endpoint doesn’t know, or breaks a limit. The detail says which. - `401 Unauthorized`, error code `not_authenticated`: No `Authorization` header. - `401 Unauthorized`, error code `invalid_api_key`: The key is unknown or revoked, or the header isn’t a `Bearer` key. - `403 Forbidden`, error code `plan_required`: The key is valid, but its account’s plan doesn’t include the API. - `403 Forbidden`, error code `forbidden`: The key’s account neither owns the collection nor is an admin. - `404 Not Found`, error code `not_found`: No collection has this ID, or it was deleted. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items/order" \ --request PUT \ --header "Authorization: Bearer $ZOOMHUB_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "asset_ids": [ "smpAsset2", "smpAsset1" ] }' ``` ### Remove an item — `DELETE /v2/collections/{id}/items/{assetId}` **Authentication:** API key. Send an API key. Removes one image from a collection. The members after it move up one place. The image itself stays. **Path parameters** - `id` (string, required): The collection’s ID. - `assetId` (string, required): The member image’s content ID. **Responses** - `204 No Content`: Removed. - `401 Unauthorized`, error code `not_authenticated`: No `Authorization` header. - `401 Unauthorized`, error code `invalid_api_key`: The key is unknown or revoked, or the header isn’t a `Bearer` key. - `403 Forbidden`, error code `plan_required`: The key is valid, but its account’s plan doesn’t include the API. - `403 Forbidden`, error code `forbidden`: The key’s account neither owns the collection nor is an admin. - `404 Not Found`, error code `not_found`: No collection has this ID or it was deleted, or the image isn’t a member. - `503 Service Unavailable`, error code `service_unavailable`: The collection is busy updating its protection; nothing was saved. Retry after the seconds the `Retry-After` header gives. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items/smpAsset1" \ --request DELETE \ --header "Authorization: Bearer $ZOOMHUB_API_KEY" ``` ### Move an item — `PATCH /v2/collections/{id}/items/{assetId}` **Authentication:** API key. Send an API key. Moves one member to a new position. The members in between shift by one place. Only positions change: no tile is redrawn. To reorder many members, [order items](https://zoomhub.net/docs/api/collection-items.md#collection-items-set-order) instead. **Path parameters** - `id` (string, required): The collection’s ID. - `assetId` (string, required): The member image’s content ID. **Body parameters** - `position` (integer, required): Its position once moved, counting from `0`: at most the last member’s. **Responses** - `200 OK`: The moved membership. - `400 Bad Request`, error code `bad_request`: The body isn’t JSON, misses a required key, has a key the endpoint doesn’t know, or breaks a limit. The detail says which. - `400 Bad Request`, error code `bad_request`: `position` is past the last member’s. - `401 Unauthorized`, error code `not_authenticated`: No `Authorization` header. - `401 Unauthorized`, error code `invalid_api_key`: The key is unknown or revoked, or the header isn’t a `Bearer` key. - `403 Forbidden`, error code `plan_required`: The key is valid, but its account’s plan doesn’t include the API. - `403 Forbidden`, error code `forbidden`: The key’s account neither owns the collection nor is an admin. - `404 Not Found`, error code `not_found`: No collection has this ID or it was deleted, or the image isn’t a member. **Request** ```bash curl "https://api.zoomhub.net/v2/collections/Smp7Set9Abc/items/smpAsset1" \ --request PATCH \ --header "Authorization: Bearer $ZOOMHUB_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "position": 0 }' ``` **Response** `200 OK` ```json { "asset_id": "smpAsset1", "object": "collection_item", "page_number": 1, "position": 0 } ```