# List queue entries

`GET https://stylor.ai/api/v1/datasets/{datasetId}/items/queue`

- Authentication: private API key, sent as `Authorization: Bearer sgpt-sk-…::…`
- Rate-limit resource: `api.v1.datasets.items.queue.list`
- Demo key: not accepted
- Web page: https://stylor.ai/guides/rest/v1/list-queue-items

Returns a page of the dataset's ingest queue, newest first, so you can
follow the progress of an upload or a store sync. Entries in every
status except `archived` are included; there is no status filter on
this endpoint, so filter client-side.

Each entry carries the raw product `data` you uploaded, its processing
`status`, and — once a worker has touched it — a `worker` block with
logs and, on failure, the reason.

`page` and `limit` are validated, not clamped: a `limit` above 200 is
rejected. Both are read with integer parsing — decimals are truncated,
trailing characters ignored, and a value with no leading digits is
rejected.

## Example request

```bash
curl -X GET "https://stylor.ai/api/v1/datasets/YOUR_DATASET_ID/items/queue" \
  -H "Authorization: Bearer $STYLOR_API_KEY"
```

## Path parameters

- `datasetId` (string (uuid), required): The dataset's id, as returned when it was created.

## Query parameters

- `page` (integer): 1-based page number. Non-numeric values are rejected. [default `1`; minimum 1]
- `limit` (integer): Entries per page. Values above 200 are rejected with a 422 rather than clamped. [default `10`; minimum 1; maximum 200]

## Responses

### 200

A page of queue entries.

Content type `application/json`:

