# Brands API Paths on this page are relative to `https://shruwd.io/api/v1`. | Method | Path | Scope | Role | |---|---|---|---| | `POST` | `/brands` | `write` | owner | | `GET` | `/brands` | `read` | viewer | | `GET` | `/brands/{brandId}` | `read` | viewer | | `PATCH` | `/brands/{brandId}` | `write` | editor | | `DELETE` | `/brands/{brandId}` | `write` | owner | `{brandId}` accepts the brand's id or its `slug`. ## Create a brand ```bash curl -X POST "https://shruwd.io/api/v1/brands" \ -H "Authorization: Bearer $SHRUWD_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Waitlister","domain":"waitlister.me","timezone":"Europe/Helsinki"}' ``` | Field | Required | Notes | |---|---|---| | `name` | Yes | How the brand is written in answers. Becomes its first matching alias | | `domain` | Yes | A URL or a bare host. Reduced to the registrable domain | | `timezone` | No | Sets the day boundary for measurements | | `contextTerms` | For short or common-word names | Words that mark a mention as being about you. See below | `https://www.acme.com/pricing` and `acme.com` resolve to the same brand. An IP address or a string with no public suffix is `422 invalid_domain`. A short or common-word name, like "Front" or "Arc", is refused with `422 context_terms_required` until you send `contextTerms` — for Front, say `["shared inbox", "customer support"]`. A mention then counts only when one of those words is near it; without them every "front-end" would count as a mention of you. The same rule applies to competitors ([Entities](https://shruwd.io/docs/api/entities.md)). Creating a brand also: - **Creates its self entity**, with the brand name as one alias and the domain attached. Nothing else can create one, and it cannot be removed. - **Plants the first cycle.** The response carries `firstCycle` as `{ cycleId, kind, scheduledFor }`, or `null`. - **Waits for prompts.** A cycle with no active prompts stays pending, so creating a brand before its prompts costs nothing. Measurement starts within minutes of the first prompts and covers only the prompts and competitors that exist then, so add [competitors](https://shruwd.io/docs/api/entities.md) first and every prompt in one call. On the free plan the response also carries `snapshot`: | Value | Meaning | |---|---| | `planned` | Your one measurement for this domain is scheduled | | `already_taken` | This domain has had its free measurement, in some workspace. The brand exists; no cycle is planned | | `null` | You are not on a snapshot plan | ### Errors | Code | Status | | |---|---|---| | `invalid_domain` · `invalid_name` · `invalid_timezone` | 422 | Bad input | | `context_terms_required` | 422 | The name is short or a common word. Send `contextTerms`; the reason is in the body | | `duplicate_domain` | 409 | An unarchived brand here already has that domain. `details` names it — `{ domain, brandId, slug, name }` | | `plan_limit` | 409 | Your plan's brand count is used up. `details` carries `{ limit, current, resource }` | Another workspace tracking the same domain is not a conflict. ## List brands ```bash curl "https://shruwd.io/api/v1/brands" \ -H "Authorization: Bearer $SHRUWD_API_KEY" ``` Each brand carries a `stats` block — open findings, the last completed and next pending cycle, the 30-day self mention rate per entitled engine, and a 56-day daily trend for the primary engine. Days below the display floor are `null` rather than a number. These come from rollups, so the list is cheap to poll compared with computing anything yourself from individual answers. ## Get one brand Returns the brand, its entitled engines, prompt and entity counts, and the same health block the dashboard shows — including the status of its Search Console connection and its log drain. ## Update a brand ```bash curl -X PATCH "https://shruwd.io/api/v1/brands/waitlister" \ -H "Authorization: Bearer $SHRUWD_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Waitlister HQ"}' ``` Only `name` and `timezone`. Both optional, at least one required — `400 empty_patch` otherwise. > **Note** > > **The domain is not editable.** It defines the brand's self entity, so a different domain > is a different brand. The `name` here is display only; what Shruwd actually matches on > lives in the brand's aliases — see [Entities](https://shruwd.io/docs/api/entities.md). A timezone change applies from the next cycle. The `slug` is stable across renames. ## Archive a brand ```bash curl -X DELETE "https://shruwd.io/api/v1/brands/waitlister" \ -H "Authorization: Bearer $SHRUWD_API_KEY" ``` Archives; nothing is deleted. Cycles stop being scheduled, history stays readable, and the domain becomes available to add again. ## Next steps - [Prompts](https://shruwd.io/docs/api/prompts.md) — the questions asked for this brand - [Entities](https://shruwd.io/docs/api/entities.md) — the brand and its competitors