---
title: "Create a product"
method: POST
path: "/api/v1/commerce/products"
tags: ["commerce"]
---

# Create a product

`POST /api/v1/commerce/products`

## Request

- Base URL: `https://app.blueticked.com`
- URL: `https://app.blueticked.com/api/v1/commerce/products`
- Auth: HTTP bearer

Add a product to the shop.

`price` is in rands and is stored as cents (`price_cents`), rounded to the nearest cent.

Omit `stock_quantity` to leave stock untracked; the storefront then never shows a sold-out state for it.

`sku` is unique per organization; a duplicate returns 409.

`images` is the product's gallery in order, up to 12; the first is the cover, shown on the shop shelf, and `image_url` always repeats it. Each image needs an https `url` and `alt` text (a short description, up to 250 characters). An image you uploaded with the upload call also sends its `path`, which must be your own business's file.

Send `images` or `image_url` (one cover image), never both. Blueticked never fetches an image link; it only shows it.

## Request body

- object
  - `name` string, required
  - `description` string
  - `price` number
  - `sku` string
  - `stock_quantity` number
  - `image_url` string, nullable: One cover image (https). Not with images.
  - `images` object[]: The gallery in order; the first is the cover. Not with image_url.
    - `url` string, required: https only.
    - `path` string, nullable: The upload call's path, for your own uploaded file.
    - `alt` string, required

## Response `200`

Success

- object
  - `ok` boolean, required
  - `product` object, required
    - `compare_at_cents` number, nullable, required
    - `id` string, uuid, required
    - `name` string, required
    - `slug` string, nullable, required
    - `description` string, nullable, required
    - `price_cents` number, nullable, required
    - `currency` string, required
    - `image_url` string, nullable, required
    - `images` object[], required
      - `url` string, required
      - `storage_path` string, nullable, required
      - `alt` string, required
      - `sort` number, required
    - `sku` string, nullable, required
    - `stock_quantity` number, nullable, required
    - `source` string, required
    - `source_ref` string, nullable, required
    - `is_active` boolean, required
    - `created_at` string, date-time, required
    - `variants` object[], required
      - `id` string, uuid, required
      - `compare_at_cents` number, nullable, required
      - `name` string, required
      - `price_cents` number, nullable, required
      - `stock_quantity` number, nullable, required
      - `is_active` boolean, required
      - `sort` number, required

## Other responses

- `400`: Validation failed
- `401`: Unauthorized: missing or invalid API key
- `402`: Insufficient wallet balance
- `403`: Forbidden: scope, plan limit, or suspension
- `404`: Not found
- `409`: Conflict (idempotency-key reuse or resource in use)
- `413`: Request body above the endpoint's size limit
- `422`: Understood but refused: the request is well-formed, the action is not permitted for this resource
- `429`: Rate limited
- `500`: Internal error
- `502`: An upstream provider refused or failed the request
- `503`: Channel or send queue unavailable

---

[API](https://skmtc.dev/blueticked/apis/blueticked-api.md) · [All operations](https://skmtc.dev/blueticked/apis/blueticked-api/llms.txt) · [OpenAPI document](https://skmtc.dev/blueticked/apis/blueticked-api/revisions/07132284f4ff?raw)
