# Buy a domain

URL: /products/site/domains/buy-a-domain · Id: `guide:buy-a-domain`

> Say "buy leaseline.app" and get the Domain registered to your company, locked, renewed ahead and serving your Site with a certificate.

A [Domain](/business/nouns/domain) you buy registers to your company, serves your [Site](/business/nouns/site) and renews before it can lapse.

Needs: [Startup](/business/nouns/startup)

**Before real money moves**

- Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval).
- You leave the chat: Never: it all happens in the chat.
- First question at Idea: “Under $20 a year, or is a premium name worth it?”
- First question at Live: “Point it at the site, or hold it so no one else takes it?”
- What it costs: The registrar price for one year.
- To undo it: Release the Domain; the registration stays until it lapses.

## What you get
- 1 domain registered to your company, details kept private (Domain)
- 1 lock that stops anyone moving the domain away (Domain)
- 3 DNS records that stop others sending mail in its name (DNS Record)
- 1 certificate, renewed before it expires (Domain)
- 1 renewal 90 days ahead, kept two years paid (Domain)
- 1 site served at leaseline.app (Site)

## Your agent does
**For agents**

- Guide: `guide:buy-a-domain`, status `live`. Page: [/products/site/domains/buy-a-domain.md](/products/site/domains/buy-a-domain.md).
- Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it.
- Leaves the chat: never.
- Needs first: [Startup](/business/nouns/startup).
- Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own.

| Step | Verb | Inputs (type, required, this guide’s value) | Returns |
| --- | --- | --- | --- |
| 1 | [`Domain.search`](/business/nouns/domain/search) (`verb:Domain.search`) | `query` string, required: example `"leaseline"` | `candidates` Domain[] |
| 2 | [`Domain.register`](/business/nouns/domain/register) (`verb:Domain.register`) | `hostname` string, required: example `"leaseline.app"`; `startup` Startup (an id), required: the `$id` of the first Startup `Startup.list` returns | `domain` Domain |
| 3 | [`Domain.connect`](/business/nouns/domain/connect) (`verb:Domain.connect`) | `hostname` string, required: example `"leaseline.app"`; `startup` Startup (an id), required: the `$id` of the first Startup `Startup.list` returns | `domain` Domain |

Returns: the last call answers with `domain` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`:

```json
{
  "api": "https://api.sb/leaseline.app",
  "domain": {
    "$id": "https://api.sb/leaseline.app/domains/domain_1",
    "$type": "Domain",
    "hostname": "leaseline.app"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Domain.connect",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/leaseline.app/actions/action_1"
  }
}
```

Next: offer “Send leaseline.com to leaseline.app”, or “Give me hello@leaseline.app”.

Calls: `Domain.search` → `Domain.register` → `Domain.connect`

Ask:

```text
Buy leaseline.app.
Find me a domain for the business under $20 a year.
Get the .com too, so no one else takes it.
```

API:

```bash
# 1. Domain.search
curl -X POST https://api.sb/leaseline.app/domains/search \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"leaseline"}'

# Look up the Startup: Startup.list
STARTUP=$(curl "https://api.sb/leaseline.app/startups?limit=1" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" | jq -r '.startups[0]["$id"] | split("/") | last')

# 2. Domain.register
curl -X POST https://api.sb/leaseline.app/domains/register \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"leaseline.app","startup":"'"$STARTUP"'"}'

# 3. Domain.connect
curl -X POST https://api.sb/leaseline.app/domains/connect \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"leaseline.app","startup":"'"$STARTUP"'"}'
```

SDK:

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

await $.Domain.search({ query: 'leaseline' })
const [startup] = await $.Startup.list({ limit: 1 })
await $.Domain.register({ hostname: 'leaseline.app', startup: startup.$id })
await $.Domain.connect({ hostname: 'leaseline.app', startup: startup.$id })
```

CLI:

```bash
npx startup-builder do Domain.search --json '{"query":"leaseline"}'
STARTUP=$(npx startup-builder do Startup.list --json '{"limit":1}' | jq -r '.startups[0]["$id"] | split("/") | last')
npx startup-builder do Domain.register --json '{"hostname":"leaseline.app","startup":"'"$STARTUP"'"}'
npx startup-builder do Domain.connect --json '{"hostname":"leaseline.app","startup":"'"$STARTUP"'"}'
```

MCP:

```json
{
  "name": "do",
  "arguments": {
    "code": "await $.Domain.search({ query: 'leaseline' })\nconst [startup] = await $.Startup.list({ limit: 1 })\nawait $.Domain.register({ hostname: 'leaseline.app', startup: startup.$id })\nreturn await $.Domain.connect({ hostname: 'leaseline.app', startup: startup.$id })"
  }
}
```

## Change it
- Send leaseline.com to leaseline.app.
- Give me hello@leaseline.app.
- Show me .com and .io options first.
- Renew it for five years.

## Under the hood
- Systems: [Sites](/products/site/sites)
- Nouns: [Domain](/business/nouns/domain), [DNS Record](/business/nouns/dns-record), [Site](/business/nouns/site)
- Events: [`Domain.registered`](/business/events/Domain.registered), [`Domain.connected`](/business/events/Domain.connected)