// Use case · Brand & design data
For onboarding flows, CRMs and white-label apps: send a domain, get its name, logos, a weighted palette with the source of each colour, its design tokens and its font stack.
credits per brand profile
10
credits per styleguide
10
credits per font report
5
{ "data": { "name": "Stripe", "colors": { "primary": "#635bff", "palette": [ { "hex": "#635bff", "source": "theme-color" } ] }, "logos": [ { "type": "apple-touch-icon" } ] }, "credits": 10} // Why
The problem
What Wayfern does
/brand returns identity, logos, a weighted palette with each colour’s source, company details and links./styleguide returns the design system: palette, type scale, radii, shadows, breakpoints and every :root token./fonts returns each family, where it is served from, its weights and formats, and the bytes it costs the page.// How it works
There is no SDK: it is one POST, and the credits field returns exactly what the call debited.
Step 1 of 4
Only a URL is required. proxy and country are optional.
{ "url": "stripe.com" }
Step 2 of 4
The page loads in a browser on a datacenter exit and is retried once on a residential exit if the site blocks it.
proxy: "auto"
Step 3 of 4
Declared sources first (theme-color, manifest, CSS variables), then rendered colours by how much of the page they cover.
colors.palette[].source
Step 4 of 4
Theme a workspace, fill a CRM row or audit a type stack. credits states the charge.
"credits": 10
// Code
The Node.js tab turns a work email into a filled-in workspace. The email-to-domain step is ordinary code in your app; what Wayfern takes is a domain.
curl -X POST https://api.wayfern.com/api/v1/brand \
-H "Authorization: Bearer wf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "url": "https://stripe.com", "proxy": "auto" }'// Three depths
Ask for the one you need: identity for a CRM row, the design system for theming, the type stack for an audit. Or all 25 credits’ worth for one domain.
POST /api/v1/brand
10 credits per profile
Who the site says it is: identity, colour, marks and links.
null when notPOST /api/v1/styleguide
10 credits per site
The design system it renders with, read off the stylesheets and the live DOM.
:rootPOST /api/v1/fonts
5 credits per site
The type stack, down to the files the page downloaded.
// Colour
Every palette entry carries a source and a weight, so you can tell a colour the site declared about itself from one that merely covers a lot of pixels. Declared entries start at weight 0 and gain weight only if the page also painted that colour.
| source | Where it was read from |
|---|---|
| theme-color | The <meta name="theme-color"> the page declares: the site naming its own brand colour. |
| manifest | theme_color and background_color from the web app manifest the page links. |
| css-variable | A colour-valued custom property declared on :root: the site’s own token, not a sampled pixel. |
| computed | Sampled off rendered elements; weight counts how many elements used it. |
theme-color
<meta name="theme-color"> the page declares: the site naming its own brand colour.manifest
theme_color and background_color from the web app manifest the page links.css-variable
:root: the site’s own token, not a sampled pixel.computed
weight counts how many elements used it.// Theming
cssVariables is the tenant’s own :root token set with values already resolved by the browser, so a var(--a, var(--b)) chain arrives as the colour it ends up being.
Apply a styleguide
const res = await fetch("https://api.wayfern.com/api/v1/styleguide", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.WF_TOKEN,
"Content-Type": "application/json"
},
body: JSON.stringify({ url: domain })
});
const { data: guide } = await res.json();
const root = document.documentElement;
// 1. The tenant's own tokens, verbatim. Keys already carry their "--" prefix,
// and the values are the resolved ones, so var() chains are collapsed.
for (const [name, value] of Object.entries(guide.cssVariables)) {
root.style.setProperty(name, value);
}
// 2. Derived signals, for the parts of your shell that need a decision.
const [accent] = guide.colors.accent;
const [tightestRadius] = guide.radii;
// Families are ranked by use and carry an inferred role: ask by role.
const families = guide.typography.families;
const heading = families.find((f) => f.role === "heading") ?? families[0];
if (accent) root.style.setProperty("--tenant-accent", accent);
if (heading) root.style.setProperty("--tenant-font", heading.stack);
if (tightestRadius) root.style.setProperty("--tenant-radius", tightestRadius);Plenty of sites declare no tokens. The report still measures the rendered page: type sizes with element counts and line heights, weights, letter spacing, radii, shadows, spacing steps and breakpoints.
/api/v1/fonts is the narrower call at 5 credits: which families, served from where, at which weights and formats, and how many bytes they cost the page.
// What it costs
The same credits that run browser sessions, scrapes and search. Rates are the same on every plan, and each response repeats the charge.
Identity, design system, type stack and a visual reference.
| Item | Credits |
|---|---|
| brand profile | 10 |
| styleguide | 10 |
| font report | 5 |
| full-page screenshot | 5 |
Total
30credits
about $0.38
at $0.0125 / credit
About 50 runs a month on Developer ($19 for 1,520 credits).
One brand profile per new work-email domain.
| Item | Credits |
|---|---|
| 100 brand profiles | 1,000 |
Total
1,000credits
about $12.50
at $0.0125 / credit
About 1 run a month on Developer ($19 for 1,520 credits).
A 1,000-domain backfill is 10,000 credits: $100 at the 20,000-credit pack rate of $0.0100 / credit. Packs do not expire, so a one-off backfill does not have to become a plan decision. Every rate is on the pricing page.
// FAQ
It comes back null, so a partial profile never poses as a complete one. Industry and founding year are read from the site’s own schema.org Organization markup; Wayfern does not assign a classification.
The declared theme-color if there is one, else the manifest’s theme colour, else the heaviest non-greyscale colour on the page, else the heaviest colour of any kind; null when none exist. The palette lists declarative sources first (theme-color, manifest, css-variable, computed) and, within a source, the heaviest first.
No. Split the work email in your own code, drop free-mail providers, and send the domain to /api/v1/brand. The Node.js tab above shows that flow.
Yes. POST /api/v1/screenshot (5 credits) captures the full page after dismissing cookie overlays, optionally in dark mode or scoped to one CSS selector. Captures are stored privately and returned as a signed URL with urlExpiresAt; store the artifact key and exchange it at /api/v1/artifacts/link for a fresh link at no cost. Screenshots are kept for 7 days.
Reports run in a real browser. proxy: "auto", the default, takes a datacenter exit first and retries on a residential one only when the site blocks it. country pins the residential exit; pair it with proxy: "residential" when a domain answers differently by region. Residential bytes are metered on top of the per-call rate.
// Keep reading
// Next step
Then run the list. Same balance and same rates, whether it is ten domains or ten thousand.