# List products

> Returns a list of products and product variants.

Breadcrumb: API › List products
Docs index: https://docs.cevoid.com/developers/llms.txt

`GET https://api.cevoid.com/v2/products`

Returns a list of products and product variants.

## Authorizations

Bearer token in the Authorization header: `Authorization: Bearer <key>` (API key).

## Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `market` | `string` | No | Market ID used to resolve localized data. Omit to use the default market. Example: `mar_sweden`. |
| `cursor` | `string` | No | Opaque cursor returned from a previous list response Example: `eyJpZCI6InBvc3RfMDEifQ`. |
| `limit` | `integer` | No | Page size between 1 and 100 Range: `1 <= x <= 100`. Example: `25`. |

## Response

### 200: Successful response

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | `object[]` | Yes | Items returned for this page. |
| `data[].market_id` | `string` | Yes | Cevoid market ID for this product presentation. Example: `mar_sweden`. |
| `data[].external_id` | `string` | No | Product identifier from the connected commerce platform. Example: `shopify_product_123`. |
| `data[].title` | `string` | No | Market-specific product title. Example: `Merino crew neck`. |
| `data[].variant_title` | `string` | No | Market-specific variant option label. Example: `Navy / M`. |
| `data[].sku` | `string` | No | Market-specific stock keeping unit. Example: `MERINO-NAVY-M`. |
| `data[].url` | `string<uri>` | No | Storefront URL for the selected market presentation. Example: `https://shop.example/products/merino-crew`. |
| `data[].image_url` | `string<uri>` | No | Primary image for the selected market presentation. Example: `https://cdn.cevoid.com/products/merino-crew/0.jpg`. |
| `data[].availability` | `enum<string>` | No | Availability for the selected market presentation. Allowed values: `IN_STOCK`, `OUT_OF_STOCK`. Example: `IN_STOCK`. |
| `data[].id` | `string` | Yes | Cevoid product or variant ID. Example: `prd_abc123def456gh`. |
| `data[].type` | `enum<string>` | Yes | Product family. Allowed value: `PRODUCT`. Example: `PRODUCT`. |
| `data[].price` | `object` | No | Market-specific Product price range. |
| `data[].price.currency` | `string` | Yes | ISO 4217 currency code. Example: `SEK`. |
| `data[].price.min_amount` | `number` | Yes | Lowest Variant price. Range: `0 <= x`. Example: `799`. |
| `data[].price.max_amount` | `number` | Yes | Highest Variant price. Range: `0 <= x`. Example: `999`. |
| `data[].market_id` | `string` | Yes | Cevoid market ID for this product presentation. Example: `mar_sweden`. |
| `data[].external_id` | `string` | No | Product identifier from the connected commerce platform. Example: `shopify_product_123`. |
| `data[].title` | `string` | No | Market-specific product title. Example: `Merino crew neck`. |
| `data[].variant_title` | `string` | No | Market-specific variant option label. Example: `Navy / M`. |
| `data[].sku` | `string` | No | Market-specific stock keeping unit. Example: `MERINO-NAVY-M`. |
| `data[].url` | `string<uri>` | No | Storefront URL for the selected market presentation. Example: `https://shop.example/products/merino-crew`. |
| `data[].image_url` | `string<uri>` | No | Primary image for the selected market presentation. Example: `https://cdn.cevoid.com/products/merino-crew/0.jpg`. |
| `data[].availability` | `enum<string>` | No | Availability for the selected market presentation. Allowed values: `IN_STOCK`, `OUT_OF_STOCK`. Example: `IN_STOCK`. |
| `data[].id` | `string` | Yes | Cevoid product or variant ID. Example: `prd_abc123def456gh`. |
| `data[].type` | `enum<string>` | Yes | Purchasable Product variant. Allowed value: `VARIANT`. Example: `VARIANT`. |
| `data[].parent_product_id` | `string` | Yes | Cevoid product ID. Present when type is VARIANT. Example: `prd_abc123def456gh`. |
| `data[].price` | `object` | No | Market-specific Variant price. |
| `data[].price.currency` | `string` | Yes | ISO 4217 currency code. Example: `SEK`. |
| `data[].price.amount` | `number` | Yes | Current Variant price. Range: `0 <= x`. Example: `899`. |
| `data[].price.sale_amount` | `number` | No | Sale price when active. Range: `0 <= x`. Example: `799`. |
| `has_more` | `boolean` | Yes | Whether another page of results is available. Example: `true`. |
| `next_cursor` | `string \| null` | Yes | Opaque cursor to request the next page, or null when the list is exhausted. Example: `eyJpZCI6InJlc291cmNlXzI1In0`. |

Response headers:

| Header | Type | Description |
| --- | --- | --- |
| `Cevoid-Processing-Ms` | `string` | End-to-end request processing time in milliseconds |
| `Cevoid-Request-Id` | `string` | Request identifier for support and tracing |
| `RateLimit-Limit` | `string` | Current rate limit bucket size |
| `RateLimit-Remaining` | `string` | Remaining requests in the current rate limit window |
| `RateLimit-Reset` | `integer` | Seconds until the next request token is available |

