> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://tieback.io/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://tieback.io/docs/_mcp/server.

# API: Identifiers

> Read and write product identifiers programmatically, covering GTIN, EAN, UPC and SKU assignment, retirement history and idempotent write behaviour.

> **Programmatic access — early access**
>
> The
>
> **tie*back***
>
> API is available to selected workspaces during early access. Endpoints in production today are
> authenticated with an authenticated session. Standalone API-key access is being onboarded per
> workspace. Contact
>
> **tie*back***
>
> to enable API credentials for your workspace.

## What It Does

The Identifiers API provides two RPCs for managing product identifiers: one for reading all identifiers (active and retired) and one for creating or updating identifiers.

## Who It's For

API integrators and automated systems that need to manage product identifiers programmatically.

## Reading Identifiers

### `list_product_identifiers`

Returns all identifiers for a product, including both active and retired entries.

**Required inputs:**

| Parameter     | Type | Description                      |
| ------------- | ---- | -------------------------------- |
| `_brand_id`   | UUID | The brand the product belongs to |
| `_product_id` | UUID | The product to query             |

**What it returns:**

A JSON object containing:

```json
{
  "ok": true,
  "product_id": "<uuid>",
  "identifiers": [
    {
      "identifier_type": "gtin",
      "identifier_value": "05060012345678",
      "identifier_value_normalized": "05060012345678",
      "status": "active",
      "created_at": "2026-01-15T10:00:00Z",
      "created_by": "<uuid>",
      "deactivated_at": null,
      "deactivated_by": null
    }
  ]
}
```

**Key details:**

* Results are ordered: active identifiers first, then most recently retired.
* Numeric types (GTIN, EAN, UPC) include both `identifier_value` (raw stored value) and `identifier_value_normalized` (digits-only presentation value).
* SKU values have the same raw and normalised value.

**Authentication:** Required. The caller must be authenticated and have access to the specified brand.

## Writing Identifiers

### `set_product_identifier`

Creates or updates an identifier for a product. If an active identifier of the same type already exists, it is retired and replaced.

**Required inputs:**

| Parameter          | Type   | Description                         |
| ------------------ | ------ | ----------------------------------- |
| `_brand_id`        | UUID   | The brand the product belongs to    |
| `_product_id`      | UUID   | The product to update               |
| `_identifier_type` | String | One of: `sku`, `gtin`, `ean`, `upc` |
| `_raw_value`       | String | The new identifier value            |

**What it returns:**

```json
{
  "ok": true,
  "product_id": "<uuid>",
  "identifier_type": "gtin",
  "identifier_value": "05060012345678",
  "status": "active"
}
```

**Key details:**

* **SKU**: routed through the SKU alias swap mechanism with case-insensitive uniqueness.
* **GTIN / EAN / UPC**: routed through the numeric alias helper with digits-only normalisation.
* The previous active identifier (if any) is automatically retired.
* Cached fields (`products.sku`, `products.gtin`) are updated automatically via write-through.

**Authentication:** Required. The caller must be authenticated and hold an admin role for the specified brand.

## Limits & Notes

* Both RPCs require authentication; they are not callable by unauthenticated or anonymous users.
* Write access requires the admin role, read access requires brand membership.
* Identifier type is case-insensitive on input but stored in a canonical form.
* An identifier value cannot be shared across products within the same brand and type while active.

## FAQ

#### Can I read identifiers without admin access?

Yes. `list_product_identifiers` requires brand access (any role), not specifically admin.

#### What happens if I set the same value that's already active?

The operation is idempotent for the same value, no unnecessary retire/create cycle occurs.

#### Can I reactivate a retired identifier?

Not directly via this API. Setting the same value again effectively creates a new active entry.

## Related Docs

* [Product Identifiers](/product-module/identifiers)
* [API: Products](/api-reference/api-products)
* [Resolver and GS1 Digital Link](/product-module/resolver-gs-1-digital-link)
* [GS1 Digital Link Contract](/product-module/gs-1-digital-link-contract)