---
title: "Create, archive and restore brands"
description: "Add a brand, archive it, list the archived brands and restore one, with the plan rules that apply."
---

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

# Create, archive and restore brands

These calls create a brand, archive it and restore an archived brand. Every call takes your API key, and calls inside a workspace also name the workspace. Deleting a brand archives it, and an archived brand can be restored at any time.

## Before you start

Send your API key on every call as `Authorization: Bearer <your-tarkle-key>`. Calls that work inside a workspace also send `X-Workspace-Key` with that workspace's 8-character key. `GET /workspaces` needs only the API key, and it lists the workspace keys your key reaches.

Every API key holds every scope except `billing:purchase`, so it holds `brands:create`, the scope these calls use. The person the key acts as must be an owner or admin of the workspace named in `X-Workspace-Key`. A key limited to chosen workspaces gets `403 no_access` for any other workspace. Writes also accept an [`Idempotency-Key`](/docs/api/idempotency).

The examples below read the key and the workspace key from shell variables:

```bash
export TARKLE_KEY="<your-tarkle-key>"
export WORKSPACE_KEY="<workspace-key>"
```

## Create a brand

`POST /brands` adds a brand. `name`, `summary` and `industry` are required. Every other field is optional. The fields are the same as in [Update a brand](/docs/api/brands/update-a-brand), plus `slug`.

```bash
curl -X POST -H "Authorization: Bearer $TARKLE_KEY" -H "X-Workspace-Key: $WORKSPACE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Bank", "summary": "Business banking for small firms", "industry": "Finance"}' \
  https://tarkle.com/api/v1/brands
```

The call answers `201` with the whole brand, as `GET /brands/{brand}` shows it, and a `Location` header with the brand's address.

