# List datasets

`GET https://stylor.ai/api/v1/datasets`

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

Returns a page of the datasets that belong to the organization behind your
private key, newest first, with live item counts for each one.

Use it to find a `datasetId` before calling any other dataset endpoint,
or to build a catalogue picker in your own tooling.

## Good to know

- Rows are a summary: `config`, `metadata` and `autoPublish` are omitted.
  Call *Retrieve dataset* for the full record.
- The `items` block is computed on every request from the catalogue and
  the ingest queue, so it is accurate but adds a little latency on very
  large accounts.
- `page` and `limit` are parsed as integers. A value that does not parse
  (for example `page=abc`) is rejected rather than defaulted. Values
  above `200` for `limit` are rejected, not clamped.
- The pagination block on this endpoint carries `page`, `limit`, `total`
  and `hasMore` only; there is no `pages` field.

## Example request

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

## Query parameters

- `page` (integer): 1-based page number. Must be an integer of at least 1. [default `1`; minimum 1]
- `limit` (integer): Datasets per page. Must be an integer between 1 and 200; larger values are rejected. [default `10`; minimum 1; maximum 200]

## Responses

### 200

A page of datasets.

Content type `application/json`:

- `datasets` (array<DatasetSummary>, required): Datasets on this page, newest first.
  - `datasetId` (string (uuid), required): Unique id of the dataset.
  - `status` (string, required): Lifecycle state of a dataset. - `draft` — newly created; not visible to search, chat or the widget. - `active` — live. Any number of datasets can be active at once. - `archived` — parked. Data is kept, items and sources are switched off. [default `"draft"`; one of `"draft"`, `"active"`, `"archived"`]
  - `name` (string, required): Display name.
  - `description` (string): Free-text description. May be an empty string.
  - `targetGender` (string, nullable, required): The dataset's `config.targetGender`, or `null` when detection is on. [one of `"mens"`, `"womens"`]
  - `createdAt` (string (date-time), required): When the dataset was created.
  - `updatedAt` (string (date-time), required): When the dataset record was last written.
  - `items` (DatasetItemCounts, required): Live counts of the records inside a dataset, split between processed items and the ingest queue.
    - `active` (integer, required): Processed items that are live. [minimum 0]
    - `archived` (integer, required): Processed items that are archived. [minimum 0]
    - `pending` (integer, required): Queue rows waiting to be processed. [minimum 0]
    - `partial_update` (integer): Queue rows waiting to apply a partial update to an existing item. Only present on list responses. [minimum 0]
    - `processing` (integer, required): Queue rows currently being processed. [minimum 0]
    - `failed` (integer, required): Queue rows that failed processing. [minimum 0]
- `pagination` (DatasetListPagination, required): Page metadata returned by *List datasets*. Unlike the shared `Pagination` shape it has no `pages` field.
  - `page` (integer, required): The page that was returned (1-based). [example `1`]
  - `limit` (integer, required): Page size that was applied. [example `10`]
  - `total` (integer, required): Total datasets in the organization. [example `2`]
  - `hasMore` (boolean, required): Whether a following page exists. [example `false`]

Example:

```json
{
  "datasets": [
    {
      "datasetId": "c9b3c6c0-9b0f-4f42-bf3f-2b7a6b1b9d31",
      "status": "active",
      "name": "Spring 2026",
      "description": "Women's spring drop",
      "targetGender": "womens",
      "createdAt": "2026-03-02T09:14:31.208Z",
      "updatedAt": "2026-08-19T16:40:02.911Z",
      "items": {
        "active": 1284,
        "archived": 12,
        "pending": 0,
        "partial_update": 3,
        "processing": 0,
        "failed": 2
      }
    },
    {
      "datasetId": "5f1e9c1a-2d3b-4c8e-9a7f-0b6d4e2c1a99",
      "status": "draft",
      "name": "Menswear import",
      "description": "",
      "targetGender": null,
      "createdAt": "2026-02-11T12:00:00.000Z",
      "updatedAt": "2026-02-11T12:00:00.000Z",
      "items": {
        "active": 0,
        "archived": 0,
        "pending": 540,
        "partial_update": 0,
        "processing": 8,
        "failed": 0
      }
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 2,
    "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 check the organizationId. | The organization that owns the key no longer exists. |
| 422 | Page must be a positive integer greater than or equal to 1. | `page` is below 1 or is not an integer (including values that fail to parse). |
| 422 | Limit must be a positive integer greater than or equal to 1. | `limit` is below 1 or is not an integer (including values that fail to parse). |
| 422 | Limit cannot exceed 200 datasets 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. |
