DomaineeDocs

Buy a domain

POST /v1/domain-purchases — charge your card and register a hostname for your end-user.

POST /v1/domain-purchases

Charges your workspace's saved Stripe card, then registers the hostname at the upstream registrar with the contact you supply. Returns the purchase record on success. Auto-refunds and reports failure if the registrar refuses after the charge succeeded.

Request

curl -X POST https://api.domainee.dev/v1/domain-purchases \
  -H "Authorization: Bearer $DOMAINEE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "hostname": "janesbakery.com",
    "years": 1,
    "registrant": {
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane@bakery.example",
      "phone": "+1.5551234567",
      "address1": "123 Main St",
      "city": "Portland",
      "stateOrProvince": "OR",
      "postalCode": "97201",
      "country": "US"
    },
    "customerReference": "user_jane_42"
  }'

Body parameters

FieldRequiredDefaultNotes
hostnameThe domain to register. Lowercased + trimmed automatically.
years1Integer 1–10. How long to register for.
registrantContact info for the legal owner of record. See below.
enableWhoisPrivacytrueFree WHOIS privacy at the registrar. Set false only if you need public WHOIS.
autoRenewfalseRenew at the registrar automatically before expiry.
maxTotalCentsSafety ceiling — if live price exceeds this, we return 409 price_changed before charging. Recommended on every call to protect against premium-price surprises.
customerReferenceOpaque string echoed back on reads + webhooks. Stash your internal user-id, order-id, etc. — then filter the list endpoint by it later.
autoConnectWhen present, after registration we ALSO provision the hostname on Domainee's edge and set the registrar DNS to a single CNAME pointing at us. One API call ships a working live domain. See below.

autoConnect object

"autoConnect": {
  "originUrl": "https://janesbakery.acmesites.app",  // required
  "keepHost": false                                  // optional, default false
}
FieldRequiredNotes
originUrlWhere the edge proxies requests. Must be https://.
keepHostForward the customer's original Host header. Default false.

If autoConnect is set, the response's purchase.connectedDomainId field is populated with the matching /v1/domains row id, and the domain resolves to your app within a minute of DNS propagation.

If any step in the chain fails (edge provisioning, DNS update), the entire transaction rolls back — the Stripe charge is refunded, the purchase row is marked refunded, and domain_purchase.failed fires.

Registrant object

All fields are forwarded to the registrar verbatim. Your end-user is the legal owner of record, not you. ICANN requires the address fields to be real — fake data risks suspension of the domain.

FieldRequiredNotes
firstName
lastName
emailRegistrar may send verification mail here.
phoneE.164 with dot: +1.5551234567.
address1
address2
city
stateOrProvince
postalCode
countryISO 3166-1 alpha-2 (e.g. "US").
organizationSet for business-owned domains.

Response — 201 Created

{
  "purchase": {
    "id": "f8a0c1b9-1234-…",
    "workspaceId": "ws_…",
    "hostname": "janesbakery.com",
    "years": 1,
    "wholesaleCents": 1418,
    "feeCents": 100,
    "totalCents": 1518,
    "currency": "USD",
    "registrar": "namecheap",
    "registrarDomainId": "182739",
    "status": "completed",
    "registrant": {
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane@bakery.example",
      "country": "US"
    },
    "whoisPrivacyEnabled": true,
    "autoRenew": false,
    "expiresAt": "2027-05-17T15:42:11.000Z",
    "customerReference": "user_jane_42",
    "createdAt": "2026-05-17T15:42:09.000Z",
    "updatedAt": "2026-05-17T15:42:11.000Z"
  }
}

Errors

CodeStatusWhen
unavailable409Hostname is already registered or not available for this TLD.
price_changed409Live price exceeded maxTotalCents. No charge made.
billing_required402The Stripe charge failed — declined card, no card on file, 3DS required, insufficient funds. No registration attempted.
registration_failed502We charged your card but the registrar refused. We automatically refunded the Stripe charge and marked the row as refunded. The error message contains the registrar's reason.
bad_request400Validation failure — missing/malformed body.

Side effects

  • A row is written to domain_purchases for your workspace.
  • Your workspace's Stripe card is charged the full totalCents.
  • The hostname is registered at the upstream registrar with the supplied contact as the legal owner.
  • One of two webhook events fires:

Idempotency

Send an Idempotency-Key header to dedupe retries:

Idempotency-Key: 8a04...

We cache the response for 24 hours per workspaceId × method × path × key. Retries with the same key return the original response without re-charging or re-registering.

After the purchase

The domain is registered but not yet configured to serve your app's content. To make it serve traffic from your platform:

  1. Update DNS at the registrar to point the hostname at Domainee's edge (one CNAME, see the Custom Domains docs).
  2. Call POST /v1/domains with the same hostname so we mint a TLS cert and start proxying.

We're considering adding an autoConnect field that does both in one call. Tell us if you want it.

On this page