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

# Gerenciar Produtos

> CRUD completo de produtos, variantes, opções, media e categorias

# Gerenciar Produtos

Este guia cobre todas as operações para consultar, criar, atualizar e excluir produtos e suas sub-entidades.

<Info>
  Para ver todos os campos disponíveis, tipos e validações de cada endpoint, consulte o [API Reference](/api-reference).
</Info>

## Regras Importantes

Antes de começar, tenha em mente estas regras que se aplicam a toda a gestão de produtos:

<Warning>
  **Ordem de criação obrigatória:** Produto → Opções → Variantes → Media / Categorias. Você não pode criar variantes sem opções primeiro.
</Warning>

* **Status do produto:** Atualmente o único valor suportado é `"published"`. O status é retornado igual nas respostas.
* **`option_values` é imutável:** Uma vez criada a variante, você não pode alterar seus `option_values` via PATCH. Se precisar corrigi-los, exclua a variante e crie-a novamente.
* **Moedas suportadas:** `MXN`, `PEN`, `COP`, `CLP`, `ARS`, `BRL`, `VES`, `BOB`, `USD`, `PYG`, `UYU`, `CRC`, `EUR`.
* **A moeda deve coincidir com a do catálogo:** Todas as variantes de um produto devem usar a mesma moeda configurada no catálogo. Usar uma moeda diferente pode causar inconsistências internas.
* **Respostas:** `PATCH` retorna `200` com o recurso atualizado. `DELETE` retorna `204` sem body.
* **Todo produto requer pelo menos uma variante:** Mesmo produtos simples (sem tamanhos ou cores) precisam de no mínimo uma opção e uma variante. Use um nome genérico como "Apresentação" ou "Unidade".
* **Não existem endpoints batch:** Cada entidade deve ser criada individualmente.

## Consultar Produtos

### Listar produtos

Retorna uma lista paginada de produtos com todas as suas sub-entidades.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.ya.onl/v1/products?page=1&limit=25" \
    -H "X-API-Key: yv_live_v1_sua_api_key"
  ```

  ```python Python theme={null}
  import httpx

  headers = {"X-API-Key": "yv_live_v1_sua_api_key"}

  response = httpx.get(
      "https://api.ya.onl/v1/products",
      headers=headers,
      params={"page": 1, "limit": 25},
  )
  result = response.json()
  products = result["data"]
  pagination = result["pagination"]
  ```

  ```javascript Node.js theme={null}
  const headers = { "X-API-Key": "yv_live_v1_sua_api_key" };

  const response = await fetch(
    "https://api.ya.onl/v1/products?page=1&limit=25",
    { headers }
  );
  const { data: products, pagination } = await response.json();
  ```
</CodeGroup>

A resposta inclui paginação:

```json theme={null}
{
  "data": [ /* array de produtos */ ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total_pages": 4,
    "total_items": 100,
    "has_more": true
  }
}
```

<Info>
  `limit` aceita um máximo de `100`. Consulte [Paginação](/pagination) para mais detalhes.
</Info>

### Obter um produto

Retorna um produto com todas as suas opções, variantes (com media) e categorias.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.ya.onl/v1/products/9876" \
    -H "X-API-Key: yv_live_v1_sua_api_key"
  ```

  ```python Python theme={null}
  response = httpx.get(
      f"https://api.ya.onl/v1/products/{product_id}",
      headers=headers,
  )
  product = response.json()
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    `https://api.ya.onl/v1/products/${productId}`,
    { headers }
  );
  const product = await response.json();
  ```
</CodeGroup>

Exemplo de resposta:

```json theme={null}
{
  "id": 9876,
  "created_at": "2026-01-15T10:00:00Z",
  "name": "Polo Negro",
  "description": "Polo de algodón pima de alta calidad",
  "characteristics": "Material: 100% algodón pima. Peso: 180g/m².",
  "status": "published",
  "categories": [
    { "id": 1, "name": "Ropa" }
  ],
  "options": [
    {
      "id": 10,
      "name": "Talla",
      "values": [
        { "id": 100, "name": "S" },
        { "id": 101, "name": "M" },
        { "id": 102, "name": "L" }
      ]
    }
  ],
  "variants": [
    {
      "id": 500,
      "name": "Polo Negro - Talla M",
      "base_price": 49.90,
      "currency": "PEN",
      "status": "available",
      "media": [
        {
          "id": 1000,
          "title": "Front view",
          "url": "https://cdn.example.com/polo-negro-m-front.jpg"
        }
      ]
    }
  ]
}
```

## Criar um Produto Completo

### 1. Criar o produto

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ya.onl/v1/products" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "catalog_id": 1,
      "name": "Polo Negro",
      "description": "Polo de algodón pima de alta calidad",
      "characteristics": "Material: 100% algodón pima. Peso: 180g/m².",
      "status": "published"
    }'
  ```

  ```python Python theme={null}
  import httpx

  headers = {"X-API-Key": "yv_live_v1_sua_api_key"}

  response = httpx.post(
      "https://api.ya.onl/v1/products",
      headers=headers,
      json={
          "catalog_id": 1,
          "name": "Polo Negro",
          "description": "Polo de algodón pima de alta calidad",
          "characteristics": "Material: 100% algodón pima. Peso: 180g/m².",
          "status": "published",
      },
  )
  product = response.json()
  product_id = product["id"]
  ```

  ```javascript Node.js theme={null}
  const headers = {
    "X-API-Key": "yv_live_v1_sua_api_key",
    "Content-Type": "application/json",
  };

  const response = await fetch("https://api.ya.onl/v1/products", {
    method: "POST",
    headers,
    body: JSON.stringify({
      catalog_id: 1,
      name: "Polo Negro",
      description: "Polo de algodón pima de alta calidad",
      characteristics: "Material: 100% algodón pima. Peso: 180g/m².",
      status: "published",
    }),
  });
  const product = await response.json();
  const productId = product.id;
  ```
