POST /v1/sites/:id/logo
Replace the site’s nav + footer logo on a site that’s already deployed.
This is a pure file swap — the existing favicon stays as-is (call POST /v1/sites/:id/favicon separately if you also want a new favicon), and the brand color palette / overall style stay unchanged. If you want the palette to chase the new logo, follow up with a revision like "match my colors to my new logo".
Cost: free — deterministic operation, no LLM call.
Why this exists
Revisions are HTML-content edits driven by the AI; they cannot swap an asset file. This endpoint is the only way to point a deployed site at a different logo image without rebuilding from scratch.
Request
curl -X POST https://api.warpweb.ai/v1/sites/<site-id>/logo \
-H "Authorization: Bearer wwk_..." \
-H "Content-Type: application/json" \
-d '{ "source": { "url": "https://example.com/my-logo.png" } }'Body
| Field | Type | Required | Description |
|---|---|---|---|
source.url | string | one of (url, sitePhotoId) | Public http(s):// URL of the new logo image. Fetched server-side via the SSRF-safe downloader; private IPs and non-image content types are rejected. |
source.sitePhotoId | string (uuid) | one of (url, sitePhotoId) | UUID of a row from this site’s site_photos catalog. Useful to promote a logo the classifier already found (subject="logo_or_brand") without re-uploading. Cross-site reuse is blocked with 403 — the row must belong to this site. |
Response (success)
{
"ok": true,
"logoPath": "images/logo.png",
"deployedUrl": "https://acme-plumbing-abc123.pages.dev",
"hint": "Logo swapped. The existing favicon was NOT regenerated; call POST /v1/sites/:id/favicon if you want a new favicon. Brand colors / style also unchanged — follow up with POST /v1/sites/:id/revisions (\"match my colors to my new logo\") if you want the palette to chase the logo."
}| Field | Description |
|---|---|
logoPath | Relative path to the new logo on the deployed site (images/logo.<ext>). Extension reflects the source content-type — png / svg / jpg / webp. |
deployedUrl | Cloudflare Pages preview URL of the freshly redeployed site. Custom domains aliased to this project pick up the change automatically. |
hint | Reminder of what was NOT changed by this call (favicon, brand colors). |
Errors
| Status | Body | Cause |
|---|---|---|
400 | { "error": "source.url or source.sitePhotoId required" } | Body missing both source variants. |
400 | { "error": "source.url must be http(s)://" } | URL scheme isn’t http or https. |
400 | { "error": "logo_download_failed", "detail": "..." } | SSRF guard rejected the URL, network error, or response wasn’t an image. |
403 | { "error": "sitePhotoId does not belong to this site" } | The given sitePhotoId exists but belongs to a different site. |
404 | { "error": "sitePhotoId not found" } | No row matches the given UUID. |
404 | { "error": "site_not_found" } | Site id doesn’t exist, OR the API key’s user doesn’t own this site (the two cases are masked to avoid leaking ownership). |
500 | { "error": "logo_swap_failed", "detail": "..." } | Unexpected server-side failure (image write, deploy, etc.). Safe to retry — operation is idempotent. |
Related
POST /v1/sites/:id/favicon— swap the favicon independently of the logoGET /v1/sites/:id/research— returns thesite_photoscatalog withidvalues you can use assitePhotoIdPOST /v1/sites/:id/revisions— to restyle colors after a logo swap