> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rastro.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Catalogs API Reference

> Complete API documentation for Catalog endpoints

## Catalog Management

### POST /public/catalogs

Create a catalog with an initial JSON Schema.

<CodeGroup>
  ```python Python theme={null}
  response = requests.post(
      "https://catalogapi.rastro.ai/api/public/catalogs",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "name": "Products",
          "description": "Main product catalog",
          "unique_id_field": "sku",
          "product_id_field": "product_id",
          "auto_evolve_schema": True,
          "strict_mode": False,
          "schema_definition": {
              "properties": {
                  "sku": {"type": "string", "description": "Stock keeping unit"},
                  "title": {"type": "string", "description": "Product title"},
                  "price": {"type": "number", "description": "Product price"}
              },
              "required": ["sku"]
          }
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X POST "https://catalogapi.rastro.ai/api/public/catalogs" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Products",
      "unique_id_field": "sku",
      "schema_definition": {
        "properties": {
          "sku": {"type": "string"},
          "title": {"type": "string"}
        },
        "required": ["sku"]
      }
    }'
  ```
</CodeGroup>

**Request Parameters:**

| Parameter                     | Type    | Required | Description                                                                                                                                                                                             |
| ----------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                        | string  | Yes      | Catalog name (1-100 chars)                                                                                                                                                                              |
| `description`                 | string  | No       | Optional description                                                                                                                                                                                    |
| `unique_id_field`             | string  | Yes      | Legacy compatibility field required by the public create request. Include the intended business key, such as `sku`, in your schema and item data; this request field is not a separate runtime selector |
| `product_id_field`            | string  | No       | Field used to group variants under products                                                                                                                                                             |
| `auto_evolve_schema`          | boolean | No       | Allow automatic schema evolution                                                                                                                                                                        |
| `strict_mode`                 | boolean | No       | Reject unknown fields                                                                                                                                                                                   |
| `schema_definition`           | object  | Yes      | Initial JSON Schema with `properties` and optional `required`                                                                                                                                           |
| `validation_rules`            | object  | No       | Catalog-level validation rules                                                                                                                                                                          |
| `catalog_md`                  | string  | No       | Markdown context for enrichment/mapping prompts                                                                                                                                                         |
| `master_catalog_id`           | string  | No       | Master catalog to inherit defaults from                                                                                                                                                                 |
| `use_master_catalog_defaults` | boolean | No       | Whether to inherit defaults from the org default master catalog                                                                                                                                         |

**Response:** The created catalog object.

***

### GET /public/catalogs

List all catalogs in your account.

<CodeGroup>
  ```python Python theme={null}
  response = requests.get(
      "https://catalogapi.rastro.ai/api/public/catalogs",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      params={"limit": 50, "offset": 0}
  )
  print(response.json())
  ```

  ```bash cURL theme={null}
  curl "https://catalogapi.rastro.ai/api/public/catalogs?limit=50&offset=0" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```
</CodeGroup>

**Query Parameters:**

| Parameter | Type    | Default | Description             |
| --------- | ------- | ------- | ----------------------- |
| `limit`   | integer | 10      | Items per page (1–100)  |
| `offset`  | integer | 0       | Number of items to skip |

**Response:**

```json theme={null}
{
  "catalogs": [
    {
      "id": "cat_123",
      "name": "Products",
      "description": "Main product catalog",
      "auto_evolve_schema": true,
      "strict_mode": false,
      "item_count": 150,
      "current_schema_version": "1.0",
      "created_at": "2026-01-15T10:30:00Z"
    }
  ],
  "total_count": 1,
  "page": 1,
  "page_size": 50
}
```

***

### GET /public/catalogs/{catalog_id}

Get details of a specific catalog.

**Response:** Same shape as a single catalog object from the list endpoint.

***

### PUT /public/catalogs/{catalog_id}

Update catalog settings. Only provided fields are changed; omitted fields remain unchanged.

