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

# Manage Product Serials

> Register, list, update, and delete a product's serialized units (GS1 serial numbers) -- the programmatic equivalent of the dashboard's product serials page.

Programmatic equivalent of the dashboard's `products/<gtin>/serials/` page.

## When to use

* A brand owner wants individual units (GS1 AI 21) of a product on record, optionally tied
  to the lot they came from.
* A serial's dates or lot need correcting.
* A serial was registered by mistake and needs removing.

## Auth

`X-API-Key` header or OAuth token. The caller must be a member of the product's
organization with the contribute role (Owner, Manager or Editor). A read-only key is
refused with `403`; a product or serial another organization owns answers `404`, so the
API never confirms it exists.

## Flow

```
GET    /products/api/v1/products/{gtin}/serials
POST   /products/api/v1/products/{gtin}/serials
GET    /products/api/v1/products/{gtin}/serials/{serial_id}
PATCH  /products/api/v1/products/{gtin}/serials/{serial_id}
DELETE /products/api/v1/products/{gtin}/serials/{serial_id}
POST   /products/api/v1/products/{gtin}/serials/register-observed
```

* **List** -- every serial on the product, paginated.
* **Create** -- the body carries `serial` (1 to 20 printable ASCII characters, no spaces)
  and optionally `lot_id` (a lot of this same product), `production_date`,
  `expiration_date` and `best_before_date`; fields are listed in the OpenAPI document at
  `/products/api/v1/openapi.json`.
* **Update** -- `PATCH` only the fields to change; `lot_id: null` detaches the unit from
  its lot.
* **Delete** -- removes one serial permanently.
* **Register observed** -- records a serial a scan was seen carrying; repeating it is
  harmless.
* **Read back** -- every write returns the saved serial; list again to confirm.

## Errors

`403` for a read-only key, or when the free plan's serial allowance is used up (the body
carries an `upgrade_url`); `404` for a product, serial or `lot_id` the caller cannot see;
`409` for a serial the product already has; `422` for an invalid value or an empty update.

## Notes

The fields a brand writes on a serial are defined once on the model
(`ProductSerial.BRAND_EDITABLE_FIELDS`); the dashboard form and the API schemas are pinned
to that set (the model's `lot` is `lot_id` on the wire).


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