- `items` (array<DatasetItemQueueEntry>, required): Queue entries on this page, newest first.
  - `itemId` (string (uuid), required): Queue entry id, assigned at upload. The processed `DatasetItem` reuses it. [example `"8b0a1b62-7c2a-4b7f-9e2c-0f3a9b1f0c11"`]
  - `organizationId` (string (uuid), required): Owning organization. [example `"0a2c1f4e-5b6d-7e8f-9012-3456789abcde"`]
  - `datasetId` (string (uuid), required): Target dataset. [example `"c9b3c6c0-9b0f-4f42-bf3f-2b7a6b1b9d31"`]
  - `status` (string, required): Processing state. [one of `"pending"`, `"processing"`, `"partial_update"`, `"complete"`, `"failed"`, `"archived"`; example `"pending"`]
  - `worker` (QueueWorkerState): Processing bookkeeping. Created with an empty `logs` list at upload; the other sub-fields appear once a worker or sync sets them.
    - `logs` (array<QueueWorkerLog>): Worker log lines, oldest first. Only the 20 most recent are kept. [max items 20]
      - `type` (string): Severity. [one of `"info"`, `"warning"`, `"error"`; example `"info"`]
      - `message` (string): Human-readable message, for example `Claimed by worker <id>`, `Completed by worker <id>`, `Failed: <reason>`, `Stale lock released by worker <id>`, `Updated by sync (<status>)` or `Archived: removed from source`. [example `"Claimed by worker w-7f2a"`]
      - `createdAt` (string (date-time)): When the line was written. [example `"2025-03-04T18:20:03.001Z"`]
    - `lockedBy` (string, nullable): Id of the worker currently processing the entry, or `null`. [example `null`]
    - `lockedAt` (string, nullable): When the current lock was taken, as an ISO 8601 string, or `null`. A lock older than 20 minutes is released and the entry returns to `pending`. [example `null`]
    - `failure` (QueueWorkerFailure, nullable): Set alongside `status: failed`. Reset to `null` when the entry is claimed again or refreshed by a sync.
      - `reason` (string): Human-readable failure reason. [example `"No images could be downloaded"`]
      - `code` (string): `PROCESSING_FAILED` a processing step reported failure; `UNEXPECTED_ERROR` processing threw; `PROCESSING_ERROR` fallback when no code was supplied. [one of `"PROCESSING_FAILED"`, `"UNEXPECTED_ERROR"`, `"PROCESSING_ERROR"`; example `"PROCESSING_FAILED"`]
      - `details` (object, nullable): Additional context. `null` for `PROCESSING_FAILED`; for `UNEXPECTED_ERROR` an object with the error `stack`. [example `null`]
      - `timestamp` (string (date-time)): When the failure was recorded. [example `"2025-03-04T18:21:10.442Z"`]
  - `disableGenerativeAssets` (boolean): Whether AI thumbnails are skipped. Always `true` at present because generative assets are disabled platform-wide. [default `true`; example `true`]
  - `forceFullProcess` (boolean): When `true` the worker runs the full AI pipeline even if the SKU already exists as a processed item. Set internally by store syncs. [default `false`; example `false`]
  - `data` (IngestProduct, required): The raw product shape accepted by the upload endpoint and stored on the queue entry as `data`. It mirrors a Shopify product export. Every field listed is required except `gender`. `description` and `productType` may be empty strings; `name`, `handle` and `sku` must be non-empty (an empty value passes field validation but fails at the database with a `500`). The three date fields must be parseable and are normalised to ISO 8601 UTC on the way in.
    - `name` (string, required): Product title. Must be non-empty. [example `"Classic Crew Tee"`]
    - `handle` (string, required): URL slug. The product URL is built as `<store URL>/products/<handle>`. Must be non-empty. [example `"classic-crew-tee"`]
    - `description` (string, required): Product description; HTML is allowed. May be an empty string. [example `"<p>A heavyweight organic cotton tee with a relaxed fit.</p>"`]
    - `publishedAt` (string, required): Any string `Date` can parse (ISO 8601 recommended). [example `"2024-11-02T09:15:00Z"`]
    - `createdAt` (string, required): Any string `Date` can parse. [example `"2024-11-02T09:15:00Z"`]
    - `updatedAt` (string, required): Any string `Date` can parse. [example `"2025-02-10T12:00:00Z"`]
    - `productType` (string, required): Merchant category. May be an empty string. [example `"T-Shirts"`]
    - `sku` (string, required): Product-level SKU. Must be non-empty, unique within the request, and not already present in the dataset's queue. [example `"A1A2P-BB2J"`]
    - `price` (number, required): Product price. Must be a non-negative number. [minimum 0; example `49`]
    - `tags` (array<string>, required): Free-form tags. Every element must be a non-empty string.
    - `images` (array<IngestProductImage>, required): Images to download. Every element must be an object with `src`.
      - `src` (string (uri), required): Publicly fetchable image URL. Required — an entry without `src` fails the upload with a database validation error. [example `"https://cdn.shopify.com/s/files/1/0001/products/tee-front.jpg"`]
    - `options` (array<IngestProductOption>, required): Product options. Every element must be an object.
      - `name` (string, required): Option name. [example `"Size"`]
      - `values` (array<string>, required): Option values. Empty strings fail the upload at the database.
    - `variants` (array<IngestProductVariant>, required): Purchasable variants. Every element must be an object; a `null` element fails the request with the shared `500`.
      - `sku` (string, required): Variant SKU. Must be a string; an empty string is accepted. [example `"A1A2P-BB2J-M"`]
      - `name` (string, required): Variant title. Becomes the size `label`. Must be non-empty — an empty string fails the upload at the database with a `500`. [example `"Medium"`]
      - `available` (boolean, required): Whether the variant is in stock. [example `true`]
      - `price` (number, required): Variant price. Must be a non-negative number. [minimum 0; example `49`]
      - `createdAt` (string, required): Any string `Date` can parse (ISO 8601 recommended). Stored normalised to ISO 8601 UTC. [example `"2024-11-02T09:15:00Z"`]
      - `updatedAt` (string, required): Any string `Date` can parse. Stored normalised to ISO 8601 UTC. [example `"2025-02-10T12:00:00Z"`]
      - `productId` (string, required): Your identifier for the parent product. Must be non-empty. [example `"8412345678901"`]
    - `gender` (string, nullable): Optional. Who you sell the product to, when you know. It is stored as the item's `metadata.gender` in place of the one the labeller would choose, ahead of any department the title or tags name and of the dataset's `targetGender`. Products that are not worn (home goods, beauty, gift cards) are always `unisex`. Omit it or send `null` to let the labeller decide. Changing it on an existing SKU relabels the product. [one of `"mens"`, `"womens"`, `"unisex"`, `null`; example `"womens"`]
  - `version` (number, required): Ingest pipeline version the entry will be processed with. [example `1`]
  - `createdAt` (string (date-time), required): When the entry was queued. [example `"2025-03-04T18:19:58.120Z"`]
  - `updatedAt` (string (date-time), required): Last status or worker change. [example `"2025-03-04T18:19:58.120Z"`]
- `pagination` (ItemPagination, required): Page metadata returned by the item and queue list endpoints. There is no page count; iterate while `hasMore` is `true`.
  - `page` (integer, required): The page that was returned (1-based). [example `1`]
  - `limit` (integer, required): The page size that was applied. [example `10`]
  - `total` (integer, required): Total number of records matching the listing. [example `1284`]
  - `hasMore` (boolean, required): Whether `page + 1` would return at least one record. [example `true`]

Example:

