> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bizzyco.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Register a Domain via the API

> Search, quote, purchase, and track a new domain registration using the Bizzy REST API

<Badge color="green">New</Badge>

Use the domain registration API when you want to buy a new domain
programmatically through Bizzy. The API searches registrar availability, returns
a live quote, charges your account's default saved Stripe payment method, and
starts a registration operation you can poll until it completes.

Availability checks are provider-backed, with Bizzy routing through its
configured availability providers before returning the same response shape shown
below.

## Prerequisites

Before you call the registration endpoints, make sure you have:

* A Bizzy API key with `domains:read` and `domains:write`.
* A default Stripe payment method saved on the Bizzy account.
* The registrant contact details required by the domain registry.
* A maximum price, in cents, that you are willing to pay for the registration.

The examples below use this base URL:

```bash theme={null}
https://api.bizzyco.ai/v1
```

## Step 1: Search availability

Search the exact domain you want to register.

```bash theme={null}
curl "https://api.bizzyco.ai/v1/domain-registrations/search?query=example.com" \
  -H "Authorization: Bearer $BIZZY_API_KEY"
```

The response is wrapped in `data`:

```json theme={null}
{
    "data": {
        "query": "example.com",
        "results": [
            {
                "domain": "example.com",
                "available": true,
                "premium": false,
                "registrationPriceCents": 1800,
                "renewalPriceCents": 1800
            }
        ]
    }
}
```

`registrationPriceCents` is the all-in first-year price and `renewalPriceCents`
is the all-in per-year renewal price, both in USD cents. They can differ —
premium domains in particular often renew at a different price than they
register at. Both are `null` when the domain is unavailable.

Only continue if `available` is `true`.

## Step 2: Get a live quote

Request a quote for the domain and registration period. `periodYears` is
optional and defaults to `1`; it can be any integer from `1` to `10`.

```bash theme={null}
curl "https://api.bizzyco.ai/v1/domain-registrations/quote?domain=example.com&periodYears=1" \
  -H "Authorization: Bearer $BIZZY_API_KEY"
```

Use the returned `amountCents` as the minimum value for `maxAmountCents` in the
registration request.

```json theme={null}
{
    "data": {
        "domain": "example.com",
        "available": true,
        "periodYears": 1,
        "amountCents": 1800,
        "currency": "usd",
        "premium": false,
        "registrationPriceCents": 1800,
        "renewalPriceCents": 1800
    }
}
```

`amountCents` is the all-in total you'll be charged: the first year at
`registrationPriceCents` plus each additional year at `renewalPriceCents`.
There are no other fees — WHOIS privacy is included at no extra cost.

<Note>
  Quotes are live. The registration request re-checks availability and price
  before charging. If the current price is higher than `maxAmountCents`, the
  API rejects the request instead of charging you.
</Note>

## Step 3: Register the domain

Submit the registration request with the domain, price guardrail, registration
settings, and registrant contact details.

Registration moves money, so it requires an `Idempotency-Key` header. Generate a
unique value per registration attempt and send the **same** value if you retry
that attempt.

```bash theme={null}
curl -X POST "https://api.bizzyco.ai/v1/domain-registrations" \
  -H "Authorization: Bearer $BIZZY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9f8c2b1a-4d3e-4a6b-8c1d-2e3f4a5b6c7d" \
  -d '{
    "domain": "example.com",
    "periodYears": 1,
    "maxAmountCents": 1800,
    "autoRenew": true,
    "whoisPrivacy": true,
    "contact": {
      "label": "Primary registrant",
      "firstName": "Ada",
      "lastName": "Lovelace",
      "organizationName": "Example Co",
      "jobTitle": "Founder",
      "address1": "123 Market St",
      "address2": "Suite 400",
      "city": "San Francisco",
      "stateProvince": "CA",
      "postalCode": "94105",
      "country": "US",
      "email": "domains@example.com",
      "phone": "+14155550123"
    }
  }'
```

Successful registration requests return `202 Accepted` with an operation ID:

```json theme={null}
{
    "data": {
        "operationId": "550e8400-e29b-41d4-a716-446655440000",
        "status": "queued",
        "domain": "example.com"
    }
}
```

The API charges the account's default saved Stripe payment method before the
operation is queued. If no default payment method exists, the request fails with
`402`.

### Idempotency

The `Idempotency-Key` header is required and makes the charge safe to retry:

* **Reuse the same key** to retry a request that may already have succeeded (a
  timeout or dropped connection before you saw the `202`). The API replays the
  original operation and never charges twice.
* **Use a new key** for a genuinely new registration attempt — for example,
  after a previous attempt failed and was refunded.

If you omit the header, the request is rejected with `400`. The same header is
required on domain renewal (`POST /v1/domains/{id}/registration/renew`).

## Required registration inputs

| Field            | Required | Notes                                                      |
| ---------------- | -------- | ---------------------------------------------------------- |
| `domain`         | Yes      | Domain name to register, such as `example.com`             |
| `periodYears`    | No       | Integer from `1` to `10`; defaults to `1`                  |
| `maxAmountCents` | Yes      | Maximum amount you authorize Bizzy to charge, in USD cents |
| `autoRenew`      | No       | Defaults to `true`                                         |
| `whoisPrivacy`   | No       | Defaults to `true`                                         |
| `contact`        | Yes      | Registrant contact object used for the domain registration |

