URL: /code/data/organizations/resolve · Id: `page:/code/data/organizations/resolve`

# Organization.resolve

> Turn one clue, a visitor’s IP address, an email address or a company name, into the one company it belongs to.

`POST https://api.sb/{your-domain}/organizations/resolve`

Turn one clue, a visitor’s IP address, an email address or a company name, into the one company it belongs to.

- **Price:** Free
- **Success rate:** 99.97% of 419,320 calls
- **Freshness:** Fresh for 30 days
- **Emits:** `Organization.resolved`
- **Capability:** [Enrichment](https://startupbuilder.dev/systems/sales/enrichment)

```text title="Run it · Ask"
Which company is behind the visit from 203.0.113.42? Spend up to 1¢.
```

```ts title="Run it · SDK"
import { $ } from 'startup-builder'

const result = await $.try.Organization.resolve({ ip: '203.0.113.42', maxCost: 0.01 })
```

```json title="Run it · Response"
{
  "organization": {
    "name": "Crestline Residential",
    "hostname": "crestline-residential.com",
    "industry": "Real estate",
    "headcount": 61,
    "country": "US",
    "region": "US-TX",
    "confidence": 0.78
  },
  "matchedOn": "ip",
  "created": false,
  "observedAt": "2026-10-27T14:02:11Z",
  "method": "estimated"
}
```

## Options and prices
| You get | Input that selects it | Price | Success rate |
| --- | --- | --- | --- |
| The company behind a visit | `{"ip":"…"}` | About 1¢ a match | 100% of 2,492 calls |
| The company behind an email address | `{"email":"…"}` | Free | 99.97% of 419,320 calls |
| The company behind a name | `{"name":"…"}` | Free | 99.97% of 419,320 calls |

## Inputs
| Name | Type | Meaning |
| --- | --- | --- |
| `ip` | `string` | A visitor’s IP address. Pass exactly one of `ip`, `email`, `name` or `hostname`. |
| `email` | `string` | An email address; its domain is matched. A free-mail address returns `organization: null` at $0. |
| `name` | `string` | A company name as a person typed it. |
| `hostname` | [`Hostname`](/code/data/types#hostname) | A domain, to find the saved Organization it belongs to. |
| `save` | `boolean` | Create the Organization in your records when none matches. Saving is a write, so it follows the call’s Mode. Default `false`. |

## Outputs
| Field | Type | What `null` means |
| --- | --- | --- |
| `organization` | `Organization \| null` | No company matched the clue: a residential or mobile IP, a free-mail address, or an unknown name. Free. |
| `organization.confidence` | `number`, in score 0 to 1 | Never null when `organization` is set. |
| `matchedOn` | `'ip' \| 'email' \| 'name' \| 'hostname'` | Never null: the clue that matched. |
| `created` | `boolean` | Never null: `true` only when `save` created the Organization. |
| `observedAt` | `string`, in ISO 8601 | Never null. |
| `method` | `Observed['method']` | Never null. An IP match reads `'estimated'`. |

## Read the result
| Field | Value | What it means | What to do |
| --- | --- | --- | --- |
| `organization` | `null` on an IP | Most visits from home and mobile networks resolve to no company. | Read the share of company visits per page, not per visit; it costs nothing. (the single IP route) |
| `confidence` | Under 0.6 on an IP | A shared office or a co-working network. | Treat it as a lead to check, never as a person to write to. (our planning number) |
| `organization.hostname` | A company that fits your customer | Someone there read your pages. | Find the person at it with `Prospect.find`, then write within a day. (the visitor rule in Find customers) |

## Effects
**Action class**

None: it reads, so no approval rule names it

**Modes**

- `try`: Runs the read and returns real rows; nothing is saved and nothing is billed.
- `send`: Returns a pending Action at once; its Event carries the rows when the read finishes.
- `do`: Waits for the read and returns the rows, billed per result.

**Idempotency**

The same `Idempotency-Key` with the same input replays the first answer at $0; with other input it returns 409.

**Saved or shared**

Nothing unless `save` is passed. A company match is shared across startups; the IP address and the visit stay yours.

**Emits**

`Organization.resolved` with `{ organization, matchedOn, created }`

**Performed by**

[Prospector](https://startupbuilder.dev/agents/sales/prospector)

**Price**

Free. Free: a name or a company email, an IP address that matches no company. 300 company visits in a month: 300 × 1¢ a match is about $3.00.

**Reliability**

The first route succeeds 99.97% of 419,320 calls. If it fails, the call refuses with `sources-busy` and nothing is spent.

**Freshness**

A reading younger than 30 days returns at $0. Readings are shared across startups for the same subject and locale.

**Batch and pages**

Up to 1 clue a call. It answers in one response.

**Rate**

[The shared rate rules](/code/data#rate): 10 calls a second per key, and an array input counts as one call.

## Refuses when
This call has no refusals of its own. Every data call can also meet [the shared data-call refusals](/code/refusals#data-calls): [`filter-unsupported`](/code/refusals#filter-unsupported), [`input-missing`](/code/refusals#input-missing), [`limit-exceeded`](/code/refusals#limit-exceeded), [`max-cost`](/code/refusals#max-cost), [`rate-limited`](/code/refusals#rate-limited), [`sources-busy`](/code/refusals#sources-busy), [`venue-unsupported`](/code/refusals#venue-unsupported).

## When it waits
Returns in one response; nothing waits.

## Example

**Ask**

```text
Which company is behind the visit from 203.0.113.42? Spend up to 1¢.
```

**API**

```bash
curl -X POST "https://api.sb/leaseline.app/organizations/resolve?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ip":"203.0.113.42","maxCost":0.01}'
```

The response is the one in the Run it window above.

**CLI**

```bash
npx startup-builder do Organization.resolve --try --data '{"ip":"203.0.113.42","maxCost":0.01}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Organization.resolve({ ip: '203.0.113.42', maxCost: 0.01 })"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const result = await $.try.Organization.resolve({
  ip: '203.0.113.42',
  maxCost: 0.01,
})
```

To retry, send the same `Idempotency-Key`: the retry returns the first answer for $0. A new key reads again.

A `sk_test_` key answers these the same way every time, at $0 ([every test value](/code/data#test-values)).

| Test value | Always returns | What it is for |
| --- | --- | --- |
| `maxCost: 0.0001` | Refuses with [`max-cost`](/code/refusals#max-cost) | Any priced call with a maxCost of 0.0001 is refused before it spends: the price is above the cap. |
| `rate-limited.test` | Refuses with [`rate-limited`](/code/refusals#rate-limited) | Any call naming this hostname answers 429 with Retry-After, so your retry logic runs. |
| `sources-busy.test` | Refuses with [`sources-busy`](/code/refusals#sources-busy) | Any call naming this hostname answers 503 as if every route were busy, and nothing is spent. |

## Used by
- **Workflows:** [Inbound routing](/capabilities/convert-visitors/inbound-routing) · [Who is visiting](/capabilities/convert-visitors/whos-visiting)
- **Jobs:** [Convert visitors](/capabilities/convert-visitors) · [Find your first customers](/capabilities/find-customers)

## Related
[`Organization.count`](/code/data/organizations/count) · [`Organization.find`](/code/data/organizations/find) · [`Organization.enrich`](/code/data/organizations/enrich)