# Domain routes: authenticate, benchmark, claim, connect

URL: /code/api/domain/verbs · Id: `page:code/api/domain/verbs`

> The Domain Verbs authenticate, benchmark, claim, connect as api.sb routes, with inputs, result, refusals and an example.

Reference for [Domain](/business/nouns/domain), one group of [Domain routes](/code/api/domain).

### Domain.authenticate
Authenticate writes a Domain’s SPF, DKIM and DMARC records and verifies them before its first send. [Verb page](/business/nouns/domain/authenticate?interface=api).

```text
POST /{namespace}/domains/{domain}/authenticate
```

Path: `domain`. Body, as JSON: the other inputs. Emits [`Domain.authenticated`](/business/events/Domain.authenticated).

**Inputs**

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `domain` | [Domain](/business/nouns/domain) | Yes | The sending Domain. |
| `dmarc` | `string` | No | The DMARC policy; it starts at `none` with reports and tightens to `quarantine`. |

**Returns**

| Output | Type | Required | Description |
| --- | --- | --- | --- |
| `domain` | [Domain](/business/nouns/domain) | Yes | The Domain, authenticated. |

**Refuses when**

| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | None. |

**Example**

```bash
curl -X POST https://api.sb/kilnbakery.com/domains/domain_VbYut4CTsH/authenticate \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
```

```json
{
  "api": "https://api.sb/kilnbakery.com",
  "domain": {
    "$id": "https://api.sb/kilnbakery.com/domains/domain_VbYut4CTsH",
    "$type": "Domain",
    "hostname": "kilnbakery.com",
    "role": "canonical",
    "state": "verifying"
  },
  "action": {
    "$id": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k",
    "operation": "Domain.authenticate",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k"
  }
}
```

### Domain.benchmark
Benchmark measures a Domain’s estimated traffic, ranking Keywords, authority and referring domains beside the competitors named. [Verb page](/business/nouns/domain/benchmark?interface=api).

```text
POST /{namespace}/domains/benchmark
```

Body, as JSON: the inputs. Emits [`Domain.benchmarked`](/business/events/Domain.benchmarked).

**Inputs**

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `hostname` | `string` | Yes | The name to measure: the Startup’s own or a competitor’s. |
| `competitors` | `string[]` | No | Names to measure beside it. |

**Returns**

| Output | Type | Required | Description |
| --- | --- | --- | --- |
| `readings` | `json` | Yes | One measure per name, each with its method and observation time. |
| `domain` | [Domain](/business/nouns/domain) | Yes | The Domain measured. |

**Refuses when**

| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | None. |

**Example**

```bash
curl -X POST https://api.sb/kilnbakery.com/domains/benchmark \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"taxcalc.tools"}'
```

```json
{
  "api": "https://api.sb/kilnbakery.com",
  "readings": {},
  "domain": {
    "$id": "https://api.sb/kilnbakery.com/domains/domain_VbYut4CTsH",
    "$type": "Domain",
    "hostname": "kilnbakery.com",
    "role": "canonical",
    "state": "verifying"
  },
  "action": {
    "$id": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k",
    "operation": "Domain.benchmark",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k"
  }
}
```

### Domain.claim
Claim gives a Startup a one-label name under an issuing Domain, or assigns it a held Domain through an approved Change. [Verb page](/business/nouns/domain/claim?interface=api).

```text
POST /{namespace}/domains/claim
```

Body, as JSON: the inputs. Emits [`Domain.claimed`](/business/events/Domain.claimed).

**Inputs**

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `hostname` | `string` | Yes | The name to claim. |
| `startup` | [Startup](/business/nouns/startup) | Yes | The Startup it serves. |

**Returns**

| Output | Type | Required | Description |
| --- | --- | --- | --- |
| `domain` | [Domain](/business/nouns/domain) | Yes | The claimed Domain. |

**Refuses when**

| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | None. |
| A label under an issuing Domain whose `publicSuffix` is false | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | None. |
| Reserved labels such as `www`, `api`, `admin`, `mail`, `mcp`, `docs` and sibling Brands | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | None. |

**Example**

```bash
curl -X POST https://api.sb/kilnbakery.com/domains/claim \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"kilnbakery.headless.ly","startup":"startup_ROlZw7tNIz"}'
```

```json
{
  "api": "https://api.sb/kilnbakery.com",
  "domain": {
    "$id": "https://api.sb/kilnbakery.com/domains/domain_VbYut4CTsH",
    "$type": "Domain",
    "hostname": "kilnbakery.com",
    "role": "canonical",
    "state": "verifying"
  },
  "action": {
    "$id": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k",
    "operation": "Domain.claim",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k"
  }
}
```

### Domain.connect
Connect attaches a hostname a Startup already holds and verifies ownership through DNS. [Verb page](/business/nouns/domain/connect?interface=api).

```text
POST /{namespace}/domains/connect
```

Body, as JSON: the inputs. Emits [`Domain.connected`](/business/events/Domain.connected).

**Inputs**

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `hostname` | `string` | Yes | The hostname to attach. |
| `startup` | [Startup](/business/nouns/startup) | Yes | The Startup it serves. |
| `tenant` | [Tenant](/business/nouns/tenant) | No | The Tenant it serves, when a Customer connects its own name. |

**Returns**

| Output | Type | Required | Description |
| --- | --- | --- | --- |
| `domain` | [Domain](/business/nouns/domain) | Yes | The connected Domain. |

**Refuses when**

| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| The input does not match the schema of the operation. | [`invalid-input`](/code/api/errors/invalid-input) | Read the schema of the operation, then send every required field with the right type. | None. |
| The key is valid, but its scopes do not allow this operation. | [`forbidden`](/code/api/errors/forbidden) | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. | None. |
| The record changed since it was read, so the write would overwrite a newer version. | [`conflict`](/code/api/errors/conflict) | Read the record again, then retry the write against its current state. | None. |
| A wildcard name for a Tenant, and past the Tenant’s name count follows its Entitlement’s `atBound` | [`refused`](/code/api/errors/refused) | Clear what the check names, then call it again. | None. |

**Example**

```bash
curl -X POST https://api.sb/kilnbakery.com/domains/connect \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"kilnbakery.com","startup":"startup_ROlZw7tNIz"}'
```

```json
{
  "api": "https://api.sb/kilnbakery.com",
  "domain": {
    "$id": "https://api.sb/kilnbakery.com/domains/domain_VbYut4CTsH",
    "$type": "Domain",
    "hostname": "kilnbakery.com",
    "role": "canonical",
    "state": "verifying"
  },
  "action": {
    "$id": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k",
    "operation": "Domain.connect",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/kilnbakery.com/actions/act_0y76a1jB6k"
  }
}
```