<CodeGroup>
  ```python Python theme={null}
  response = requests.put(
      f"https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "name": "Renamed Catalog",
          "description": "Updated description",
          "auto_evolve_schema": False,
          "catalog_md": "# Catalog Context\nThis catalog contains industrial bearings."
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X PUT "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "Renamed Catalog", "description": "Updated description"}'
  ```
</CodeGroup>

**Request Parameters:**

| Parameter            | Type    | Required | Description                                               |
| -------------------- | ------- | -------- | --------------------------------------------------------- |
| `name`               | string  | No       | New catalog name (1–100 chars)                            |
| `description`        | string  | No       | Updated description                                       |
| `auto_evolve_schema` | boolean | No       | Allow automatic schema evolution                          |
| `strict_mode`        | boolean | No       | Reject unknown fields                                     |
| `catalog_md`         | string  | No       | Markdown context injected into enrichment/mapping prompts |

**Response:** The updated catalog object.

***

### DELETE /public/catalogs/{catalog_id}

Delete a catalog and all its data (items, schema, snapshots).

```bash theme={null}
curl -X DELETE "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json theme={null}
{"message": "Catalog cat_123 deleted successfully"}
```

***

## Schema Management

### GET /public/catalogs/{catalog_id}/schema

Get the current schema definition, including field metadata and workflow tracking.

```bash theme={null}
curl "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/schema" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json theme={null}
{
  "version": "1.2",
  "schema_definition": {
    "properties": {
      "sku": {"type": "string", "description": "Stock keeping unit"},
      "price": {"type": "number", "description": "Product price"}
    },
    "required": ["sku"]
  },
  "total_fields": 2,
  "input_fields_count": 1,
  "generated_fields_count": 1,
  "fields_workflow_info": [...]
}
```

***

### POST /public/catalogs/{catalog_id}/schema/fields

Add a new field to the catalog schema. Creates a new schema version.

<CodeGroup>
  ```python Python theme={null}
  response = requests.post(
      f"https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/schema/fields",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "field_name": "weight_kg",
          "field_type": "number",
          "description": "Product weight in kilograms",
          "required": False,
          "field_category": "input",
          "unit": "kg"
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X POST "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/schema/fields" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"field_name": "weight_kg", "field_type": "number", "description": "Product weight"}'
  ```
</CodeGroup>

**Request Parameters:**

| Parameter          | Type    | Required | Description                                                                                 |
| ------------------ | ------- | -------- | ------------------------------------------------------------------------------------------- |
| `field_name`       | string  | Yes      | Name of the field                                                                           |
| `field_type`       | string  | Yes      | Type such as `string`, `number`, `integer`, `boolean`, `array`, or `object`                 |
| `description`      | string  | No       | Field description                                                                           |
| `required`         | boolean | No       | Whether the field is required (default: false)                                              |
| `field_category`   | string  | No       | `input` or `generated`. Stored as workflow-tracking metadata when `workflow_id` is provided |
| `position`         | string  | No       | Where to add the field: `top` or `bottom`                                                   |
| `workflow_id`      | string  | No       | Workflow ID associated with the schema change                                               |
| `unit`             | string  | No       | Unit of measurement (e.g., `kg`, `V`, `W`)                                                  |
| `sample_values`    | array   | No       | Example values for the field                                                                |
| `validation_rules` | object  | No       | JSON Schema validation (pattern, enum, etc.)                                                |

**Response:**

```json theme={null}
{
  "success": true,
  "catalog_id": "cat_123",
  "new_schema_version": "1.3",
  "previous_schema_version": "1.2",
  "fields_added": ["weight_kg"],
  "message": "Field 'weight_kg' added successfully. New schema version: 1.3"
}
```

***

### PUT /public/catalogs/{catalog_id}/schema/fields/batch

Add, update, and/or remove multiple fields in one atomic operation.