Transfer lock is enabled automatically after a domain is registered. Manage it
afterwards with `PATCH /v1/domains/{id}/registration`.

The `contact` object requires:

| Field           | Required | Notes                                      |
| --------------- | -------- | ------------------------------------------ |
| `firstName`     | Yes      | Registrant first name                      |
| `lastName`      | Yes      | Registrant last name                       |
| `address1`      | Yes      | Street address                             |
| `city`          | Yes      | City                                       |
| `stateProvince` | Yes      | State, province, or administrative region  |
| `postalCode`    | Yes      | Postal or ZIP code                         |
| `country`       | Yes      | Two-letter country code, such as `US`      |
| `email`         | Yes      | Registrant email address                   |
| `phone`         | Yes      | Registrant phone number; E.164 recommended |

These contact fields are optional: `label`, `organizationName`, `jobTitle`, and
`address2`. If you provide `organizationName`, `jobTitle` is also required — the
domain registry rejects a company contact without a job title. `label` is stored
only in Bizzy; changing it later does not update the registrar contact.

After registration, update registrar-backed contact fields with
`PATCH /v1/domains/{id}/registration/contact`. Changing the registrant's name,
organization, or email resets Bizzy's 15-day ICANN verification window and shows
the registrant verification notice again. Changing only the local `label` does
not contact the registrar or reset verification.

Registered Bizzy-managed domains can be deleted with `DELETE /v1/domains/{id}`
only after the registration has fully lapsed: the domain's status must be
`expired`, and its DNS zone must hold no records beyond the zone's built-in
ones (the apex NS set and SOA). Disable email for the domain first so Bizzy
removes the email records it manages, and delete any remaining records with the
DNS record endpoints. A renewal that is already queued or running also blocks
the deletion until it finishes. A blocked deletion returns `409` with code
`REGISTERED_DOMAIN_NOT_EXPIRED`, `REGISTERED_DOMAIN_RENEWAL_IN_FLIGHT`, or
`REGISTERED_DOMAIN_DNS_NOT_EMPTY` — the last lists the blocking records in the
error details. This keeps a paid, still-active registration from being hidden
from Bizzy while the registrar continues to renew it.

## Step 4: Poll the operation

Registration is asynchronous because it depends on payment, registrar, DNS, and
email setup work. Poll the operation until it reaches `succeeded` or `failed`.

```bash theme={null}
curl "https://api.bizzyco.ai/v1/operations/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $BIZZY_API_KEY"
```

Operation statuses are:

| Status      | Meaning                                       |
| ----------- | --------------------------------------------- |
| `queued`    | Payment succeeded and provisioning is waiting |
| `running`   | Registration provisioning has started         |
| `succeeded` | The domain was registered and added to Bizzy  |
| `failed`    | Registration failed; check `errorMessage`     |

When the operation succeeds, `resourceType` is `domain` and `resourceId` is the
new Bizzy domain ID.

```json theme={null}
{
    "data": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "type": "domain_registration",
        "status": "succeeded",
        "resourceType": "domain",
        "resourceId": "6f5b6fc6-7e21-4f5b-8d6d-0c0f6c269b5d",
        "resourceName": "example.com",
        "workflowId": "domain-registration-example-com",
        "paymentIntentId": "pi_123",
        "errorCode": null,
        "errorMessage": null,
        "completedAt": "2026-06-14T16:30:00.000Z",
        "createdAt": "2026-06-14T16:29:45.000Z",
        "updatedAt": "2026-06-14T16:30:00.000Z"
    }
}
```

## Step 5: Read the domain

After the operation succeeds, fetch the new domain using `resourceId`.

```bash theme={null}
curl "https://api.bizzyco.ai/v1/domains/6f5b6fc6-7e21-4f5b-8d6d-0c0f6c269b5d" \
  -H "Authorization: Bearer $BIZZY_API_KEY"
```

Registered domains are managed by Bizzy, so DNS and email authentication records
are configured automatically. The domain becomes usable for Bizzy-hosted email
after setup completes.

## Common failures

| Error code                | HTTP status | What to do                                                     |
| ------------------------- | ----------- | -------------------------------------------------------------- |
| `DOMAIN_UNAVAILABLE`      | `409`       | Search for another domain or TLD                               |
| `PRICE_EXCEEDS_MAXIMUM`   | `409`       | Get a fresh quote and decide whether to raise `maxAmountCents` |
| `PAYMENT_METHOD_REQUIRED` | `402`       | Add or choose a default payment method in Bizzy billing        |
| `PAYMENT_FAILED`          | `402`       | Update the default payment method and try again                |

## Next steps

After registration succeeds:

* Create an email address on the domain from
  [Bizzy-hosted email addresses](/user-guide/email-addresses/bizzy-hosted).
* Manage records with the
  [`/v1/domains/{id}/dns-records`](/user-guide/domains/dns) endpoints.
* Review setup and renewal history in
  [Domain Events](/user-guide/domains/events).
