# Brand API

> Returns a company's identity from its domain: name and description, logos and icons, share images, brand colors and fonts, the type scale for body text, headings, buttons and links, social profiles and the contact details it publishes for machines. Every value says where on the site it came from.

Need a page's content rather than the company's identity? Use [Scrape](https://rankfield.dev/endpoints/scrape).

- Page: https://rankfield.dev/endpoints/brand
- Full reference: https://rankfield.dev/docs/brand/get-a-brand

## Request

`GET https://rankfield.dev/v1/brand?domain={domain}`

Send `Authorization: Bearer YOUR_API_KEY`. Get a free key at https://rankfield.dev/?tab=key#playground (no account).

```bash
curl "https://rankfield.dev/v1/brand?domain=notion.so" \
  -H "Authorization: Bearer $RANKFIELD_API_KEY"
```

Response:

```json
{
  "domain": "notion.com",
  "finalUrl": "https://www.notion.com/",
  "status": 200,
  "blocked": null,
  "name": {
    "value": "Notion",
    "source": "schema.org Organization"
  },
  "description": {
    "value": "Build Custom Agents, search across all your apps, and automate busywork. The AI workspace where teams get more done, faster.",
    "source": "schema.org Organization"
  },
  "logos": [
    {
      "url": "https://www.notion.com/front-static/logo-ios.png",
      "source": "schema.org Organization logo",
      "confidence": 0.95,
      "type": "image/png",
      "width": null,
      "height": null,
      "variant": null,
      "colors": null,
      "fallback": false
    }
  ],
  "logosReason": null,
  "wordmark": null,
  "icons": {
    "best": {
      "url": "https://www.notion.com/front-static/logo-ios.png",
      "sizes": null,
      "type": "image/png",
      "source": "link rel=apple-touch-icon"
    },
    "favicon": [
      {
        "url": "https://www.notion.com/front-static/favicon.ico",
        "sizes": null,
        "type": "image/x-icon",
        "source": "link rel=icon"
      }
    ],
    "appleTouch": [
      {
        "url": "https://www.notion.com/front-static/logo-ios.png",
        "sizes": null,
        "type": "image/png",
        "source": "link rel=apple-touch-icon"
      }
    ],
    "manifest": [],
    "maskIcon": null
  },
  "images": {
    "ogImage": {
      "url": "https://www.notion.com/front-static/meta/teams-and-agents.jpg",
      "width": null,
      "height": null,
      "alt": null,
      "type": null,
      "source": "og:image"
    },
    "twitterImage": {
      "url": "https://www.notion.com/front-static/meta/teams-and-agents.jpg",
      "alt": null,
      "source": "twitter:image"
    }
  },
  "colors": {
    "themeColor": [],
    "manifest": {
      "theme": null,
      "background": null
    },
    "cssVariables": [
      {
        "name": "--tatami-color-white",
        "value": "#fff",
        "hex": "#ffffff",
        "uses": 8,
        "stock": false
      },
      {
        "name": "--table-border",
        "value": "var(--tatami-color-gray-300)",
        "hex": "#dfdcd9",
        "uses": 7,
        "stock": false
      },
      {
        "name": "--tatami-color-red-500",
        "value": "#f64932",
        "hex": "#f64932",
        "uses": 4,
        "stock": false
      },
      "…"
    ],
    "mostUsed": [
      {
        "hex": "#ffffff",
        "count": 13,
        "neutral": true,
        "score": 70,
        "stock": false,
        "seen": [
          "button"
        ]
      },
      {
        "hex": "#dfdcd9",
        "count": 7,
        "neutral": true,
        "score": 46,
        "stock": false,
        "seen": [
          "header"
        ]
      },
      {
        "hex": "#000000bf",
        "count": 3,
        "neutral": true,
        "score": 28,
        "stock": false,
        "seen": [
          "button"
        ]
      },
      "…"
    ],
    "roles": {
      "primary": null,
      "accent": null,
      "background": {
        "hex": "#ffffff",
        "from": "body background",
        "element": "body",
        "method": "computed"
      },
      "text": {
        "hex": "#000000",
        "from": "body colour",
        "element": "body",
        "method": "computed"
      },
      "headerBackground": null
    },
    "rolesDark": null,
    "rolesReason": null
  },
  "fonts": [
    {
      "family": "NotionInter",
      "source": "@font-face",
      "uses": 3
    },
    {
      "family": "Noto Sans Arabic",
      "source": "@font-face",
      "uses": 0
    },
    {
      "family": "Noto Sans Hebrew",
      "source": "@font-face",
      "uses": 0
    },
    "…"
  ],
  "typography": {
    "method": "stylesheet",
    "viewport": {
      "width": 1280.0,
      "height": 800.0
    },
    "rootFontSize": {
      "px": 16.0,
      "basis": "html font-size 16px (body,html)"
    },
    "body": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": "16px",
        "declared": "16px",
        "px": 16.0,
        "basis": "px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": null
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for body nor on html"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": 24.0,
        "basis": "1.5 × font size 16px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": null
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for body nor on html"
      }
    },
    "h1": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": "2em",
        "declared": "2em",
        "px": 32.0,
        "basis": "1em = 16px (body)",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "h1",
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": null
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: browsers make headings bold"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": 48.0,
        "basis": "1.5 × font size 32px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for h1 nor on body"
      }
    },
    "h2": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: the browser default for h2 is 1.5em"
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: browsers make headings bold"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": null,
        "basis": null,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": "1.5 × the font size, which isn't declared"
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for h2 nor on body"
      }
    },
    "h3": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: the browser default for h3 is 1.17em"
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: browsers make headings bold"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": null,
        "basis": null,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": "1.5 × the font size, which isn't declared"
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for h3 nor on body"
      }
    },
    "h4": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: the browser default for h4 is 1em"
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: browsers make headings bold"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": null,
        "basis": null,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": "1.5 × the font size, which isn't declared"
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for h4 nor on body"
      }
    },
    "h5": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: the browser default for h5 is 0.83em"
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: browsers make headings bold"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": null,
        "basis": null,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": "1.5 × the font size, which isn't declared"
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for h5 nor on body"
      }
    },
    "h6": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: the browser default for h6 is 0.67em"
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: browsers make headings bold"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": null,
        "basis": null,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": "1.5 × the font size, which isn't declared"
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for h6 nor on body"
      }
    },
    "button": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "font: inherit",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": "16px",
        "declared": "font: inherit",
        "px": 16.0,
        "basis": "px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "weight": {
        "value": null,
        "declared": "font: inherit",
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for button nor on body"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "font: inherit",
        "px": 24.0,
        "basis": "1.5 × font size 16px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared: buttons use the browser's own control font"
      }
    },
    "link": {
      "family": {
        "value": "NotionInter, Inter, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, \"Apple Color Emoji\", Arial, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\"",
        "declared": "var(--tatami-font-family-sans)",
        "primary": "NotionInter",
        "generic": false,
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "size": {
        "value": "16px",
        "declared": "16px",
        "px": 16.0,
        "basis": "px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "weight": {
        "value": null,
        "declared": null,
        "number": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for link nor on body"
      },
      "lineHeight": {
        "value": "1.5",
        "declared": "1.5",
        "px": 24.0,
        "basis": "1.5 × font size 16px",
        "source": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
        "selector": "body,html",
        "media": null,
        "inherited": "body",
        "method": "stylesheet",
        "reason": null
      },
      "letterSpacing": {
        "value": null,
        "declared": null,
        "px": null,
        "basis": null,
        "source": null,
        "selector": null,
        "media": null,
        "inherited": null,
        "method": "stylesheet",
        "reason": "not declared for link nor on body"
      }
    }
  },
  "social": [
    {
      "network": "youtube",
      "url": "https://www.youtube.com/channel/UCoSvlWS5XcwaSzIcbuJ-Ysg",
      "source": "schema.org sameAs"
    },
    {
      "network": "facebook",
      "url": "https://www.facebook.com/NotionHQ/",
      "source": "schema.org sameAs"
    },
    {
      "network": "x",
      "url": "https://twitter.com/NotionHQ",
      "source": "schema.org sameAs"
    },
    "…"
  ],
  "contact": {
    "source": null,
    "email": null,
    "telephone": null,
    "address": null,
    "contactPoints": []
  },
  "language": {
    "code": "en",
    "script": "Latn",
    "confidence": 1.0,
    "source": "content",
    "declared": "en-us"
  },
  "fetches": [
    {
      "url": "https://notion.com/robots.txt",
      "purpose": "robots.txt",
      "status": 404,
      "bytes": null,
      "error": null
    },
    {
      "url": "https://notion.com/",
      "purpose": "page",
      "status": 200,
      "bytes": 168106,
      "error": null
    },
    {
      "url": "https://www.notion.com/_next/static/chunks/301vj_6h9dd4-.css",
      "purpose": "stylesheet",
      "status": 200,
      "bytes": 161114,
      "error": null
    },
    "…"
  ],
  "cached": false,
  "ageSeconds": 0
}
```

## Parameters

| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
| `domain` | query | string | required unless `url` |  | The company's domain, e.g. `acme.com`. A URL works too: `https://acme.com/about` means `acme.com`. Send `domain` or `url`, not both. |
| `url` | query | string | no |  | Instead of `domain`: a full URL on the site. We read the homepage, not this page. |
| `roles` | query | boolean | no | `false` | `true` computes the colour roles on a large page too. They are computed by default on pages up to about 6,000 tags and 1.6 MB of CSS (four times the earlier limit); on a larger page `colors.roles` is `null` with a reason unless you ask. On a very large page even `roles=true` can come back `null` with `over the CPU budget`. |
| `screenshot` | query | string | no |  | `viewport` or `fullPage`: also return a WebP image of the homepage as a browser shows it. |
| `viewport` | query | string | no | `desktop` | `desktop` (1366×768) or `mobile` (412×915): the screen for the screenshot. |
| `maxAge` | query | integer | no | `86400` | Seconds a stored answer may be old (default 24 hours), up to 2,592,000. `0` reads the site fresh. |
| `timeout` | query | integer | no | `20` | Seconds the call may take, 1 to 60. |

## Response

| Field | Type | Description |
|---|---|---|
| `domain, finalUrl, status` | string, string, integer | The site we read, the homepage that answered after redirects, and its HTTP status. A 404 or 500 comes back here with empty brand fields. |
| `blocked` | object \| null | The firewall that answered instead of the homepage (`{vendor, challenged, kind, signals}`). Then every brand field is empty: we never guess. |
| `name, description` | object | `{value, source}`. Sources, best first: schema.org Organization, meta tags, the web app manifest, the page title. |
| `logos, logosReason` | array, string \| null | The site's own logos, best first: `{url, source, confidence, type, width, height, variant, fallback}`, starting with the one the page shows in its header (inline SVGs as `data:` URLs with their `colors`). Never a favicon or share image, with one exception: when the page has no logo image, the site's best icon stands in as the only entry, with `fallback: true`. `variant` is `light` (drawn for dark backgrounds), `dark` or `null`. `logosReason` says why the list is empty or holds only the fallback. |
| `wordmark` | object \| null | `{text, source}`: the site's name as the page sets it in type in its link home (`KYLIAN` on kylian.ai), when that link holds no image and names the site. `null` otherwise. |
| `icons, images` | object | `best`, the one icon to show the site by (an SVG, else the largest; `null` when none is declared), then favicons, Apple touch icons, manifest icons and the mask icon; the `og:image` and Twitter image. |
| `colors` | object | `themeColor`, the manifest's colors, CSS custom properties holding colors, and `mostUsed` colors weighted by where they paint (`score`, `seen`), each with a `hex`. `stock` marks a framework's default colors (WordPress, Bootstrap, Tailwind, shadcn/ui), ranked after the site's own. |
| `colors.roles, colors.rolesDark, colors.rolesReason` | object \| null, object \| null, string \| null | The colors the page's own elements get: `primary`, `accent`, `background`, `text` and `headerBackground`, each `{hex, from, element, method: "computed"}`, and the same in dark mode when the site has one. On a large page `roles` is `null` unless you send `roles=true`; `rolesReason` says why. |
| `fonts` | array | `{family, source, uses}`: Google Fonts, `@font-face`, Adobe Fonts, then fonts the CSS names. |
| `typography` | object \| null | The type scale at 1280×800, from the site's own stylesheets: `body`, `h1` to `h6`, `button` and `link`, each with `family`, `size`, `weight`, `lineHeight` and `letterSpacing`. Each value is `{value, declared, px, basis, source, selector, media, inherited, reason}`, with `number` for weight and `primary` and `generic` for family. `null` on a blocked or error page. |
| `social` | array | `{network, url, source}` from schema.org `sameAs` and links on the page. We never visit them. |
| `contact` | object | Email, phone, address and contact points, only from the site's own schema.org data; `null` values otherwise. |
| `language, fetches` | object, array | The homepage's language, and each request we made for this answer. |
| `screenshot` | object | With `screenshot`: a WebP image, `{format, kind, viewport, bytes, data}` (base64). |
| `cached, ageSeconds` | boolean, integer | Whether the answer came from our store, and its age. |

## Errors

Errors come as `{"error":{"code":"…","message":"…","details":{…}}}` with the HTTP status.

| Status | Code | When |
|---|---|---|
| 400 | `invalid_input` | A parameter is missing, unknown or malformed. |
| 401 | `unauthorized` | The key is missing, unknown or revoked. |
| 403 | `robots_disallowed` | robots.txt disallows Rankfield-User for the homepage; `details` has the rule and line. |
| 403 | `blocked` | The website's bot protection refused us. Reported at once and never worked around; `details` says which protection. Not counted as usage. |
| 403 | `site_excluded` | The site is on the exclusion list: Reddit, LinkedIn, Facebook, Instagram, X/Twitter and TikTok (subdomains included), Google search result pages, and sites whose owners asked us. |
| 415 | `unsupported_content_type` | The homepage is not HTML. |
| 422 | `address_not_public` | The host resolves to a private or internal address. |
| 429 | `busy` | Our fetch capacity is busy: the call was refused at once, waited 4 seconds without a turn, or its time limit ran out while it waited (then `details.reason` is `capacity`). A new job also gets it when the shared job queue is full (`Retry-After` 60). Not counted as usage. Retry after `Retry-After` seconds. |
| 500 | `internal` | Our bug. Retry. |
| 502 | `fetch_failed` | The website could not be reached (DNS, connection, TLS, more than 5 redirects or a bad one, a malformed answer); `details.reason` says which. |
| 503 | `unavailable` | The service is restarting or briefly unavailable. Retry after `Retry-After`. (A full fetch capacity answers `429` `busy`.) |
| 504 | `timeout` | The website did not answer within `timeout`. With `details.reason: "sitePace"`, the call waited its turn for this website instead, which we fetch gently, shared by all customers. Retry after `Retry-After`, or allow a longer `timeout`. |

## Price and limits

- Free; no per-call charge.
- No per-key limits. When the server is busy you get `429` `busy` with `Retry-After`.
- Only answered calls count as usage (plus the website errors listed below); our own errors (`500`, `503`), `429` `busy` and a `504` with `details.reason` `sitePace` don't.

## Up to 10,000 domains in one job

`POST /v1/brand/jobs` with an `Idempotency-Key` header and `{"items":[{"domain":"acme.com"}, …]}`. Each item takes the same parameters as one call, except `timeout`: items use the default, 20 seconds. Every item is checked first: if any is invalid, the whole request is a `400` that lists the first 20. A new job answers `202`; the same `Idempotency-Key` with a byte-identical body returns the same job (`200`, `Idempotency-Replayed: true`), and with any other body is a `409`.

Read `GET /v1/brand/jobs/{id}/results?cursor=0&limit=100`: finished items as they complete, each `{index, ok, result}` or `{index, ok: false, error}`. Pass `cursor` back until `hasMore` is false. `POST /v1/brand/jobs/{id}/cancel` stops a job. A job runs 16 items at a time; an item that meets `busy` waits and retries by itself. Results are kept 24 hours.

Send as many jobs as you like. Jobs from all keys share one queue: when 200,000 items are already waiting, a new job answers `429` `busy` with `Retry-After` (60 seconds).

Reference: https://rankfield.dev/docs/get-started/batch-jobs

## Notes

- We read the homepage, its web app manifest, up to 4 of its own stylesheets (on its own host or its CDN) and `/favicon.ico` when the page names no icon: 8 requests at most, robots.txt included.
- Colour roles are computed on the page as fetched, without JavaScript: a page whose buttons get their colours from script gets the colours of its static HTML and CSS.
- We fetch as `Rankfield-User`, obey robots.txt on every request and redirect, run no JavaScript unless the call asks for it, use no cookies or proxies, and never work around a firewall. We fetch each site gently, shared by all customers. More: [rankfield.dev/bot](https://rankfield.dev/bot).

## MCP

Tools on https://rankfield.dev/mcp: `brand_profile`, `start_brand_job`, `get_brand_results`.
