# Domains

> Every app gets <slug>.vibiz.app. Buy a domain of its own from your credits, registered to you and live on the app at once.

Every app already answers at `https://<slug>.vibiz.app`, free, for as long as it exists. When the business wants a name of its own, buy one here: it is paid from the account's credits, registered to the owner, and served on the app at once, with HTTPS and no DNS to set. A domain you already own elsewhere is connected instead ([Hosting ▸ Your own domain](https://app.vibiz.app/docs/hosting#your-own-domain)).

## Buying one

```bash
vibiz domains search sellshelf          # names across endings, with prices
vibiz domains buy sellshelf.app         # owner key: shows the price, the balance after, and asks
vibiz domains owned                     # what the account bought: expiry, auto-renew
```

In the console: the project ▸ **Domains** ▸ **Buy a domain** (search, pick one, confirm), and **Domains** in the main menu for the account's domains.

1. **Search** a name (`sellshelf`) or an exact domain (`sellshelf.app`). Each result shows the price for the first year and the renewal price a year, in USD.
2. **Quote** one: the price, your balance after, and whether your saved owner details cover it.
3. **Confirm** (the owner). The price is taken from your credits, the registration is placed, and within a minute or two the domain is `active` and serves the project, `www` included.

- **Prices** are in USD cents and are the full price: nothing else is added. Premium names (priced higher by the registry) need an explicit confirmation.
- **The price you saw is the price you pay.** A buy carries `expected_price_cents`; if the price moved since, nothing is charged and the answer (`409`, `reason: price_changed`) carries a new quote to confirm.
- **Not enough credits**: `402 payment_required` with the Billing link in `next_step`. Add credits and buy again.
- **If the registration fails**, the credits go back to your balance at once (a `domain_refund` line in Billing ▸ History).
- On the Billing history a purchase is a `domain` line: `Domain sellshelf.app (1 year)`.

## Owner details

A domain is legally registered to a real person or company: the **domain owner**. Their details (name, email, phone, postal address, optionally the company) are entered once, on the first purchase, and saved for the account (encrypted at rest); later purchases use them by themselves, and the confirmation shows "Registered to: Ann Smith, San Francisco, US". Personal details are hidden from the public WHOIS where the domain ending allows it.

- Some endings ask for more (`.us`: a nexus category; `.ca`: a legal type). Only those extra fields are asked for, and they are saved too: the quote's `owner_details.fields_needed` lists them.
- Change them in the console (**Domains ▸ Owner details**), with `vibiz domains owner --input '<json>'`, or `PUT /v1/domains/owner`. Changes apply to domains bought from then on.
- Only an owner can see or change them. Agents never fill them in.

## Confirming the owner

ICANN, which oversees domain names, requires a new domain's owner contact details to be confirmed within 15 days of registration; without it the registry suspends the domain. Vibiz handles the request for you: the registry writes to a private contact address we keep for the domain (your name, address and phone stay on the registration; you remain the legal owner), and the account's owners get one email from Vibiz, **Confirm your domain sellshelf.app**, with a link to the console. Press **Confirm** there and it is done.

- Each owned domain carries `contact_verification`: `status` (`pending`, `verified`, or `unknown` before the registry has answered), `verify_by`, and `can_confirm` (the request arrived and one click confirms it). The console shows "Confirm by <date>" on the domain until it is confirmed.
- Reminders go out 7, 3 and 1 day(s) before `verify_by`. Vibiz checks with the registry about once a day; **Check now** (or `POST /v1/domains/:domain/contact-verification/check`) asks at once.
- If the request hasn't arrived, `next_step` says so: write to support@vibiz.ai and we finish it before the deadline.
- Domains bought before this was in place were registered with the owner's own email: the registry wrote to that address, so open its message and follow the link. The console still shows where it stands.

## Email at the domain

Want `hello@` your new domain in the inbox you already use? After buying, press **Set up email** (or Domains ▸ Email forwarding): Vibiz sets the domain's mail records for you, and forwards each address you choose, "via Vibiz". See [Email ▸ Forwarding](https://app.vibiz.app/docs/email#forwarding-helloyourcompanycom-to-your-inbox).

## Renewals

