Brand assets
Brand assets
Extracts the visual identity of each prospect from its own website: main logo, logo variants, favicon, dominant brand color, harmonic palette derived from the logo. Optional homepage screenshot. All images are re-hosted in the caller's private storage, so a link never breaks when the prospect rotates its CDN.
The module is read-only against the prospect's site — no form submission, no login, no authentication crossing.
Inputs
One row per POI. Only site_web is required; the rest is passed through.
| Field | Type | Required | Notes |
|---|---|---|---|
site_web |
string | yes | HTTP(S) URL of the prospect's website. |
nom |
string | no | Display name, surfaced in the UI. |
A batch accepts 1 to 10 000 rows. Rows without site_web are dropped before the job is enqueued.
Job-level options:
| Option | Type | Default | Notes |
|---|---|---|---|
source_job_id |
string | null | Parent job in the pipeline chain. |
capture_screenshot |
bool | false | Adds a homepage screenshot. ~5x slower per row. |
Outputs
Per-row output. Local URLs point to assets re-hosted under /api/brand-assets/<owner_user_id>/<sha256>.<ext> and served only to the owner (or an admin).
| Column | Type | Notes |
|---|---|---|
logo_url |
string | Source URL of the main logo as found on the prospect's site. |
logo_local_url |
string | Re-hosted copy of the main logo, stable URL. |
logo_source |
string | Where the logo was picked up (e.g. og:image, JSON-LD, apple-touch). |
logo_variants_local_urls |
list | Re-hosted alternate marks: apple-touch, mask-icon, monochrome, etc. |
favicon_url |
string | Source URL of the highest-quality favicon detected. |
favicon_local_url |
string | Re-hosted copy of the favicon. |
brand_color |
string | Dominant brand color as a hex string. |
brand_color_source |
string | Origin of the color (theme-color meta, logo sampling, etc.). |
brand_palette |
list | Five harmonic hex colors derived from the logo. |
screenshot_local_url |
string | Homepage screenshot. Populated only when capture_screenshot=true. |
Binaries are stored as data/brand_assets/<user_id>/<sha256>.<ext>. Allowed extensions: svg, png, jpg, jpeg, webp, gif, ico, avif. Each asset is hashed for de-duplication across rows of the same owner.
Lifecycle
Standard job states — see Jobs lifecycle. Per-row HTTP errors never fail the job: a failed row carries fetch_error and a null logo_local_url.
Pipeline
| Needs | Produces |
|---|---|
site_web |
logo_url, logo_local_url, logo_variants_local_urls, favicon_url, favicon_local_url, brand_color, brand_palette, screenshot_local_url |
pipelinable: true, slots after any step that yields site_web — most commonly a scrap parent. supports_veille: false: brand identity is a one-shot extraction, not a recurring signal.
Endpoints
Create a batch job
POST /api/jobs/brand-assets
Body:
{
"items": [
{"nom": "Stripe", "site_web": "https://stripe.com"}
],
"source_job_id": null,
"capture_screenshot": false
}
Returns a JobPublic envelope. Authentication: any active user.
Live single-domain lookup
GET /api/brand-lookup?domain=<domain>&refresh=<bool>
Single-shot, no batch job created. The first call for a given domain fetches live (~2–3s) and stores the result in a per-user cache. Subsequent calls within seven days return the cached profile instantly. refresh=true forces a re-fetch.
Response shape:
{
"domain": "stripe.com",
"cached": false,
"cached_at": null,
"profile": {
"status": "ok",
"logo_url": "...",
"logo_local_url": "...",
"logo_source": "og:image",
"logo_variants_local_urls": ["..."],
"favicon_url": "...",
"favicon_local_url": "...",
"brand_color": "#635BFF",
"brand_color_source": "theme-color",
"brand_palette": ["#635BFF", "..."],
"http_status": 200,
"final_url": "https://stripe.com/",
"fetch_error": null
}
}
Serve a re-hosted asset
GET /api/brand-assets/<owner_user_id>/<sha256>.<ext>
Per-owner isolation: only the owner (or an admin) can read assets from the namespace. Filenames are validated against a strict regex; path traversal attempts are rejected with 400.
For global quotas and caps, see Limits. Brand-lookup cache TTL: 7 days, per user, per domain. Screenshot mode multiplies per-row cost by ~5; opt-in only.
Errors
| Code | Meaning |
|---|---|
| 400 | Aucun établissement avec site web — no row carried a usable site_web. |
| 400 | Invalid domain on /api/brand-lookup. |
| 400 | Invalid asset filename on the serve endpoint. |
| 403 | Access to an asset owned by another user. |
| 502 | Live lookup failed upstream (Lookup failed: <type>: <message>). |
What's next
- techstack — detect the CMS, analytics, and frameworks behind the same
site_web. - ads_intelligence — surface the prospect's paid acquisition footprint to complement the visual identity.