Skip to Content
APIEndpointsUpdate brand profile

Update brand profile

Updates the brand’s identity and descriptions: name, industry, primary audience, aliases, short and detailed descriptions, key features and main market. These are the same fields the Identity and Descriptions tabs of the Brand Profile page edit, and they land in the same place.

This is a PATCH, not a PUT. Send only the fields you want to change: omit a field to leave it alone, or pass null to clear it. There is no whole-document replace on this API, because one that silently cleared the fields you did not send would be a data-loss bug wearing the right verb.

Requires the write:brand_profile scope, and the workspace must be enabled for API writes.

PATCH /v1/brands/{brand_id}/profile

Authorization

HeaderTypeRequired
AuthorizationBearer asky_sk_…required
Idempotency-Keystringrequired

Path parameters

ParameterTypeRequiredDescription
brand_iduuidrequiredFrom List brands

Query parameters

None.

Any parameter you pass returns 400 invalid_request naming the offending key, rather than being ignored silently.

Body

application/json. At least one field is required — an empty body returns 400 invalid_request rather than reporting success for a call that changed nothing.

FieldTypeRequiredDescription
namestring, 1–100 charsoptionalMay also rename the workspace. See Notes
industrystring | null, up to 200 charsoptionalUsed for positioning and competitor benchmarks
primary_audiencestring | null, up to 200 charsoptionalWho the brand serves first
main_marketstring | null, up to 100 charsoptional
short_descriptionstring | null, up to 1000 charsoptionalConcise summary
descriptionstring | null, up to 5000 charsoptionalDetailed description
aliasesstring[] | null, max 50optionalOther names the brand is referenced by. null or [] clears them
key_featuresstring[] | null, max 50optionalnull or [] clears them

Every limit matches what the Brand Profile page enforces, so a value written here is one the page can save back.

Request

curl --request PATCH \ --url 'https://api.askylabs.com/v1/brands/242546de-4cee-4a7d-952e-f6aa60c63ef8/profile' \ --header 'Authorization: Bearer <api-key>' \ --header 'Idempotency-Key: <unique-per-attempt>' \ --header 'Content-Type: application/json' \ --data '{"industry":"B2B SaaS - AI Search Optimization Platforms","primary_audience":"B2B marketers"}'

Response

{ "data": { "profile": { "name": "Asky", "aliases": ["Asky Labs"], "industry": "B2B SaaS - AI Search Optimization Platforms", "short_description": "AI search visibility monitoring.", "description": "Asky tracks how brands appear across AI search engines…", "primary_audience": "B2B marketers", "main_market": "Europe", "key_features": ["Visibility tracking", "Competitor benchmarks"] } }, "request_id": "req_7d21b0af59c34e18b6ac" }

Response fields

The complete profile after the change, so you can put it straight into a cache without a follow-up read. The shape matches the corresponding fields of Get brand profile.

FieldTypeDescription
data.profile.namestringrequired
data.profile.aliasesstring[]required. [] when none
data.profile.industrystring | nullrequired
data.profile.short_descriptionstring | nullrequired
data.profile.descriptionstring | nullrequired
data.profile.primary_audiencestring | nullrequired
data.profile.main_marketstring | nullrequired
data.profile.key_featuresstring[]required. [] when none
data.workspace_renamedbooleanpresent only when name changed. false when the workspace has several brands and was deliberately left alone
request_idstringrequired. Also returned as the x-request-id header

Errors

StatusCodeWhen
400invalid_requestAn unknown field, a value over its limit, or a body with no fields
401invalid_tokenThe key is missing, malformed, or does not exist
403plan_requiredThis workspace is not enabled for API writes
403insufficient_scopeThe key lacks write:brand_profile, or is brand-restricted and attempted a rename. The message distinguishes them
404not_foundThe brand does not exist, or this key is not allowed to reach it. The two are deliberately indistinguishable
409conflictThe brand has no analysed profile yet, so there is nothing to update
429rate_limitedOver 60 requests per minute. See the Retry-After header

Notes

Renaming the brand may also rename its workspace, on exactly the same rule the app uses: only when the workspace holds a single active brand, and the workspace becomes "{name} Workspace". A workspace with several brands is left alone, because renaming a shared workspace after one of its brands would be wrong. data.workspace_renamed reports which happened, read back from the database rather than assumed.

Because that reaches an entity above the brand, a key restricted to specific brands may not do it: renaming would let a credential deliberately narrowed to one brand change the workspace it lives in. Such a key gets 403 insufficient_scope with a message naming that reason, and every other field still updates normally. A key with access to all brands behaves exactly like the app.

The workspace rename runs after the brand rename and is reported separately as data.workspace_renamed. false is the normal answer for a multi-brand workspace and needs no action. The brand rename itself always succeeds or the call fails, so a 200 means the brand was renamed either way.

null clears, omission preserves. {"description": null} empties the detailed description; leaving description out entirely keeps whatever is there. For aliases and key_features, both null and [] clear the list.

Not editable here: domains, sitemaps, documentation sources, social profiles, connected social accounts and writing styles. Each either asserts ownership of something outside Asky, schedules crawl work, or holds credentials — none are text edits, so none sit behind this scope. Manage them in the app.

Changing the profile does not re-run anything. Prompt suggestions and alignment read the profile when they next run; updating it does not trigger a refresh, matching the app.

Idempotency-Key is required. Send a unique value per attempt and reuse it when retrying that attempt: a retry replays the original response instead of executing again. See Idempotency.

Last updated on