<CodeGroup>
  ```python Python theme={null}
  response = requests.put(
      f"https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/schema/fields/batch",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "fields_to_add": [
              {"field_name": "color", "field_type": "string", "description": "Product color"},
              {"field_name": "weight", "field_type": "number", "unit": "kg"}
          ],
          "fields_to_update": [
              {"field_name": "price", "description": "Updated price description"}
          ],
          "fields_to_remove": ["old_field"],
          "reason": "Schema cleanup"
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X PUT "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/schema/fields/batch" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "fields_to_add": [{"field_name": "color", "field_type": "string"}],
      "fields_to_remove": ["old_field"],
      "reason": "Schema cleanup"
    }'
  ```
</CodeGroup>

**Request Parameters:**

| Parameter          | Type   | Required | Description                                                  |
| ------------------ | ------ | -------- | ------------------------------------------------------------ |
| `fields_to_add`    | array  | No       | Fields to add (same shape as POST schema/fields)             |
| `fields_to_update` | array  | No       | Fields to update (include `field_name` + changed attributes) |
| `fields_to_remove` | array  | No       | Field names to remove                                        |
| `reason`           | string | No       | Reason for the changes                                       |

**Response:** Same shape as POST schema/fields response.

***

## Taxonomy Management

### GET /public/catalogs/{catalog_id}/taxonomy

Get the catalog's taxonomy with computed inheritance (levels, paths, inherited attributes).

Returns `null` if no taxonomy is configured.

```bash theme={null}
curl "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/taxonomy" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Supports ETag caching via `If-None-Match` header — returns `304 Not Modified` when unchanged.

***

### PUT /public/catalogs/{catalog_id}/taxonomy

Set or replace the catalog taxonomy. Creates a new schema version.

<CodeGroup>
  ```python Python theme={null}
  response = requests.put(
      f"https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/taxonomy",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "name": "Product Categories",
          "hierarchy_levels": ["Category", "Subcategory"],
          "nodes": {
              "electronics": {
                  "name": "Electronics",
                  "parent": None,
                  "attributes": []
              },
              "phones": {
                  "name": "Phones",
                  "parent": "electronics",
                  "attributes": [
                      {"name": "brand", "type": "enum", "values": ["Apple", "Samsung"]}
                  ]
              }
          }
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X PUT "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/taxonomy" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Product Categories",
      "hierarchy_levels": ["Category"],
      "nodes": {
        "electronics": {"name": "Electronics", "parent": null, "attributes": []}
      }
    }'
  ```
</CodeGroup>

**Response:** The enriched taxonomy with computed fields (level, path, children, inherited\_attributes).

***

### DELETE /public/catalogs/{catalog_id}/taxonomy

Remove taxonomy from the catalog. Creates a new schema version without taxonomy.

```bash theme={null}
curl -X DELETE "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/taxonomy" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:** `204 No Content`

***

## Catalog Context

### GET /public/catalogs/{catalog_id}/catalog-md

Get the catalog's markdown context (injected into enrichment and mapping prompts).

```bash theme={null}
curl "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/catalog-md" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json theme={null}
{"catalog_id": "cat_123", "catalog_md": "# Product Context\nThis catalog contains..."}
```

***

### PUT /public/catalogs/{catalog_id}/catalog-md

Update the catalog's markdown context directly (versioned).

```bash theme={null}
curl -X PUT "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/catalog-md" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"catalog_md": "# Updated Context\nNew instructions for enrichment."}'
```

<Note>
  You can also update `catalog_md` via `PUT /public/catalogs/{catalog_id}` by including the `catalog_md` field in the request body.
</Note>

***

### GET /public/catalogs/{catalog_id}/quality-prompt

Get the catalog's quality prompt (used by the judge and readiness checks).

### PUT /public/catalogs/{catalog_id}/quality-prompt

Set the quality prompt.

```json theme={null}
{"prompt": "Rate completeness of product specs on a 1-5 scale..."}
```

***

## Item Management

