| Signup field | Brand response path |
|---|---|
| Company Name | brand.title |
| Company Description | brand.description |
| Company Logo | brand.logos[].url |
| Website | brand.domain |
| Address | brand.address.{street,city,country,postal_code} |
brand.socials[type=linkedin].url | |
| Industry | brand.industries.eic[0].industry |
- Set up a backend proxy
- Call the Brand API on email submission
- Render the prefilled fields with edit controls
- Add prefetch to keep the cache warm
Prerequisites
- A Context.dev API key
- The Context.dev SDK for your backend:
Step 1. Set up a backend proxy
The Brand API is authenticated with a secret key. Put that key in the browser and anyone who opens devtools can copy it and run up your bill. Every call from your signup form has to go through a backend route that holds the key server-side. A minimal proxy route accepts an email from your frontend, calls/brand/retrieve-by-email, and returns the brand payload:
CONTEXT_DEV_API_KEY, calls Context.dev’s Brand API, and returns the brand object untouched; you pick fields in step 3, so new fields land without a backend deploy. Anything that isn’t a clean hit (free email, unknown domain, cold-hit timeout, or a Gmail-class address caught before the call) comes back as brand: null, which the frontend reads as “nothing to prefill, so fall through to generic onboarding.”
Step 2. Call retrieve on email submission
When the user submits the email page, hit the proxy and stash the result in form state. The next step reads from it.- Free and disposable emails have no brand. The proxy short-circuits the well-known free providers (Gmail, Yahoo, Outlook, ProtonMail, and friends) before spending a call; anything that slips past the list (disposable forwarders, lesser-known providers) returns a 422 the proxy swallows. Either way you get
brand: nulland render the generic form. - First-time domains are slow. A domain Context.dev hasn’t crawled yet runs several seconds on the first hit: 7s at p50, up to a minute at p99 (see the latency table). Step 4 warms the cache so the call lands in under a second.
Understand the response
A successful retrieve returnsstatus, code, and a brand object. Here’s a real response for [email protected]:
brand:
| Field | Type | Notes |
|---|---|---|
title | string | Company name |
description | string | One-paragraph summary |
domain | string | Extracted from the email |
logos[] | array | Each has url, type (logo or icon), and mode (light, dark, has_opaque_background) |
colors[] | array | Each has hex and name |
socials[] | array | Each has type (e.g. linkedin) and url |
address | object | street, city, country, postal_code, plus state and country codes |
industries.eic[] | array | Each has industry and subindustry |
Structure your form to favor prefill. Put fields the API can return after fields it can’t. The gap buys the retrieve a few seconds to land, so the response is usually waiting by the time the user reaches the company step:
- Email: triggers retrieve.
- Password or OAuth: the API can’t return this.
- User’s role at the company: the API can’t return this either.
- Company logo, description, and socials: prefilled.
Step 3. Display the prefilled values
On the prefilled step, render the response with editable inputs. The user’s job is to glance, fix anything wrong, and continue.defaultValue, not value; React’s uncontrolled inputs do this correctly out of the box.
Pick the right logo variant. brand.logos[] returns multiple variants, each with a type (logo or icon) and mode (light, dark, or has_opaque_background). Filter by where you’ll display it:
| Use case | Filter |
|---|---|
| Logo on a white-background dashboard | type === "logo" and mode === "light" |
| Avatar bubble | type === "icon" and mode === "has_opaque_background" |
| Dark-mode app | type === "logo" and mode === "dark" |
logos[0]. Always show a replace affordance. The API’s pick is a default, not a verdict.
Require an explicit confirm for public-facing data. If the logo or company name will be visible to teammates or shown on a public profile, don’t auto-accept; gate it behind a “Looks right” click. The wrong logo on a competitor’s profile is worse than no logo at all.
Step 4. Prefetch on email typing (optional)
The basic version works, but the first hit on an uncrawled domain may take up to 60 seconds. To make the step transition feel instant, fire a free prefetch call while the user is still typing their email.POST /brand/prefetch-by-email queues the same crawl that retrieve would, then returns right away with { status, message, domain }. It costs zero credits and is available on paid plans, so it’s safe to call on every email-field blur.
Add a second proxy route:
Handle the cold hits that slip through
Even with prefetch, the occasional cold hit will outrun the user. Three options:- Skeleton. Render the prefilled step with a loading state, fill in when retrieve resolves. Best when the step has no other interactive elements.
- Fill on-arrive. Render the editable form with blanks; when retrieve returns, fill empty fields without animating. Don’t overwrite anything the user typed in the meantime.
- Skip silently. Show empty fields. Surface a soft “we couldn’t auto-fill this” notice if you care.
Learn more
Brand API Guide
How the Brand API works end to end, every lookup variant, and the full
profile shape.
API Reference
The retrieve-by-email endpoint: parameters, response schema, and error
codes.
Prefetching
Latency curves, cache TTLs, and the mechanics behind the prefetch endpoint.
Best Practices
Caching TTLs, override rules, never-expose-keys.