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

# Create a product.

`POST /api/v1/products`

## Request

- Base URL: `https://app.tracepass.eu`
- URL: `https://app.tracepass.eu/api/v1/products`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://app.tracepass.eu/api/oauth/authorize`, token URL `https://app.tracepass.eu/api/oauth/token`, scopes: `passports:write`)

Create a product. The category template is resolved
automatically from the `category` slug — must match a
seeded category. `model` strings are unique within the
workspace.

## Headers

- `Idempotency-Key` string

## Request body

- CreateProductInput
  - `name` string, required
  - `model` string, required: Unique within the workspace.
  - `category` string, required: Seeded category slug — `batteries`, `textiles`, `jewelry`, `electronics`, `furniture`, `detergents`, `paints-coatings`, `packaging`, `toys`, `fmcg`, `tyres`, `iron-steel`, `construction`.
  - `description` string
  - `defaultFieldValues` object: Seed values for passports created from this product, keyed by template field. Each value is checked against the template: a numeric string for a number field is stored as a number, and any other value the template rejects answers 400 `Invalid default field values` with `details` (in a batch, that item's result is an error).
  - `imageUrls` string[]
  - `sourceLocale` string

## Response `201`

Product created.

- Product
  - `_id` string: MongoDB ObjectId hex string (24 chars).
  - `name` string
  - `model` string
  - `category` string
  - `templateId` string: MongoDB ObjectId hex string (24 chars).
  - `defaultFieldValues` object: Seed values for passports created from this product, keyed by template field. Each value is checked against the template: a numeric string for a number field is stored as a number, and any other value the template rejects answers 400 `Invalid default field values` with `details` (in a batch, that item's result is an error).
  - `imageUrls` string[]
  - `passportCount` integer
  - `status` 'active' | 'archived'
  - `sourceLocale` string
  - `createdAt` string, date-time
  - `updatedAt` string, date-time

## Other responses

- `400`: Validation error or malformed request.
- `401`: Missing or invalid API key.
- `403`: Plan-gate or workspace permission denied.
- `409`: Conflict — duplicate model on a product, GTIN registered to a different tenant, serial collision within a GTIN.
- `422`: Idempotency-Key reused with a different request body. Use a new key for the new request, or reuse the original body.
- `429`: Daily v1 write or passport-read budget exhausted. Resets at 00:00 UTC.

---

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