Three reads, each answering a different question about the business at a
domain. They are what makes "the account filled itself in" possible: a record
holding nothing but `priya@acme.com` can offer a name, an industry, a size
band and an address instead of an empty form.

| Call | Answers | Scope |
| --- | --- | --- |
| `connect.enrichment.company()` | What the business *does* | `enrichment:read` |
| `connect.enrichment.brand()` | What it *looks like* | `enrichment:brand` |
| `connect.enrichment.presence()` | How *findable* it is | `enrichment:presence` |

Three scopes rather than one, because the cost is not comparable: a company
read fetches a few pages, a brand extraction crawls stylesheets and may render
the site in a headless browser, and a presence scan is roughly twenty fetches
across a site's well-known paths. A key holds only what you granted it in
Console.

<Callout title="Measured, not recalled">
Every value is read off the company's own website and comes back with the URL
it came from. A field the pages never stated is `null` — not a plausible
guess. Ask a model what a company does and it will answer confidently about a
site it never opened; that is the failure mode these endpoints exist to avoid.
</Callout>

## Looking a company up

```ts
const result = await connect.enrichment.company({ email: "priya@acme.com" });

if (result.status === "enriched") {
  prefill({ name: result.profile.name, industry: result.profile.industry });
}
```

Send an `email` or a `domain` — whichever you hold. `domain` wins when both
are given.

**It is a suggestion, not a save.** Nothing is written to your store, and
nothing should be written without the person in front of it agreeing. Render
it as a prefill they can correct, which is how the same feature works
everywhere else they have seen it.

## Every call can decline

Each of the three answers a two-arm union, and the second arm is not an error:

```ts
if (result.status === "skipped") {
  // result.reason — render the form empty and move on
}
```

| Reason | Means |
| --- | --- |
| `no_domain` | Nothing to look up |
| `consumer_domain` | `founder@gmail.com` names a person, not an employer |
| `blocked_domain` | Connect will not read this one |
| `unreachable` | The site did not answer |
| `no_signal` | The pages stated nothing usable (`company`, `brand`) |
| `no_stylesheet` | Nothing to measure a brand from (`brand`) |
| `provider_unavailable` | **Connect** did not answer (`presence`) |

`unreachable` and `provider_unavailable` are worth separating in your UI. The
first is a fact about the customer's site that they may want to know; the
second is our problem and is never something to tell them about their own
site.

A successful result also carries `cached`, which says whether Connect served
it from its platform-wide cache. The profile is identical either way — it is
there for your own telemetry, not for a decision.

## Brand

```ts
const result = await connect.enrichment.brand({ domain: "acme.com" });

if (result.status === "extracted") {
  const primary = result.profile.brandKit.palette.find((c) => c.role === "primary");
}
```

Useful for white-labelling a portal to a customer's brand, pre-filling a
design brief, or showing a real account card instead of a grey placeholder.
Three things decide whether your integration works:

- **Set your client timeout to at least 90 seconds.** A cold read runs the
  whole extraction before answering and can take up to a minute. Many HTTP
  clients default to 30s and abandon a request that was about to succeed.
  Cached is the normal case — profiles are held for 90 days, so you pay the
  cold path roughly once per domain.
- **Never store `brandKit.logos[].url`.** It is a short-lived signed URL
  minted per read. Render it directly or re-read the profile; persist
  `sourceUrl` if you need something stable.
- **Check `palette[].source`.** A `css-var` entry is the company naming its
  own colour. A `frequency` entry is a ranked count of what appears most, and
  is much weaker evidence.

## Presence

How visible the business is online, scored out of 100 — by a search engine, by
a customer, and by the assistants that increasingly answer questions about a
business before anyone visits its site.

```ts
const result = await connect.enrichment.presence({ domain: "acme.com" });

if (result.status === "scanned") {
  for (const next of result.scan.recommendations) {
    console.log(`${next.priority}. ${next.title} — ${next.fix}`);
  }
}
```

- **The score is computed, not generated.** Every point comes from a check run
  against something observed, and each check ships with its weight, what was
  seen, and the URL that settles it — so the total is reconstructable. A model
  only orders `recommendations` and writes the prose; it cannot move the
  number. That is what makes this safe to show a customer.
- **A low score is a success, not a skip.** Every check failing is the most
  useful report this produces.
- **`social` is claimed, never verified.** Those are URLs the site itself
  printed; nothing proves the accounts belong to that business, so render them
  as "linked from their site". `machineReadable: false` means a real profile
  that search engines have to infer from a footer link — a specific, common
  and easily fixed finding.
- **Timeout ≥ 90 seconds**, same as brand. Scans are held for a fortnight.

## Refreshing, and who the call is attributed to

```ts
await connect.enrichment.company({ domain: "acme.com", refresh: true, asUser: sessionToken });
```

`refresh` re-reads the site even when Connect holds a fresh result. It is for
an operator pressing **Refresh** — not for automatic calls, which should take
the cache and the latency that comes with it.

`asUser` takes a member's session token and attributes the generation to their
workspace; without it the call is attributed to your application. The token
travels as a header and never reaches the request body — it is a credential,
not a field.

## Next steps

- **[API reference](/docs/api)** — the three endpoints, their request and
  response schemas, and the scope each needs.
- **[Reference](/docs/reference/server)** — `EnrichmentResource`, generated
  from source.