---
title: "Brand API endpoints"
description: "Every Brand API call with its method, the key scope it checks, its parameters and what it returns."
---

> 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.

# Brand API endpoints

Paths are relative to `https://tarkle.com/api/v1`. Every call sends your API key as `Authorization: Bearer <your-tarkle-key>`. A call that works inside a workspace also sends `X-Workspace-Key: <workspace-key>`, the 8-character key of that workspace, which `GET /workspaces` lists. Only `GET /workspaces` and `POST /brand-lookup` work without it. To create a key, see [Authentication](/docs/get-started/authentication). The exact request and response schemas are in [`openapi.json`](https://tarkle.com/api/v1/openapi.json).

```bash
curl -H "Authorization: Bearer $TARKLE_KEY" -H "X-Workspace-Key: $WORKSPACE_KEY" "https://tarkle.com/api/v1/brands?limit=10"
```

## What the key can do here

A key acts as the person who created it, with that person's access in each workspace it reaches. Brand calls need that person to be an owner or admin of the workspace. Otherwise the answer is `403 forbidden`. A key limited to chosen workspaces answers `403 no_access` for any other workspace.

Keys have no scope picker: a key holds every scope except the one for purchases. The **Needs** column names the scope each call checks, so you can match it to an error. Brand calls allow 120 requests a minute for each key.

## Calls

| Call | Needs | What it does |
| --- | --- | --- |
| `GET /brands` | `brands:read` | The workspace's brands, newest first. `limit` (1 to 100, default 25) and `cursor`. |
| `GET /brands/{brand}` | `brands:read` | One brand in full. |
| `POST /brands` | `brands:create` | Create a brand. It is always a private draft. See [Create, archive and restore brands](/docs/api/brands/create-and-delete). |
| `PATCH /brands/{brand}` | `brands:write` | Change the fields you send. The slug, passwords and domains cannot be changed here. See [Update a brand](/docs/api/brands/update-a-brand). |
| `DELETE /brands/{brand}` | `brands:create` | Archive the brand. Needs `confirm_delete: true`. |
| `GET /archived-brands` | `brands:create` | The archived brands, newest first. They never expire. |
| `POST /archived-brands/{brand}/restore` | `brands:create` | See [Create, archive and restore brands](/docs/api/brands/create-and-delete). |
| `GET`, `PUT`, `DELETE /brands/{brand}/domain` | `brands:domains` | See [Brand domains](/docs/api/brands/domain). |
| `GET /brands/{brand}/assets` | `brands:read` | Logos, icon, banner and collection files with download links. |
| `GET /brands/{brand}/markdown` | `brands:read` | The brand as `brand.md` (`text/markdown`). |
| `GET /brands/{brand}/analytics` | `brands:read` | Views, downloads and requests. `period` is `30d` (default), `90d` or `all`. |
| `POST /brands/{brand}/files` | `brands:files` | Start an upload of one brand file. See [Upload brand files](/docs/api/brands/files). |
| `POST /brands/{brand}/files/import` | `brands:files` | Fetch a picture from a public web address and attach it, in one call. |
| `POST /brands/{brand}/files/{file}/complete` | `brands:files` | Check the uploaded file and attach it. |
| `DELETE /brands/{brand}/files` | `brands:files` | Take one file off the brand, named by `slot` in the query. |
| `GET /brands/{brand}/requests` | `brands:requests` | Download and view requests. `status`, `limit`, `cursor`. |
| `POST /brands/{brand}/requests/{request}` | `brands:requests` | Approve or reject one request. See [Access requests](/docs/api/brands/access-requests). |
| `POST /brand-lookup` | `brands:read` | Suggestions for a brand from a website address. Saves nothing and needs no workspace. |

## Create a brand

`POST /brands` needs `name`, `summary` and `industry`. `access`, `is_draft` and `confirm_public` are refused on create, because a new brand is always a private draft.

Send `password` to protect the brand from the start. It must be at least 8 characters and at most 72 bytes. Only a hash of it is stored. The password is for the API only: the MCP server does not set one when it creates a brand. The slug defaults to the name. At the plan's brand page limit the call answers `403 forbidden`, and a slug the workspace already uses answers `409 name_taken`.

## Archive and restore

`DELETE /brands/{brand}` archives the brand. The API never deletes a brand for good. The brand's page goes offline and answers `404`, the app stops listing it, and its slug and its place under the plan's brand page limit are freed. Its domains are detached and are not restored. Its files and settings are kept, and nothing removes them, so the brand can always be restored. The call answers with `archived: true` and the archived brand's `id`, `slug`, `name`, `archived_at` and `domains`.

`POST /archived-brands/{brand}/restore` puts one back with its id, where `{brand}` is that id (a uuid, or the call answers `400`). The plan's brand page limit applies as it does on create, so the call answers `403 forbidden` at the limit. If the old slug is taken now, send another `slug` in the body, otherwise the answer is `409 name_taken`. Domains are not restored; connect them again with [Brand domains](/docs/api/brands/domain). The call returns the restored brand in full.

## The list response

`GET /brands` returns `data` (an array) and `next_cursor`. Each item has `id`, `slug`, `name`, `summary`, `access`, `is_draft`, `download_approval`, `indexable`, `created_at` and `urls` (the public `page` address and the `api` address). See [Paging and limits](/docs/api/paging-and-limits).

## Fields of a brand

`GET /brands/{brand}` returns these fields.

| Field | Contents |
| --- | --- |
| `id`, `slug`, `name` | The identifiers and the name. |
| `summary`, `story` | Short description and longer story. |
| `industry`, `size`, `company_type`, `year_founded` | Company facts. |
| `website` | The brand's website address. |
| `social` | `twitter`, `facebook`, `instagram`, `linkedin`, `youtube` and `github` links. |
| `colors` | `primary` and `secondary` (or `null`) and `additional` (a list of `name` and `value`). |
| `fonts` | `headline` and `body`, each with `name`, `custom` and `source` (`google`, `adobe` or `custom`), and `css` for an Adobe font. |
| `print_values` | The CMYK and Pantone values of each color. |
| `auto_logo_variants` | Whether black and white logo downloads are made automatically. |
| `access` | `public`, `password` or `restricted`. |
| `is_draft`, `download_approval` | Whether the brand is a draft, and whether downloads need approval. |
| `indexable` | True when the page is public and not a draft. |
| `tracking` | `ga4`, `gtm`, `search_console` and `adobe_kit` IDs. |
| `seo` | `title` and `description`, each `null` when not set. |
| `team` | A `title` and a list of members with `id`, `name`, `title` and `has_photo`. |
| `press` | Links with `id`, `title`, `url`, `description`, `image` and `source`. |
| `guidelines` | Sections with `id`, `title`, `text` and `images` (each with `id`, `kind` and `caption`). |
| `urls` | `page`, `markdown`, `mark_usage` and `api` addresses. |
| `created_at` | When the brand was created. |

## Files

A brand's files can be read in two ways: from the Assets call of this API, or from the file links in the brand's own markdown. Both cover the icon, the logos and the collection files.

### Upload and remove files

Start an upload with `POST /brands/{brand}/files`, send the file to the address it returns, then call `POST /brands/{brand}/files/{file}/complete`. For a picture that is already on the web, `POST /brands/{brand}/files/import` does both steps in one call. See [Upload brand files](/docs/api/brands/files) and [Update a brand](/docs/api/brands/update-a-brand).

The `slot` is one of `icon`, `main_logo`, `banner`, `social_image`, `favicon`, `logo`, `asset`, `team_photo` or `guideline_image`. Logos and collection files need `id` (from `GET /brands/{brand}/assets`), team photos need `member_id` or `member_name`, and guideline images need `section_id` and `id`. The stored file is deleted too unless something of the brand still uses it.

### Through the API: `GET /brands/{brand}/assets`

`GET /brands/{brand}/assets` returns `brand` (`id`, `slug`), then `images` and `collections`.

- `images` lists the icon, main logo and banner that are set, each with a `role` of `icon`, `main_logo` or `banner`.
- `collections` lists each collection with `id`, `name`, `description` and `files`.

Download links expire. The response carries `links_expire: true`, so list again when you need a fresh link.

### Through the file links in brand.md

Each file in a public brand's markdown page links to `/api/brand-asset?brand=<id>&file=<key>` on the host the page is served from.

`/api/brand-asset` answers only when all of these are true:

- the brand is public, is not a draft and does not need download approval;
- the file is one of that brand's own icon, logos, collection files, guideline images or older images (when none of its collections has files).

It does not serve the banner, the social image, the favicon, the font files, the team photos or any other file of the brand. When all checks pass, the link redirects with `302` to a signed link. That signed link is valid for 7 days. A visitor address can make 300 of these requests an hour for each brand, and above that limit the answer is `429`, with a `Retry-After` header of 3600 seconds.

`GET /brands/{brand}/markdown` returns the same brand.md text without the file links. Use `GET /brands/{brand}/assets` when you need the files themselves.

## Analytics

The `series` is built from the 2,000 most recent rows of each number, so for a very busy brand it can add up to less than its `total`. `downloaded_files` holds `top_assets`, `formats` and `unrecorded` for the downloads in the period. It is `null` when that data is not available.

## Related

- [Quick start](/docs/api/brands/quick-start)
- [Create, archive and restore brands](/docs/api/brands/create-and-delete)
- [Update a brand](/docs/api/brands/update-a-brand)
- [Upload brand files](/docs/api/brands/files)
- [Brand domains](/docs/api/brands/domain)
- [Access requests](/docs/api/brands/access-requests)
- [Paging and limits](/docs/api/paging-and-limits)
- [Errors](/docs/api/errors)
- [How to manage brand pages with the Tarkle API](https://tarkle.com/help/apps-and-developers/how-to-manage-brand-pages-with-the-tarkle-api)

Source: https://tarkle.com/docs/api/brands/endpoints/index.mdx