### GET /public/catalogs/{catalog_id}/items

List items in a catalog with pagination, search, and sorting.

<CodeGroup>
  ```python Python theme={null}
  response = requests.get(
      f"https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/items",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      params={"limit": 50, "offset": 0, "sort": "created_at:desc"}
  )
  ```

  ```bash cURL theme={null}
  curl "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/items?limit=50&offset=0" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```
</CodeGroup>

**Query Parameters:**

| Parameter      | Type    | Default | Description                                         |
| -------------- | ------- | ------- | --------------------------------------------------- |
| `limit`        | integer | 50      | Items per page (1–1000)                             |
| `offset`       | integer | 0       | Number of items to skip                             |
| `search`       | string  | —       | Text search across all fields                       |
| `search_query` | string  | —       | Alias for `search`                                  |
| `sort`         | string  | —       | Sort by `field:direction` (e.g., `created_at:desc`) |

**Response:**

```json theme={null}
{
  "items": [
    {
      "id": "item_123",
      "data": {"title": "Product A", "price": 29.99, "variants": [...]},
      "metadata": {"created_at": "2026-01-15T10:30:00Z", "updated_at": null, "version": null}
    }
  ],
  "total": 150,
  "page": 0,
  "limit": 50
}
```

***

### GET /public/catalogs/{catalog_id}/items/{item_id}

Get a single item by database ID.

**Response:** Single item in the same shape as list items.

***

### POST /public/catalogs/{catalog_id}/items

Upsert a single item. Put the business identifier inside `data` (for example, `{"sku": "A1"}`); the legacy `unique_identifier` field is still required by the request shape but is not used as a separate selector.

```bash theme={null}
curl -X POST "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/items" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "unique_identifier": "A1",
    "data": {"sku": "A1", "title": "Product A", "price": 29.99},
    "source_info": {"source": "public_api"}
  }'
```

| Parameter           | Type   | Required | Description                                                                     |
| ------------------- | ------ | -------- | ------------------------------------------------------------------------------- |
| `unique_identifier` | string | Yes      | Legacy compatibility field. Send the same value as the identifier inside `data` |
| `data`              | object | Yes      | Item data to write                                                              |
| `source_info`       | object | No       | Metadata recorded with the write                                                |

**Response:** The created or updated item.

***

### PUT /public/catalogs/{catalog_id}/items/{item_id}

Update a single item. Only the fields you provide will be updated.

**Request Body:** Any fields to update (dynamic schema).

**Response:** The updated item.

***

### DELETE /public/catalogs/{catalog_id}/items/{item_id}

Delete a single item.

**Response:**

```json theme={null}
{"message": "Item deleted successfully"}
```

***

### POST /public/catalogs/{catalog_id}/items/bulk

Create or update up to 1000 items at once. Include your business key fields, such as `sku`, in each item object.

<CodeGroup>
  ```python Python theme={null}
  response = requests.post(
      f"https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/items/bulk",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "items": [
              {"sku": "A1", "title": "Product A", "price": 29.99},
              {"sku": "A2", "title": "Product B", "price": 39.99}
          ]
      }
  )
  ```

  ```bash cURL theme={null}
  curl -X POST "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/items/bulk" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"items": [{"sku": "A1", "title": "Product A", "price": 29.99}]}'
  ```
</CodeGroup>

**Request Parameters:**

| Parameter            | Type    | Required | Description                                                                                                  |
| -------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------ |
| `items`              | array   | Yes      | Array of item objects (max 1000)                                                                             |
| `source_info`        | object  | No       | Metadata about the data source                                                                               |
| `auto_evolve_schema` | boolean | No       | Accepted for compatibility. Public bulk writes currently allow schema evolution from the submitted item data |

<Note>
  There is no `unique_field` query parameter. Put the business key fields directly in each item object.
</Note>

**Response:**

```json theme={null}
{
  "success": true,
  "items_processed": 15,
  "items_created": 10,
  "items_failed": 0,
  "schema_evolved": false,
  "errors": []
}
```

