// Use case · Brand & design data

Get a domain’s logos, colours and fonts from one URL

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

POST /api/v1/brand 200 OK
{  "data": {    "name": "Stripe",    "colors": {      "primary": "#635bff",      "palette": [        {          "hex": "#635bff",          "source": "theme-color"        }      ]    },    "logos": [      { "type": "apple-touch-icon" }    ]  },  "credits": 10}
"credits" in the response
Abridged and illustrative. Every key is a real field; what a domain yields depends on what it publishes. This call debited 10 credits.

// Why

Every brand signal a domain gives away

The problem

Brand data is scattered across a site

  • Logos hide in meta tags, manifests and touch icons; colours in CSS variables and rendered pixels.
  • A flat list of hex values does not say which one is the brand.
  • Asking new users to type in company details slows every signup.

What Wayfern does

One POST per depth, with sources attached

  • /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

A domain in, a brand profile out

There is no SDK: it is one POST, and the credits field returns exactly what the call debited.

  1. Step 1 of 4

    Send a domain

    Only a URL is required. proxy and country are optional.

    { "url": "stripe.com" }

  2. Step 2 of 4

    A real browser renders it

    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"

  3. Step 3 of 4

    Signals are read and ranked

    Declared sources first (theme-color, manifest, CSS variables), then rendered colours by how much of the page they cover.

    colors.palette[].source

  4. Step 4 of 4

    Use it

    Theme a workspace, fill a CRM row or audit a type stack. credits states the charge.

    "credits": 10

// Code

Enrich a signup from its work email

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.

POST /api/v1/brand
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

Identity, design system, type stack

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.

    • name, legalName, description, slogan
    • industry and founded, from the site’s own schema.org Organization markup
    • email, phone and address when published, null when not
    • colors.primary plus a weighted palette
    • logos[] with type, format, width, height and variant
    • links.social by network; links.site for pricing, docs, careers
  • POST /api/v1/styleguide

    10 credits per site

    The design system it renders with, read off the stylesheets and the live DOM.

    • colors.palette plus text, background and accent short-lists
    • typography.families with the full stack and a role (heading, body, mono, ui)
    • a type scale: each size with element count, line height and weight
    • radii, shadows, spacing and the breakpoints in the site’s CSS
    • cssVariables: every custom property declared on :root
    • sources: which sheets the report was built from
  • POST /api/v1/fonts

    5 credits per site

    The type stack, down to the files the page downloaded.

    • family plus source: google, adobe, bunny, fontshare, self-hosted, third-party or system
    • host serving the files
    • weights, styles and the formats fetched
    • files[] with url, format and bytes
    • display and unicodeRanges from @font-face
    • usage, and totalBytes across every font file

// Colour

A palette that says where each hex came from

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.

  • theme-color

    Where it was read from
    The <meta name="theme-color"> the page declares: the site naming its own brand colour.
  • manifest

    Where it was read from
    theme_color and background_color from the web app manifest the page links.
  • css-variable

    Where it was read from
    A colour-valued custom property declared on :root: the site’s own token, not a sampled pixel.
  • computed

    Where it was read from
    Sampled off rendered elements; weight counts how many elements used it.

// Theming

Their design tokens, straight into your custom properties

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);
  • Beyond the tokens

    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.

  • Type, if that is all you need

    /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

Priced per call, from one balance

The same credits that run browser sessions, scrapes and search. Rates are the same on every plan, and each response repeats the charge.

One domain, the full kit

Identity, design system, type stack and a visual reference.

Credits for: One domain, the full kit
ItemCredits
brand profile10
styleguide10
font report5
full-page screenshot5

Total

30credits

about $0.38
at $0.0125 / credit

About 50 runs a month on Developer ($19 for 1,520 credits).

Enrich 100 signups

One brand profile per new work-email domain.

Credits for: Enrich 100 signups
ItemCredits
100 brand profiles1,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

Questions about brand data

What if the site does not publish a field?

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.

How is colors.primary chosen?

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.

Is there an email-to-company endpoint?

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.

Can I get a screenshot of the page as well?

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.

What if the domain blocks the request?

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.

// Next step

Point it at one domain to see the shape

Then run the list. Same balance and same rates, whether it is ten domains or ten thousand.