Brand profiles
Brand profiles endpoints of the Zanfia Workspace API, with schemas and code samples.
Brand identity (logo, colors, typography, voice) used by AI generation. Build one by hand or extract it from a website URL — extraction is asynchronous: the profile starts pending, poll it until ready. All routes require a Authorization: Bearer header — see Authentication.
List brand profiles
/brand-profilesAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/brand-profiles"{ "count": 0, "brandProfiles": [ { "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "workspaceId": "string", "createdBy": "string", "updatedBy": "string", "id": "string", "name": "string", "source": { "url": "string", "extractedAt": "2019-08-24T14:15:22Z", "extractor": "manual", "status": "pending", "stage": "crawling", "error": "string" }, "visual": { "logo": { "lightUrl": "string", "light": { "url": "string", "mediaId": "string" }, "darkUrl": "string", "dark": { "url": "string", "mediaId": "string" }, "faviconUrl": "string", "favicon": { "url": "string", "mediaId": "string" } }, "colors": { "primary": "string", "secondary": "string", "accent": "string", "background": "string", "text": "string", "palette": [ "string" ] }, "typography": { "headingFamily": "string", "bodyFamily": "string", "monoFamily": "string", "sources": [ { "family": "string", "provider": "google", "url": "string" } ] } }, "editorial": { "voice": "string", "tone": "string", "audience": "string", "valueProposition": "string", "contentPillars": [ "string" ], "sampleHeadlines": [ "string" ], "languages": [ "string" ] }, "manuallyEditedFields": [ "string" ] } ]}{ "error": "string"}Create a brand profile
/brand-profilesAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Manual creation — no source URL, no extraction. The profile lands Ready (source.extractor: manual) with empty visual/editorial blocks the caller fills in via PATCH.
Response Body
application/json
application/json
curl -X POST "https://example.com/brand-profiles" \ -H "Content-Type: application/json" \ -d '{ "name": "string" }'{ "brandProfile": { "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "workspaceId": "string", "createdBy": "string", "updatedBy": "string", "id": "string", "name": "string", "source": { "url": "string", "extractedAt": "2019-08-24T14:15:22Z", "extractor": "manual", "status": "pending", "stage": "crawling", "error": "string" }, "visual": { "logo": { "lightUrl": "string", "light": { "url": "string", "mediaId": "string" }, "darkUrl": "string", "dark": { "url": "string", "mediaId": "string" }, "faviconUrl": "string", "favicon": { "url": "string", "mediaId": "string" } }, "colors": { "primary": "string", "secondary": "string", "accent": "string", "background": "string", "text": "string", "palette": [ "string" ] }, "typography": { "headingFamily": "string", "bodyFamily": "string", "monoFamily": "string", "sources": [ { "family": "string", "provider": "google", "url": "string" } ] } }, "editorial": { "voice": "string", "tone": "string", "audience": "string", "valueProposition": "string", "contentPillars": [ "string" ], "sampleHeadlines": [ "string" ], "languages": [ "string" ] }, "manuallyEditedFields": [ "string" ] }}{ "error": "string"}Extract a brand from a URL
/brand-profiles/extractAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Schedules ASYNC brand extraction from a URL. The response returns the profile immediately with source.status: pending; the background runner flips it to ready/failed and fills the visual/editorial blocks — poll GET /brand-profiles/:brandProfileId to observe the result. With brandProfileId set, re-extracts into the existing profile; its manuallyEditedFields are preserved. If enqueueing fails the returned profile is already failed (with source.error set) instead of pending.
Response Body
application/json
application/json
curl -X POST "https://example.com/brand-profiles/extract" \ -H "Content-Type: application/json" \ -d '{ "url": "string" }'{ "brandProfile": { "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "workspaceId": "string", "createdBy": "string", "updatedBy": "string", "id": "string", "name": "string", "source": { "url": "string", "extractedAt": "2019-08-24T14:15:22Z", "extractor": "manual", "status": "pending", "stage": "crawling", "error": "string" }, "visual": { "logo": { "lightUrl": "string", "light": { "url": "string", "mediaId": "string" }, "darkUrl": "string", "dark": { "url": "string", "mediaId": "string" }, "faviconUrl": "string", "favicon": { "url": "string", "mediaId": "string" } }, "colors": { "primary": "string", "secondary": "string", "accent": "string", "background": "string", "text": "string", "palette": [ "string" ] }, "typography": { "headingFamily": "string", "bodyFamily": "string", "monoFamily": "string", "sources": [ { "family": "string", "provider": "google", "url": "string" } ] } }, "editorial": { "voice": "string", "tone": "string", "audience": "string", "valueProposition": "string", "contentPillars": [ "string" ], "sampleHeadlines": [ "string" ], "languages": [ "string" ] }, "manuallyEditedFields": [ "string" ] }}{ "error": "string"}Get a brand profile
/brand-profiles/{brandProfileId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Response Body
application/json
application/json
curl -X GET "https://example.com/brand-profiles/string"{ "brandProfile": { "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "workspaceId": "string", "createdBy": "string", "updatedBy": "string", "id": "string", "name": "string", "source": { "url": "string", "extractedAt": "2019-08-24T14:15:22Z", "extractor": "manual", "status": "pending", "stage": "crawling", "error": "string" }, "visual": { "logo": { "lightUrl": "string", "light": { "url": "string", "mediaId": "string" }, "darkUrl": "string", "dark": { "url": "string", "mediaId": "string" }, "faviconUrl": "string", "favicon": { "url": "string", "mediaId": "string" } }, "colors": { "primary": "string", "secondary": "string", "accent": "string", "background": "string", "text": "string", "palette": [ "string" ] }, "typography": { "headingFamily": "string", "bodyFamily": "string", "monoFamily": "string", "sources": [ { "family": "string", "provider": "google", "url": "string" } ] } }, "editorial": { "voice": "string", "tone": "string", "audience": "string", "valueProposition": "string", "contentPillars": [ "string" ], "sampleHeadlines": [ "string" ], "languages": [ "string" ] }, "manuallyEditedFields": [ "string" ] }}{ "error": "string"}Update a brand profile
/brand-profiles/{brandProfileId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Partial update. Top-level keys touched by patch are recorded in manuallyEditedFields on the doc so re-extraction preserves them. visual and editorial replace their whole block (logo MediaRef siblings are merged back server-side). Same patch contract as the dashboard (UpdateBrandProfileRequestDTO).
Response Body
application/json
application/json
curl -X PATCH "https://example.com/brand-profiles/string" \ -H "Content-Type: application/json" \ -d '{ "patch": {} }'{ "brandProfile": { "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "workspaceId": "string", "createdBy": "string", "updatedBy": "string", "id": "string", "name": "string", "source": { "url": "string", "extractedAt": "2019-08-24T14:15:22Z", "extractor": "manual", "status": "pending", "stage": "crawling", "error": "string" }, "visual": { "logo": { "lightUrl": "string", "light": { "url": "string", "mediaId": "string" }, "darkUrl": "string", "dark": { "url": "string", "mediaId": "string" }, "faviconUrl": "string", "favicon": { "url": "string", "mediaId": "string" } }, "colors": { "primary": "string", "secondary": "string", "accent": "string", "background": "string", "text": "string", "palette": [ "string" ] }, "typography": { "headingFamily": "string", "bodyFamily": "string", "monoFamily": "string", "sources": [ { "family": "string", "provider": "google", "url": "string" } ] } }, "editorial": { "voice": "string", "tone": "string", "audience": "string", "valueProposition": "string", "contentPillars": [ "string" ], "sampleHeadlines": [ "string" ], "languages": [ "string" ] }, "manuallyEditedFields": [ "string" ] }}{ "error": "string"}Delete a brand profile
/brand-profiles/{brandProfileId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Response Body
application/json
application/json
curl -X DELETE "https://example.com/brand-profiles/string"{ "brandProfileId": "string", "deleted": true}{ "error": "string"}Was this article helpful?