- **Slug.** The slug defaults to the name: lowercase letters, numbers and single hyphens, 48 characters at most. Send `slug` to choose another. A slug that another brand in the workspace already uses answers `409 name_taken`.
- **Limits.** `name` takes 48 characters, `summary` 200 and `story` 2,000. A longer value is refused with `400 invalid_request`, never cut.
- **Always a private draft.** `access`, `is_draft` and `confirm_public` are refused on create. A new brand is a private draft. Set who can open it afterwards with `PATCH /brands/{brand}`. Going public needs `confirm_public: true` in that call.
- **Password.** `password` can be set on create. It must be at least 8 characters and at most 72 bytes. The password is stored as a hash, and the brand's `access` reads `password` when one is set.
- **Pictures.** A team member's photo is given as `photo_url` in `team`. A guideline section's pictures are given as `images`, each with a `url`, a `kind` and a `caption`. Addresses must be https. A request fetches up to 12 pictures, and Tarkle fetches each one from its address and stores it with the brand. When the request names a picture, the response lists each one in `pictures`, with `ok` and, for a picture that failed, an `error`. A failed picture leaves the saved brand in place.
- **Domains.** Connect a custom domain after the brand exists, with the [brand domain endpoints](/docs/api/brands/domain).
- **Plan brand page limit.** Free allows one brand page for the whole organization. Pro and Agency allow unlimited brand pages. [Brand page plans and limits](https://tarkle.com/help/branding/brand-page-plans-and-limits) explains the plans. Archived brands do not count toward the limit. At the limit the call answers `403 forbidden`, and `details.entitlement` is `BRAND_PAGE_LIMIT`.

### Errors on create

A missing or empty value, or a value that is not in its list, is refused with [`invalid_request`](/docs/api/errors/invalid_request) (`400`). The `detail` message names the field.

| Answer | When | Message |
| --- | --- | --- |
| `400 invalid_request` | `name` is missing or empty | `name is required` |
| `400 invalid_request` | `summary` is missing or empty | `summary is required when creating a brand` |
| `400 invalid_request` | `industry` is missing or empty | `industry is required when creating a brand` |
| `400 invalid_request` | `summary` and `industry` are both missing or empty | `summary and industry are required when creating a brand` |
| `400 invalid_request` | `access`, `confirm_public` or `is_draft` is sent | `access is not accepted when creating a brand. A new brand is a private draft; set it with PATCH /brands/{brand}` (the message names the field sent) |
| `400 invalid_request` | `password` is shorter than 8 characters or longer than 72 bytes | `password must be at least 8 characters`, or `password must be at most 72 bytes` |
| `400 invalid_request` | `industry`, `size` or `company_type` is not in its list | `industry must be one of:` (or `size` or `company_type`), then the whole list separated by `; ` |
| `409 name_taken` | the slug is used by another brand in the workspace | `That page address is already used in this workspace` |

`size` and `company_type` can be left out. When they are sent, they must be one of the values below. Case and extra spaces do not matter in these three fields: `finance` is stored as `Finance`.

## Values for industry, size and company type

`industry`, `size` and `company_type` take exactly one of the values below. [Update a brand](/docs/api/brands/update-a-brand) checks these three fields against the same lists.

**Industry**

- Arts and Entertainment
- Business and Consumer Services
- Community and Society
- Computer Electronics and Technology
- E-commerce and Shopping
- Finance
- Food and Drink
- Gambling
- Games
- Health
- Heavy Industry and Engineering
- Hobbies and Leisure
- Home and Garden
- Jobs and Career
- Law and Government
- Lifestyle
- Luxury
- News and Media
- Pets and Animals
- Reference Materials
- Science and Education
- Sports
- Travel and Tourism
- Vehicles

**Size**

- 1 employee
- 2-10 employees
- 11-50 employees
- 51-200 employees
- 201-500 employees
- 501-1000 employees
- 1001-5000 employees
- 5001-10,000 employees
- 10,001+ employees

**Company type**

- Educational
- Government Agency
- Non-Profit
- Partnership
- Privately Held
- Public Company
- Self-Employed
- Self-Owned

## Archive a brand

Deleting a brand archives it. `DELETE /brands/{brand}` takes the brand offline and keeps a copy that [restore](#restore-a-brand) can bring back. The API never deletes a brand for good, so archive is the only delete. `{brand}` is the brand's id or its slug. The call needs `confirm_delete: true`, in the JSON body or as `?confirm_delete=true`. Without it the call answers `400 confirmation_required` and changes nothing.

```bash
curl -X DELETE -H "Authorization: Bearer $TARKLE_KEY" -H "X-Workspace-Key: $WORKSPACE_KEY" \
  -H "Content-Type: application/json" -d '{"confirm_delete": true}' \
  https://tarkle.com/api/v1/brands/acme-bank
```

The answer is `200` with `archived: true`, and the brand's `id`, `slug`, `name`, `archived_at` and `domains`. The `domains` list holds the domains the brand had, which are now detached.

- **What goes offline.** The brand leaves the brand list, so `GET /brands/{brand}` answers `404 not_found`. The brand no longer counts toward the plan's brand page limit, and its slug is free for a new brand.
- **Domains.** The domains are detached at once and are not restored. Connect them again after a restore.
- **What the archive keeps.** The brand's settings and its password, its logos, colors, images and asset files. Access requests and analytics are not part of the archive.
- **How long.** An archived brand stays in the archive until you restore it.
- **Activity.** The archive is recorded in the workspace Activity as `brand.archived`, with the name of the key that made the call.

## List archived brands

`GET /archived-brands` lists the brands archived through the API in this workspace, newest first. Each item has `id`, `slug`, `name`, `archived_at` and `domains`. The list is not paged. It returns the newest 100 archived brands.

```bash
curl -H "Authorization: Bearer $TARKLE_KEY" -H "X-Workspace-Key: $WORKSPACE_KEY" \
  https://tarkle.com/api/v1/archived-brands
```

## Restore a brand

`POST /archived-brands/{brand}/restore` puts an archived brand back with the same id and content. `{brand}` is the brand's id from the list above, and it must be a UUID. The body is optional. Send `slug` to restore the brand under another address.

```bash
curl -X POST -H "Authorization: Bearer $TARKLE_KEY" -H "X-Workspace-Key: $WORKSPACE_KEY" \
  -H "Content-Type: application/json" -d '{"slug": "acme-bank-2"}' \
  https://tarkle.com/api/v1/archived-brands/$BRAND_ID/restore
```

| Answer | Meaning |
| --- | --- |
| `200` | The brand is back. The body is the whole brand, as `GET /brands/{brand}` shows it. |
| `400 invalid_request` | `{brand}` is not a UUID, or `slug` is not a valid address. |
| `403 forbidden` | The workspace is at its brand page limit. |
| `404 not_found` | No archived brand with that id in this workspace. |
| `409 name_taken` | The slug is used by another brand now. Send another `slug`. |

A restore is recorded in the workspace Activity as `brand.restored`. To fill in the restored brand's text, colors and team, use [Update a brand](/docs/api/brands/update-a-brand).

Source: https://tarkle.com/docs/api/brands/create-and-delete/index.mdx