```json
{
  "data": [
    {
      "id": "prd_abc123def456gh",
      "type": "PRODUCT",
      "market_id": "mar_sweden",
      "external_id": "shopify_product_123",
      "title": "Merino crew neck",
      "sku": "MERINO-CREW",
      "url": "https://shop.example.com/products/merino-crew",
      "image_url": "https://cdn.cevoid.com/products/merino-crew/0.jpg",
      "availability": "IN_STOCK",
      "price": {
        "currency": "SEK",
        "min_amount": 799,
        "max_amount": 999
      }
    },
    {
      "id": "var_abc123def456gh",
      "type": "VARIANT",
      "parent_product_id": "prd_abc123def456gh",
      "market_id": "mar_sweden",
      "external_id": "shopify_variant_456",
      "title": "Merino crew neck",
      "variant_title": "Navy / M",
      "sku": "MERINO-CREW-NAVY-M",
      "url": "https://shop.example.com/products/merino-crew?variant=navy-m",
      "image_url": "https://cdn.cevoid.com/products/merino-crew/navy-m.jpg",
      "availability": "IN_STOCK",
      "price": {
        "currency": "SEK",
        "amount": 899,
        "sale_amount": 799
      }
    }
  ],
  "has_more": true,
  "next_cursor": "eyJpZCI6IjY4YTUwYjNkMWYwMDAwMDAwMDAwMDAwMCJ9"
}
```

### 400: Bad request

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `additional_data` | `object` | No | Optional machine-readable error details. |
| `additional_data.{key}` | `any` | No |  |
| `status` | `number` | Yes | HTTP status code for the error response. Example: `404`. |
| `code` | `string` | Yes | Stable machine-readable error code. Example: `not_found`. |
| `message` | `string` | Yes | Human-readable description of the error. Example: `Route not found`. |
| `request_id` | `string` | No | Request identifier for support and tracing. Example: `req_abc123`. |

Response headers: the same as 200.

```json
{
  "additional_data": {
    "errors": [
      {
        "field": "query.market",
        "message": "Invalid input: expected string, received array"
      }
    ]
  },
  "status": 400,
  "code": "bad_request",
  "message": "Bad request",
  "request_id": "req_abc123"
}
```

### 401: Unauthorized

`application/json`

Same fields as 400.

Response headers: the same as 200.

```json
{
  "status": 401,
  "code": "unauthorized",
  "message": "Unauthorized",
  "request_id": "req_abc123"
}
```

### 403: Forbidden

`application/json`

Same fields as 400.

Response headers: the same as 200.

```json
{
  "status": 403,
  "code": "forbidden",
  "message": "Forbidden",
  "request_id": "req_abc123"
}
```

### 422: Validation error

`application/json`

Same fields as 400.

Response headers: the same as 200.

```json
{
  "additional_data": {
    "errors": [
      {
        "field": "query.market",
        "message": "Invalid input: expected string, received array"
      }
    ]
  },
  "status": 422,
  "code": "validation_error",
  "message": "Validation error",
  "request_id": "req_abc123"
}
```

### 429: Too many requests

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `additional_data` | `object` | Yes | Machine-readable rate-limit details. |
| `additional_data.retry_after_seconds` | `integer` | Yes | Range: `0 <= x`. |
| `additional_data.{key}` | `any` | No |  |
| `status` | `integer` | Yes | HTTP status code. Example: `404`. |
| `code` | `string` | Yes | Stable machine-readable error code. Example: `not_found`. |
| `message` | `string` | Yes | Human-readable error description. Example: `Resource not found`. |
| `request_id` | `string` | No | Request identifier for support and tracing. Example: `req_abc123`. |

Response headers:

| Header | Type | Description |
| --- | --- | --- |
| `Cevoid-Processing-Ms` | `string` | End-to-end request processing time in milliseconds |
| `Cevoid-Request-Id` | `string` | Request identifier for support and tracing |
| `RateLimit-Limit` | `string` | Current rate limit bucket size |
| `RateLimit-Remaining` | `string` | Remaining requests in the current rate limit window |
| `RateLimit-Reset` | `integer` | Seconds until the next request token is available |
| `Retry-After` | `integer` | Seconds to wait before retrying the request |

```json
{
  "status": 429,
  "code": "rate_limit_exceeded",
  "message": "Rate limit exceeded",
  "request_id": "req_abc123",
  "additional_data": {
    "retry_after_seconds": 1
  }
}
```

### 500: Internal server error

`application/json`

Same fields as 400.

Response headers: the same as 200.

```json
{
  "status": 500,
  "code": "internal_server_error",
  "message": "Internal server error",
  "request_id": "req_abc123"
}
```

## Request example

```bash
curl 'https://api.cevoid.com/v2/products' \
  -H "Authorization: Bearer ${CEVOID_API_KEY}"
```

---

Canonical: https://docs.cevoid.com/developers/api/products/list-products
