This page is the text of the tarkle-brand-api agent skill.
The skill file itself is SKILL.md with this front matter:
name: tarkle-brand-api
description: Create, update, publish, archive and restore Tarkle brand pages through the Tarkle API, including brand files, brand domains and brand webhooks. Use when a task manages a workspace's brand pages from code or from an agent, or when you must choose between the Tarkle MCP server and the API.Use this skill to manage Tarkle brand pages (logo, color, font and guideline pages that a workspace shares with clients) from code or an agent. Check facts in the live OpenAPI file before relying on this text: GET https://tarkle.com/api/v1/openapi.json describes the paths and the error codes.
API or MCP?
| You hold | You can do |
|---|---|
| A Tarkle API key, made in Settings > API | Everything in this skill. |
The same key in an MCP client, sent as Authorization: Bearer <your-tarkle-key> to https://mcp.tarkle.com/mcp |
The MCP brand tools: read a brand, check and connect a brand’s domain, create a draft brand and update a brand. |
| Browser sign-in (OAuth), with no key | The same MCP brand tools. |
A key marked Legacy does not open the MCP server: create a new key for it. Never put a key in a prompt, a file in the repository or a log.
Your API key
Only the organization’s owners and admins can open Settings > API. It has two tabs, API keys and Webhooks.
To make a key, click Create, enter a Name, choose Access, then click Create again. Access is All workspaces or Only selected workspaces. With the second choice, pick the workspaces the key may reach. The new key is shown once, in the API key created dialog: click it to copy, then click Done.
A key does everything the API and the MCP server can do in the workspaces it reaches, reading and writing. It acts as the person who made it. No key can make purchases. A brand call also needs that person to be an owner or admin of the workspace.
The key’s menu (Key actions) has Copy token, Rename and Delete. Owners and admins can copy a key again from there. Delete stops the key at once. A key marked Legacy was made before API keys had full access and cannot be copied: create a new key instead.
A key made before API keys had full access keeps working for the calls its access covers. A call it lacks answers 403 forbidden, and the answer names what is missing. A key that has no access at all answers 403 token_without_scopes: create a new key.
Every call
- Base URL
https://tarkle.com/api/v1. HeaderAuthorization: Bearer <your-tarkle-key>. - Header
X-Workspace-Key: <8 character key>on every call inside a workspace.GET /workspaceslists the keys the key can use. A workspace id is refused with400 workspace_key_required. - A key limited to selected workspaces gets
403 no_accessin any other workspace. - The key acts as the person who created it. For brand calls that person must be an owner or admin of the workspace, otherwise
403 forbidden. - A brand in
{brand}is its id (uuid) or its slug. A brand of another workspace is404 not_found. - Add
Idempotency-Key: <uuid>to aPOST,PATCH,PUTorDELETEyou may repeat. The same key with the same request returns the first answer. A reused key with a different request is422 idempotency_key_reused. - Errors are
application/problem+json. Branch oncode, not on the message. On429, waitRetry-Afterseconds. - Brand calls allow 120 requests a minute per key.
Recipes
Create a brand and fill it in
POST /brands {"name": "Acme Bank", "slug": "acme-bank", "summary": "Business banking for small firms", "industry": "Finance"}.name,summaryandindustryare required. Limits: summary 200 characters, story 2,000 characters. Do not sendaccess,is_draftorconfirm_public: a new brand is a private draft.PATCH /brands/{brand}with the fields that change, such as text, links, colors,download_approval,trackingand SEO fields.- Upload the brand’s files (below).
- To publish,
PATCH {"is_draft": false}. Read the brand withGET /brands/{brand}and check it is complete first. - To open it to everyone,
PATCH {"access": "public", "confirm_public": true}. Withoutconfirm_publicthe call answers400 confirmation_required. Ask the user before you do it.
Upload a file (three steps)
POST /brands/{brand}/files {"slot": "icon", "size": <bytes>, "filename": "icon.png"}. Slots:icon,main_logo,banner,social_image,favicon,logo(an extra logo),asset(a collection file),team_photoandguideline_image. The answer holds thefile_id, anuploadaddress toPUTthe file to and acomplete_url.PUTthe bytes toupload.url.POST /brands/{brand}/files/{file_id}/complete. Logo, asset and team photo uploads take more fields. See Upload brand files.
- Types and sizes: icons, main and extra logos take PNG, JPEG, WebP or SVG up to 10 MB, and guideline images take the same. Banners, social images and team photos take PNG, JPEG or WebP up to 10 MB. A favicon takes PNG, JPEG, WebP, SVG or ICO up to 2 MB. Collection files take any type up to 100 MB.
- A file whose contents are not what its name says answers
422 invalid_file, and the stored file is removed.
Connect a domain
PUT /brands/{brand}/domain {"domain": "brand.example.com"} takes a plain hostname, with no https://, path, port or spaces. The answer lists the dns_records to add at the domain’s DNS host. Show them to the user before you go on.
409 domain_takenmeans another brand, or another part of Tarkle, already uses the domain.DELETE /brands/{brand}/domaindisconnects the domain. Ask the user before you remove a domain.
Archive and restore
DELETE /brands/{brand} with {"confirm_delete": true} archives the brand. Without confirm_delete the call answers 400 confirmation_required. Ask the user before you archive. A brand is restored with POST /archived-brands/{brand}/restore.
Listen for changes
POST /webhooks {"url": "https://...", "events": ["brand.updated"]} adds an endpoint. Each request is signed with the endpoint’s signing secret.
Verify each request with its Tarkle-Signature header, t=<unix seconds>,v1=<hex>. The v1 value is an HMAC-SHA256 of <t>.<raw body> made with the secret. Reject a t more than 5 minutes old, and accept the request when one v1 value matches.
Events: brand.updated (brand edits), brand.downloaded (downloads), brand.request.created (new access requests), brand.request.approved and brand.request.rejected. brand.viewed (page views) is sent only when an endpoint names it: “all events” does not include it.
Rules for agents
- Read before you write:
GET /brands/{brand}and show the user what will change. Send only the fields that change. - Confirm with the user before: making a brand public, archiving a brand, removing a domain, deleting a webhook.
- Treat test data as real: use a clearly named test brand and archive it when you are done.
- Do not call the API from browser code. A key in a page is a leaked key.
- Not in the API: setting a password on an existing brand. Only
POST /brandstakes a password.