***

## Product Variant Management

Use these endpoints when a catalog groups variants under a product item. The `{product_id}` path parameter is the parent product item's database ID, not the business `product_id` field value stored in row data.

### POST /public/catalogs/{catalog_id}/products/{product_id}/items

Create one variant under a product.

```bash theme={null}
curl -X POST "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/products/{product_item_id}/items" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sku":"SHIRT-001-RED-M","color":"Red","size":"M","price":29.99}'
```

### PUT /public/catalogs/{catalog_id}/products/{product_id}

Update product-level fields shared by variants.

```bash theme={null}
curl -X PUT "https://catalogapi.rastro.ai/api/public/catalogs/{catalog_id}/products/{product_item_id}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"product_title":"Classic T-Shirt","product_brand":"MyBrand"}'
```

### POST /public/catalogs/{catalog_id}/products/{product_id}/items/bulk

Bulk upsert variants for one product.

```json theme={null}
{
  "product": {
    "product_title": "Classic T-Shirt",
    "product_brand": "MyBrand"
  },
  "variants": [
    {"sku": "SHIRT-001-RED-M", "color": "Red", "size": "M"},
    {"sku": "SHIRT-001-BLUE-M", "color": "Blue", "size": "M"}
  ],
  "source_info": {"source": "public_api"},
  "auto_evolve_schema": true
}
```

**Response:**

```json theme={null}
{
  "product_id": "SHIRT-001",
  "items_processed": 2,
  "items_created": 2,
  "items_updated": 0,
  "items_failed": 0,
  "schema_evolved": false,
  "errors": [],
  "warnings": []
}
```

***

## Enriching Catalog Items

To enrich items in a catalog, use the [Enrich API](/enrich/reference) with the `catalog_id` parameter. The catalog's schema and taxonomy are automatically applied.

```python theme={null}
response = requests.post(
    "https://catalogapi.rastro.ai/api/public/enrich",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "catalog_id": "cat_abc123",
        "items": [
            {"part_number": "6205-2RS", "name": "Deep Groove Ball Bearing"}
        ],
        "speed": "deep"
    }
)
```

See [Enrich Examples](/enrich/examples#reuse-configuration-with-catalog-id) for more details.

***

## Snapshots

### GET /public/catalogs/{catalog_id}/snapshots

List catalog snapshots.

### POST /public/catalogs/{catalog_id}/snapshots

Create a snapshot. Request body: `{"reason": "Before migration"}`.

### POST /public/catalogs/{catalog_id}/snapshots/{snapshot_id}/restore

Restore from a snapshot. Automatically creates a safety snapshot first.

***

## MCP-Oriented Endpoints

These endpoints are commonly used by Rastro MCP servers for large catalog workflows:

* `GET /public/catalogs/{catalog_id}/raw-items` for full-fidelity catalog row pulls. Supports `limit` (1-5000, default 1000), `offset`, `entity_type=product|variant`, `search`, `sort_field`, and `sort_order=asc|desc`
* `GET /public/catalogs/{catalog_id}/raw-items/{item_id}` for a single raw catalog row
* `GET /public/catalogs/{catalog_id}/activities` to audit pending/completed activities
* `POST /public/catalogs/{catalog_id}/activities` to create activity shells
* `POST /public/catalogs/{catalog_id}/activities/custom-transform` to create a custom transform activity
* `POST /public/catalogs/{catalog_id}/activities/{activity_id}/save-workflow` to save an activity as a workflow
* `POST /public/activities/{activity_id}/staged-changes/append` to append staged changes in chunks
* `POST /public/activities/{activity_id}/pending-review` to finalize one review activity

Activity listing supports `status`, `type`, `limit`, and `offset` query parameters. Snapshots support `snapshot_type`, `limit`, and `offset`.

See [MCP Reference](/mcp/reference) for full workflow guidance.