</CodeGroup>

### 2. Adicionar opções

A resposta inclui os IDs dos valores criados. **Guarde esses IDs** para usá-los ao criar variantes.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ya.onl/v1/products/9876/options" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Talla",
      "values": ["S", "M", "L"]
    }'
  ```

  ```python Python theme={null}
  response = httpx.post(
      f"https://api.ya.onl/v1/products/{product_id}/options",
      headers=headers,
      json={"name": "Talla", "values": ["S", "M", "L"]},
  )
  option = response.json()
  # option = {"id": 10, "name": "Talla", "values": [
  #   {"id": 100, "name": "S"}, {"id": 101, "name": "M"}, {"id": 102, "name": "L"}
  # ]}
  value_ids = {v["name"]: v["id"] for v in option["values"]}
  ```

  ```javascript Node.js theme={null}
  const optionRes = await fetch(
    `https://api.ya.onl/v1/products/${productId}/options`,
    {
      method: "POST",
      headers,
      body: JSON.stringify({ name: "Talla", values: ["S", "M", "L"] }),
    }
  );
  const option = await optionRes.json();
  // option = {id: 10, name: "Talla", values: [
  //   {id: 100, name: "S"}, {id: 101, name: "M"}, {id: 102, name: "L"}
  // ]}
  const valueIds = Object.fromEntries(
    option.values.map((v) => [v.name, v.id])
  );
  ```
</CodeGroup>

<Info>
  **Precisa adicionar mais valores a uma opção?** Use `POST /v1/products/{product_id}/options/{option_id}/values` com o nome do novo valor (ex. `{"name": "XL"}`).
</Info>

### 3. Criar variantes

Cada variante deve incluir `option_values` com pelo menos um ID de valor de opção.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ya.onl/v1/products/9876/variants" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Polo Negro - Talla M",
      "base_price": 49.90,
      "currency": "PEN",
      "status": "available",
      "option_values": [101]
    }'
  ```

  ```python Python theme={null}
  response = httpx.post(
      f"https://api.ya.onl/v1/products/{product_id}/variants",
      headers=headers,
      json={
          "name": "Polo Negro - Talla M",
          "base_price": 49.90,
            "currency": "PEN",
          "status": "available",
          "option_values": [value_ids["M"]],
      },
  )
  variant = response.json()
  variant_id = variant["id"]
  ```

  ```javascript Node.js theme={null}
  const variantRes = await fetch(
    `https://api.ya.onl/v1/products/${productId}/variants`,
    {
      method: "POST",
      headers,
      body: JSON.stringify({
        name: "Polo Negro - Talla M",
        base_price: 49.9,
        currency: "PEN",
        status: "available",
        option_values: [valueIds["M"]],
      }),
    }
  );
  const variant = await variantRes.json();
  const variantId = variant.id;
  ```
</CodeGroup>

### 4. Adicionar media à variante

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ya.onl/v1/products/9876/variants/500/media" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "title": "Front view",
      "url": "https://cdn.example.com/polo-negro-m-front.jpg"
    }'
  ```

  ```python Python theme={null}
  response = httpx.post(
      f"https://api.ya.onl/v1/products/{product_id}/variants/{variant_id}/media",
      headers=headers,
      json={
          "title": "Front view",
          "url": "https://cdn.example.com/polo-negro-m-front.jpg",
      },
  )
  media = response.json()
  ```

  ```javascript Node.js theme={null}
  const mediaRes = await fetch(
    `https://api.ya.onl/v1/products/${productId}/variants/${variantId}/media`,
    {
      method: "POST",
      headers,
      body: JSON.stringify({
        title: "Front view",
        url: "https://cdn.example.com/polo-negro-m-front.jpg",
      }),
    }
  );
  const media = await mediaRes.json();
  ```
</CodeGroup>

<Warning>
  As URLs de media devem ser **públicas e acessíveis**. O sistema não pode acessar URLs privadas ou protegidas por autenticação.
</Warning>

<Info>
  **Tipos de arquivo permitidos:**

  | Tipo | Extensão | Tamanho máximo |
  | - | - | - |
  | Imagem | `jpeg` | 5 MB |
  | Imagem | `png` | 5 MB |
  | Vídeo | `3gp` | 16 MB |
  | Vídeo | `mp4` | 16 MB |
  | Documento | `pdf` | 100 MB |
</Info>

### 5. Atribuir categorias

Este endpoint é **idempotente**: se um tag já está atribuído, ele é ignorado e a resposta é `200`. Só retorna `201` quando novos tags são atribuídos.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.ya.onl/v1/products/9876/categories" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{"tag_ids": [1, 2]}'
  ```

  ```python Python theme={null}
  response = httpx.post(
      f"https://api.ya.onl/v1/products/{product_id}/categories",
      headers=headers,
      json={"tag_ids": [1, 2]},
  )
  categories = response.json()
  ```

  ```javascript Node.js theme={null}
  const catRes = await fetch(
    `https://api.ya.onl/v1/products/${productId}/categories`,
    {
      method: "POST",
      headers,
      body: JSON.stringify({ tag_ids: [1, 2] }),
    }
  );
  const categories = await catRes.json();
  ```
</CodeGroup>

## Atualizar Entidades

<AccordionGroup>
  <Accordion title="Atualizar produto">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X PATCH "https://api.ya.onl/v1/products/9876" \
        -H "X-API-Key: yv_live_v1_sua_api_key" \
        -H "Content-Type: application/json" \
        -d '{"name": "Polo Negro Premium"}'
      ```

      ```python Python theme={null}
      response = httpx.patch(
          f"https://api.ya.onl/v1/products/{product_id}",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
          json={"name": "Polo Negro Premium"},
      )
      ```

      ```javascript Node.js theme={null}
      const response = await fetch(
        `https://api.ya.onl/v1/products/${productId}`,
        {
          method: "PATCH",
          headers: {
            "X-API-Key": "yv_live_v1_sua_api_key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ name: "Polo Negro Premium", status: "draft" }),
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Atualizar opção">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X PATCH "https://api.ya.onl/v1/products/9876/options/10" \
        -H "X-API-Key: yv_live_v1_sua_api_key" \
        -H "Content-Type: application/json" \
        -d '{"name": "Talla (cm)"}'
      ```

      ```python Python theme={null}
      response = httpx.patch(
          f"https://api.ya.onl/v1/products/{product_id}/options/10",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
          json={"name": "Talla (cm)"},
      )
      ```

      ```javascript Node.js theme={null}
      const response = await fetch(
        `https://api.ya.onl/v1/products/${productId}/options/10`,
        {
          method: "PATCH",
          headers: {
            "X-API-Key": "yv_live_v1_sua_api_key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ name: "Talla (cm)" }),
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Atualizar valor de opção">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X PATCH "https://api.ya.onl/v1/products/9876/options/10/values/100" \
        -H "X-API-Key: yv_live_v1_sua_api_key" \
        -H "Content-Type: application/json" \
        -d '{"name": "Small"}'
      ```

      ```python Python theme={null}
      response = httpx.patch(
          f"https://api.ya.onl/v1/products/{product_id}/options/10/values/100",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
          json={"name": "Small"},
      )
      ```

      ```javascript Node.js theme={null}
      const response = await fetch(
        `https://api.ya.onl/v1/products/${productId}/options/10/values/100`,
        {
          method: "PATCH",
          headers: {
            "X-API-Key": "yv_live_v1_sua_api_key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ name: "Small" }),
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Atualizar variante">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X PATCH "https://api.ya.onl/v1/products/9876/variants/500" \
        -H "X-API-Key: yv_live_v1_sua_api_key" \
        -H "Content-Type: application/json" \
        -d '{"base_price": 59.90, "status": "not_available"}'
      ```

      ```python Python theme={null}
      response = httpx.patch(
          f"https://api.ya.onl/v1/products/{product_id}/variants/500",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
          json={"base_price": 59.90, "status": "not_available"},
      )
      ```

      ```javascript Node.js theme={null}
      const response = await fetch(
        `https://api.ya.onl/v1/products/${productId}/variants/500`,
        {
          method: "PATCH",
          headers: {
            "X-API-Key": "yv_live_v1_sua_api_key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ base_price: 59.9, status: "not_available" }),
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Atualizar media">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X PATCH "https://api.ya.onl/v1/products/9876/variants/500/media/1000" \
        -H "X-API-Key: yv_live_v1_sua_api_key" \
        -H "Content-Type: application/json" \
        -d '{"title": "Vista frontal atualizada"}'
      ```

      ```python Python theme={null}
      response = httpx.patch(
          f"https://api.ya.onl/v1/products/{product_id}/variants/500/media/1000",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
          json={"title": "Vista frontal atualizada"},
      )
      ```

      ```javascript Node.js theme={null}
      const response = await fetch(
        `https://api.ya.onl/v1/products/${productId}/variants/500/media/1000`,
        {
          method: "PATCH",
          headers: {
            "X-API-Key": "yv_live_v1_sua_api_key",
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ title: "Vista frontal atualizada" }),
        }
      );
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Excluir Entidades

<AccordionGroup>
  <Accordion title="Remover categoria de um produto">
    Isso desvincula a categoria do produto, mas **não exclui** a categoria global.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X DELETE "https://api.ya.onl/v1/products/9876/categories/1" \
        -H "X-API-Key: yv_live_v1_sua_api_key"
      ```

      ```python Python theme={null}
      response = httpx.delete(
          f"https://api.ya.onl/v1/products/{product_id}/categories/1",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
      )
      ```

      ```javascript Node.js theme={null}
      await fetch(
        `https://api.ya.onl/v1/products/${productId}/categories/1`,
        {
          method: "DELETE",
          headers: { "X-API-Key": "yv_live_v1_sua_api_key" },
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Excluir media">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X DELETE "https://api.ya.onl/v1/products/9876/variants/500/media/1000" \
        -H "X-API-Key: yv_live_v1_sua_api_key"
      ```

      ```python Python theme={null}
      response = httpx.delete(
          f"https://api.ya.onl/v1/products/{product_id}/variants/500/media/1000",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
      )
      ```

      ```javascript Node.js theme={null}
      await fetch(
        `https://api.ya.onl/v1/products/${productId}/variants/500/media/1000`,
        {
          method: "DELETE",
          headers: { "X-API-Key": "yv_live_v1_sua_api_key" },
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Excluir variante">
    <Warning>
      Excluir uma variante também exclui toda a sua media associada.
    </Warning>

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X DELETE "https://api.ya.onl/v1/products/9876/variants/500" \
        -H "X-API-Key: yv_live_v1_sua_api_key"
      ```

      ```python Python theme={null}
      response = httpx.delete(
          f"https://api.ya.onl/v1/products/{product_id}/variants/500",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
      )
      ```

      ```javascript Node.js theme={null}
      await fetch(
        `https://api.ya.onl/v1/products/${productId}/variants/500`,
        {
          method: "DELETE",
          headers: { "X-API-Key": "yv_live_v1_sua_api_key" },
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Excluir valor de opção">
    <Warning>
      Você não pode excluir um valor de opção se ele estiver associado a uma variante ativa.
    </Warning>

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X DELETE "https://api.ya.onl/v1/products/9876/options/10/values/100" \
        -H "X-API-Key: yv_live_v1_sua_api_key"
      ```

      ```python Python theme={null}
      response = httpx.delete(
          f"https://api.ya.onl/v1/products/{product_id}/options/10/values/100",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
      )
      ```

      ```javascript Node.js theme={null}
      await fetch(
        `https://api.ya.onl/v1/products/${productId}/options/10/values/100`,
        {
          method: "DELETE",
          headers: { "X-API-Key": "yv_live_v1_sua_api_key" },
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Excluir opção">
    <Warning>
      Excluir uma opção também exclui todos os seus valores. As variantes associadas a esses valores podem ficar em estado inconsistente.
    </Warning>

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X DELETE "https://api.ya.onl/v1/products/9876/options/10" \
        -H "X-API-Key: yv_live_v1_sua_api_key"
      ```

      ```python Python theme={null}
      response = httpx.delete(
          f"https://api.ya.onl/v1/products/{product_id}/options/10",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
      )
      ```

      ```javascript Node.js theme={null}
      await fetch(
        `https://api.ya.onl/v1/products/${productId}/options/10`,
        {
          method: "DELETE",
          headers: { "X-API-Key": "yv_live_v1_sua_api_key" },
        }
      );
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Excluir produto completo">
    <Warning>
      Excluir um produto exclui **todas** as suas variantes, opções, valores de opção e media. Essa ação não pode ser desfeita.
    </Warning>

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X DELETE "https://api.ya.onl/v1/products/9876" \
        -H "X-API-Key: yv_live_v1_sua_api_key"
      ```

      ```python Python theme={null}
      response = httpx.delete(
          f"https://api.ya.onl/v1/products/{product_id}",
          headers={"X-API-Key": "yv_live_v1_sua_api_key"},
      )
      ```

      ```javascript Node.js theme={null}
      await fetch(`https://api.ya.onl/v1/products/${productId}`, {
        method: "DELETE",
        headers: { "X-API-Key": "yv_live_v1_sua_api_key" },
      });
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Produto Simples (sem variações)

Nem todos os produtos têm tamanhos ou cores. Mesmo assim, todo produto requer pelo menos **uma opção e uma variante**. Use um nome genérico para a opção.

<CodeGroup>
  ```bash cURL theme={null}
  # 1. Criar produto
  curl -X POST "https://api.ya.onl/v1/products" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{"catalog_id": 1, "name": "Dona Glaseada", "description": "Dona artesanal con glaseado de azúcar", "status": "published"}'

  # 2. Criar opção genérica
  curl -X POST "https://api.ya.onl/v1/products/9877/options" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{"name": "Presentación", "values": ["Estándar"]}'

  # 3. Criar variante única
  curl -X POST "https://api.ya.onl/v1/products/9877/variants" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{"name": "Dona Glaseada", "base_price": 5.00, "currency": "PEN", "option_values": [200]}'

  # 4. Adicionar imagem
  curl -X POST "https://api.ya.onl/v1/products/9877/variants/600/media" \
    -H "X-API-Key: yv_live_v1_sua_api_key" \
    -H "Content-Type: application/json" \
    -d '{"title": "Dona Glaseada", "url": "https://cdn.example.com/dona-glaseada.jpg"}'
  ```

  ```python Python theme={null}
  import httpx

  headers = {"X-API-Key": "yv_live_v1_sua_api_key"}
  base = "https://api.ya.onl/v1"

  # 1. Criar produto
  response = httpx.post(f"{base}/products", headers=headers, json={
      "catalog_id": 1, "name": "Dona Glaseada",
      "description": "Dona artesanal con glaseado de azúcar", "status": "published",
  })
  product_id = response.json()["id"]

  # 2. Criar opção genérica
  response = httpx.post(f"{base}/products/{product_id}/options", headers=headers,
      json={"name": "Presentación", "values": ["Estándar"]})
  value_id = response.json()["values"][0]["id"]

  # 3. Criar variante única
  response = httpx.post(f"{base}/products/{product_id}/variants", headers=headers,
      json={"name": "Dona Glaseada", "base_price": 5.00, "currency": "PEN", "option_values": [value_id]})
  variant_id = response.json()["id"]

  # 4. Adicionar imagem
  httpx.post(f"{base}/products/{product_id}/variants/{variant_id}/media", headers=headers,
      json={"title": "Dona Glaseada", "url": "https://cdn.example.com/dona-glaseada.jpg"})
  ```

  ```javascript Node.js theme={null}
  const headers = { "X-API-Key": "yv_live_v1_sua_api_key", "Content-Type": "application/json" };
  const base = "https://api.ya.onl/v1";

  // 1. Criar produto
  const prodRes = await fetch(`${base}/products`, {
    method: "POST", headers,
    body: JSON.stringify({ catalog_id: 1, name: "Dona Glaseada",
      description: "Dona artesanal con glaseado de azúcar", status: "published" }),
  });
  const productId = (await prodRes.json()).id;

  // 2. Criar opção genérica
  const optRes = await fetch(`${base}/products/${productId}/options`, {
    method: "POST", headers,
    body: JSON.stringify({ name: "Presentación", values: ["Estándar"] }),
  });
  const valueId = (await optRes.json()).values[0].id;

  // 3. Criar variante única
  const varRes = await fetch(`${base}/products/${productId}/variants`, {
    method: "POST", headers,
    body: JSON.stringify({ name: "Dona Glaseada", base_price: 5.0, currency: "PEN", option_values: [valueId] }),
  });
  const variantId = (await varRes.json()).id;

  // 4. Adicionar imagem
  await fetch(`${base}/products/${productId}/variants/${variantId}/media`, {
    method: "POST", headers,
    body: JSON.stringify({ title: "Dona Glaseada", url: "https://cdn.example.com/dona-glaseada.jpg" }),
  });
  ```
</CodeGroup>

<Info>
  O nome da opção é livre: `"Apresentação"`, `"Tipo"`, `"Unidade"`, etc.
</Info>

## Erros Comuns

Erros de validação (`422`) retornam um body com detalhes do campo que falhou:

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "option_values"],
      "msg": "List should have at least 1 item",
      "type": "too_short"
    }
  ]
}
```

<AccordionGroup>
  <Accordion title="422 — &#x22;option_values must have at least 1 item&#x22;">
    Você está criando uma variante sem `option_values` ou com uma lista vazia. Você deve criar opções primeiro com `POST /v1/products/{product_id}/options` e usar os IDs dos valores retornados.
  </Accordion>

  <Accordion title="Criar variantes antes de opções">
    Se tentar criar uma variante antes de ter criado opções, não terá IDs de valores disponíveis para o campo `option_values`. Sempre crie opções primeiro.
  </Accordion>

  <Accordion title="Usar nome em vez de tag_id para categorias">
    O endpoint `POST /v1/products/{product_id}/categories` requer `tag_ids` (lista de IDs numéricos), não nomes de categoria. Primeiro crie a categoria com `POST /v1/categories` e use o `id` retornado.
  </Accordion>

  <Accordion title="Esquecer catalog_id ao criar produto">
    O campo `catalog_id` é obrigatório ao criar um produto. Obtenha seu catálogo com `GET /v1/catalogs`.
  </Accordion>

  <Accordion title="IDs de option_value inválidos">
    Os IDs de `option_values` devem corresponder a valores do mesmo produto. Usar IDs de outro produto ou IDs inexistentes resultará em erro.
  </Accordion>

  <Accordion title="Tentar alterar option_values de uma variante existente">
    `PATCH /v1/products/{product_id}/variants/{variant_id}` não aceita `option_values`. Os valores de opção de uma variante são atribuídos apenas na criação. Se precisar corrigi-los, exclua a variante e crie-a novamente com os valores corretos.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.