```json
{
  "items": [
    {
      "itemId": "8b0a1b62-7c2a-4b7f-9e2c-0f3a9b1f0c11",
      "organizationId": "0a2c1f4e-5b6d-7e8f-9012-3456789abcde",
      "datasetId": "c9b3c6c0-9b0f-4f42-bf3f-2b7a6b1b9d31",
      "status": "complete",
      "worker": {
        "logs": [
          {
            "type": "info",
            "message": "Claimed by worker w-7f2a",
            "createdAt": "2025-03-04T18:20:03.001Z"
          },
          {
            "type": "info",
            "message": "Completed by worker w-7f2a",
            "createdAt": "2025-03-04T18:22:41.900Z"
          }
        ],
        "lockedBy": null,
        "lockedAt": null
      },
      "disableGenerativeAssets": true,
      "forceFullProcess": false,
      "data": {
        "name": "Classic Crew Tee",
        "handle": "classic-crew-tee",
        "description": "<p>A heavyweight organic cotton tee with a relaxed fit.</p>",
        "publishedAt": "2024-11-02T09:15:00.000Z",
        "createdAt": "2024-11-02T09:15:00.000Z",
        "updatedAt": "2025-02-10T12:00:00.000Z",
        "productType": "T-Shirts",
        "sku": "A1A2P-BB2J",
        "price": 49,
        "tags": [
          "organic",
          "basics"
        ],
        "variants": [
          {
            "sku": "A1A2P-BB2J-M",
            "name": "Medium",
            "available": true,
            "price": 49,
            "createdAt": "2024-11-02T09:15:00.000Z",
            "updatedAt": "2025-02-10T12:00:00.000Z",
            "productId": "8412345678901"
          }
        ],
        "images": [
          {
            "src": "https://cdn.shopify.com/s/files/1/0001/products/tee-front.jpg"
          }
        ],
        "options": [
          {
            "name": "Size",
            "values": [
              "Medium",
              "Large"
            ]
          }
        ]
      },
      "version": 1,
      "createdAt": "2025-03-04T18:19:58.120Z",
      "updatedAt": "2025-03-04T18:22:41.900Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 1,
    "hasMore": false
  }
}
```

## Errors

Every error is a JSON object with an `error` string. Match on the status code; the message is written for people.

| Status | Message | When |
| --- | --- | --- |
| 401 | Organization not found. Please verify the organizationId. | The organization encoded in the API key no longer exists. |
| 404 | Dataset not found for this organization. | No dataset with this `datasetId` belongs to the key's organization. |
| 422 | Page must be an integer greater than or equal to 1. | `page` is 0, negative, or not a number. |
| 422 | Limit must be an integer greater than or equal to 1. | `limit` is 0, negative, or not a number. |
| 422 | Limit cannot exceed 200 items per request. | `limit` is greater than 200. |

### Shared authentication, quota and rate-limit errors

| Status | Message | When |
| --- | --- | --- |
| 401 | API key missing. | The `Authorization` header is absent, is not `Bearer <key>`, or the key does not have three dash-separated segments. |
| 401 | Authentication failed: public key is invalid or not recognized. | A public-key endpoint was called with a key that does not exist. |
| 401 | Authentication failed: private key provided instead of a public key. | A public-key endpoint was called with an `sgpt-sk-…` key. |
| 401 | Authentication failed: token is not recognized. | A private-key endpoint was called with a key whose lookup segment does not exist. |
| 401 | Authentication failed: private key is invalid. | A private-key endpoint was called with a key whose secret does not match. |
| 401 | Authentication failed: public key provided instead of a private key. | A private-key endpoint was called with an `sgpt-pk-…` key. |
| 401 | Authentication failed: bearer token format is invalid. | A private key was sent without its `::` lookup segment. |
| 401 | Authentication failed: API key could not be read. Regenerate the key. | The key's embedded organization data could not be decrypted or parsed. |
| 403 | Demo mode is not available for private-key routes. Demos are only supported with public API keys. | The demo key was sent to a private-key endpoint. |
| 403 | Demo mode is not supported on this API route. Check the documentation for available demo endpoints. | The demo key was sent to a public-key endpoint that opts out of demo mode. |
| 403 | No active subscription for this organization. | The organization that owns the key has no active subscription. |
| 403 | No quota found for organization "<organizationId>". | The organization has no quota record for the current billing period. |
| 403 | No entitlement for "<resource>". | The plan's quota template has no entry for this endpoint. |
| 403 | Access denied to "<resource>". | The plan's quota template turns this endpoint off. |
| 429 | Monthly quota exceeded for "<resource>" (<quota>/<quota> used). | The billing-period quota for this endpoint is exhausted. `Retry-After` gives the seconds until the period resets. |
| 429 | RPM limit exceeded for "<resource>" (<used>/<limit> used). | More than the allowed requests per minute were sent. `Retry-After` is 60. |
| 500 | Internal server error. | An unexpected failure on the server. The message is always this string; details are logged, never returned. Quota consumed by the request is refunded, as it is for every 5xx response. |