Domains are registered for a year (up to 10 with `--years`). **Auto-renew is on**: about 30 days before expiry the renewal price is taken from your credits and the domain renewed. If the credits are short, the account's owners are emailed and it is tried again every day; add credits and it renews by itself. Turn auto-renew off per domain (`vibiz domains auto-renew sellshelf.app off`) to let it lapse, or renew early with `vibiz domains renew sellshelf.app`.

## Moving a domain out

The domain is yours. `vibiz domains transfer-code sellshelf.app` (owner key, or the console) gives the code another registrar asks for. Registries lock a domain for 60 days after it is registered or moved.

## Agents

Agents may search and quote. By default buying and renewing are the owner's: a quote carries `buy_url`, the console page where the owner confirms, and an agent's buy answers `403 owner_only` with the same link in `details.console_url`.

The owner can let agents and the CLI buy and renew domains themselves, up to a price per domain: console ▸ Billing ▸ *Domains bought by agents*, or `PATCH /v1/billing {"agent_domain_limit_cents": 3000}` (owner key; `null` turns it off). Then a quote says `can_buy: true` and `agent_limit_cents`, and an agent key buys with the owner details the owner saved (it can never send its own). Over the limit: `403 over_agent_limit` with the confirm link. Premium names always need the owner. Auto-renew, the transfer code and the owner details stay the owner's.

A bought domain is trusted for sign-in at once (we hold its DNS), and so is any name under it a project adds, with no TXT record to set.

From MCP: `vibiz_buy_domain` (`search`, `quote`, `buy`, `owned`): search first, tell the user the price, then `buy` when the quote's `can_buy` is true, or send the owner the link. From the CLI: `vibiz domains buy <domain>` buys when allowed and prints the link otherwise.

## Over HTTP

| Route | Who | |
| --- | --- | --- |
| `GET /v1/domains/search?q=sellshelf` | any key | `data[]`: `domain`, `available`, `premium`, `price_cents`, `renewal_price_cents`, `buy_url` |
| `GET /v1/domains/quote?domain=&years=&project_id=` | any key | the price, `balance_after_cents`, `enough_credits`, `owner_details`, `buy_url`, `next_step` |
| `POST /v1/projects/:id/domains/buy` | owner | `{ domain, years?, expected_price_cents, confirm_premium?, contact?, save_contact?, additional? }` → `202` the owned domain (`registering`, then `active`) |
| `GET /v1/domains` · `GET /v1/domains/:domain` | any key | owned domains: `status`, `expires_at`, `auto_renew`, `renewal_price_cents`, `registered_to`, `contact_verification`, `last_order` |
| `POST /v1/domains/:domain/contact-verification/confirm` | owner | confirm the owner's contact details (when `can_confirm`) |
| `POST /v1/domains/:domain/contact-verification/check` | any key | ask the registry now |
| `PATCH /v1/domains/:domain` | owner | `{ auto_renew }` |
| `POST /v1/domains/:domain/renew` | owner | `{ years?, expected_price_cents }` |
| `POST /v1/domains/:domain/auth-code` | owner | the transfer code |
| `GET /v1/domains/owner` · `PUT /v1/domains/owner` | owner | the owner details `{ contact }` |

## Errors

| Code | Status | When | Next step |
| --- | --- | --- | --- |
| `payment_required` | 402 | the balance doesn't cover the price | add credits (`next_step`), buy again |
| `conflict` (`price_changed`) | 409 | the price moved since the quote | confirm `details.quote.price_cents` |
| `invalid_request` (`owner_details_required`) | 400 | no owner details saved yet | the owner fills them in at `details.console_url` |
| `invalid_request` (`owner_details_fields_required`) | 400 | the ending asks for more | ask for `details.fields` only, buy again with `additional` |
| `invalid_request` (`premium_confirmation_required`) | 400 | a premium name | confirm the price with `confirm_premium: true` |
| `forbidden` (`owner_only`) | 403 | an agent key | send the owner `details.console_url` |
| `conflict` (`no_confirmation_link`) | 409 | confirming before the registry's request arrived | wait, or write to support@vibiz.ai |
| `provider_failed` (`confirmation_failed`) | 502 | the registry didn't take the confirmation | try again in a few minutes, or write to support |
