---
title: "Create product"
method: POST
path: "/products"
tags: ["Products"]
---

# Create product

`POST /products`

## Request

- Base URL: `https://api.crevio.co/v1`
- URL: `https://api.crevio.co/v1/products`
- Auth: API key in header `Authorization`

Creates a new product. A product can't be set to `active` until it has at least one price variant — create it as `draft` (the default), add a price variant via POST /price_variants, then PATCH the product to `active`.

## Headers

- `Idempotency-Key` string

## Request body

- ProductRequest
  - `name` string
  - `status` 'draft' | 'active' | 'archived': A product can't be set to `active` until it has at least one price variant. Create it as `draft` (or omit — `draft` is the default), add a price variant via POST /v1/price_variants, then PATCH the product to `active`.
  - `description` string
  - `body_html` string
  - `slug` string
  - `button_cta` string, nullable
  - `available_from` string, date-time, nullable
  - `available_until` string, date-time, nullable
  - `tax_code` string, nullable
  - `images` string[]: MediaLibrary file ids (e.g. `file_abc123`) to set as the product gallery; the first is the cover. Replaces the existing gallery — an empty array clears it. Create files via POST /v1/files or POST /v1/images/generate.
  - `seo` object: Search-engine metadata for the product page, in the same shape it is returned. Omitted keys are left unchanged.
    - `title` string, nullable: Meta title for the product page. Aim for 60 characters or fewer; `null` clears it.
    - `description` string, nullable: Meta description for the product page. Aim for 160 characters or fewer; `null` clears it.

## Response `201`

Product created

- Product
  - `id` string, required
  - `object` string, required
  - `name` string, required
  - `slug` string, required
  - `status` 'draft' | 'active' | 'archived', required
  - `description` string, required
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `metadata` object, required
  - `body_html` string, required
  - `button_cta` string, nullable, required
  - `url` string, required
  - `available_from` string, date-time, nullable, required
  - `available_until` string, date-time, nullable, required
  - `published_at` string, date-time, nullable, required
  - `reviews_count` integer, required
  - `average_rating` number, nullable, required
  - `seo` union: ID by default, full object when expanded
    - string
    - Seo
      - `title` string, nullable, required
      - `description` string, nullable, required
  - `media_gallery` MediaGalleryItem[], required
    - `id` string, required
    - `type` string, required
    - `category` 'image' | 'video' | 'external', required
    - `url` string, required
  - `price_variants` PriceVariant[], required
    - `id` string, required
    - `object` string, required
    - `name` string, required
    - `amount` integer, nullable, required
    - `amount_type` 'free' | 'fixed' | 'custom', required
    - `billing_type` 'subscription' | 'one_time' | 'payment_plan', required
    - `recurring_interval` 'day' | 'week' | 'month' | 'year' | 'null', nullable, required
    - `interval_count` integer, required
    - `installment_count` integer, nullable, required
    - `setup_fee_amount` integer, nullable, required
    - `trial_period_days` integer, nullable, required
    - `revoke_after_days` integer, nullable, required
    - `quantity_available` integer, nullable, required
    - `archived` boolean, nullable, required
    - `position` integer, required
    - `hidden` boolean, nullable, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `currency` string, nullable, required
    - `discounted_from_amount` integer, nullable, required
    - `minimum_amount` integer, nullable, required
    - `maximum_amount` integer, nullable, required
    - `preset_amount` integer, nullable, required
    - `waitlist` boolean, required
    - `benefits` string[]
    - `purchase_url` string, required
    - `product` string, required
  - `reviews` Review[]
    - `id` string, required
    - `object` string, required
    - `rating` integer, required
    - `customer_name` string, nullable, required
    - `content` string, nullable, required
    - `created_at` string, date-time, required
    - `customer_image_url` string, nullable, required

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Forbidden
- `422`: Validation error
- `429`: Rate limit exceeded — 600 requests per minute per credential. Retry after the number of seconds in `Retry-After`.
- `500`: Internal server error

---

[API](https://skmtc.dev/crevio/apis/crevio-api-v1.md) · [All operations](https://skmtc.dev/crevio/apis/crevio-api-v1/llms.txt) · [OpenAPI document](https://skmtc.dev/crevio/apis/crevio-api-v1/revisions/2219f18ad651?raw)
