Use whenever a user wants to register or buy a custom domain for an Eliza Cloud app — including in the same request as building the app (\"build me X and put it on Y.com\"). Uses Cloudflare as registrar after explicit user confirmation, paid from the user's existing cloud credit balance. Pairs with `build-monetized-app` (build first, then buy domain) and `eliza-cloud-manage-domain` (post-purchase: list, edit dns records, detach). Skip when the user is fine with the auto-assigned `*.apps.eliza...
Scanned 9/3/2026
Install to Claude Code
npx -y skills add elizaOS/eliza --skill eliza-cloud-buy-domain --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Eliza Cloud Buy Domain?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/elizaos-eliza-cloud-buy-domain)More formats (shields.io, HTML) on the badges page.
---
name: eliza-cloud-buy-domain
description: "Use whenever a user wants to register or buy a custom domain for an Eliza Cloud app — including in the same request as building the app (\"build me X and put it on Y.com\"). Uses Cloudflare as registrar after explicit user confirmation, paid from the user's existing cloud credit balance. Pairs with `build-monetized-app` (build first, then buy domain) and `eliza-cloud-manage-domain` (post-purchase: list, edit dns records, detach). Skip when the user is fine with the auto-assigned `*.apps.eliza.app` subdomain."
---
# Buy a domain for your app on Eliza Cloud
Use this skill when an Eliza Cloud app needs a real custom domain (e.g. `myapp.com`) instead of the auto-assigned `*.apps.eliza.app` subdomain.
The cloud handles everything: domain availability check, registration through cloudflare, DNS pointing at your app's container, and attachment to your app record. You pay from your existing cloud credit balance — no separate cloudflare account, no manual DNS config, no credit card paste.
> **Status — shipped end to end.** Custom-domain buy layers on top of the live
> app build + monetize flow and is offered only *after* an app is live (never as
> the first step). The buy money-path is hardened — atomic with
> refund-on-registration-failure and purchase idempotency (#10244, #10247) — and
> the CNAME origin last-mile (#10245) and renewal billing cron (#10246) are live.
> Always confirm the price and get an explicit user "yes" before any buy; never
> auto-buy.
>
> **In a conversational agent, prefer the first-class actions.** An agent running
> `@elizaos/plugin-cloud-apps` already has `CHECK_APP_DOMAIN` (availability +
> price quote), `BUY_APP_DOMAIN` (two-phase confirm with a quote TTL; maps the
> idempotent-buy / refund / no-charge-recovery outcomes to honest replies), and
> `LIST_APP_DOMAINS` — use those instead of raw SDK calls from chat. The SDK flow
> below is for orchestrated workers and custom code.
## Prerequisites
- An app registered on Eliza Cloud (use `build-monetized-app` first if you haven't shipped one yet)
- Enough cloud credit balance to cover the domain (cloudflare wholesale + a fixed eliza cloud margin; a `.com` is roughly $14–15 USD/year)
- Either the parent-agent Cloud command bridge in an orchestrated worker, or
`ELIZAOS_CLOUD_API_KEY` in the parent/app runtime. Do not pass wallet private
keys or owner Cloud API keys into a spawned child process.
## Default flow
```ts
import { ElizaCloudClient } from "@elizaos/cloud-sdk";
const cloud = new ElizaCloudClient({
apiKey: process.env.ELIZAOS_CLOUD_API_KEY,
// optional override for local dev / staging / preview deploys.
// unset in prod → SDK uses eliza.app for browser flows and api.eliza.app for API calls
baseUrl: process.env.ELIZA_CLOUD_BASE_URL,
});
// 1. quote — confirms availability + total price the user will pay
const quote = await cloud.routes.postApiV1AppsByIdDomainsCheck({
pathParams: { id: appId },
json: { domain: "myapp.com" },
});
if (!quote.available) {
// try a different domain or pick an alternate TLD
return;
}
const totalUsd = quote.price.totalUsdCents / 100;
// 2. confirm with the user (one-line ack is enough; the SDK will throw
// if the org balance is insufficient)
//
// "buying myapp.com for $14.95 from your cloud balance — ok?"
// 3. buy — atomic on the cloud side: debit credits → register via cloudflare
// → write managed_domains row + attach to app → CNAME the new zone at
// the app's container url. Refunds credits if registration fails. If the
// domain is already owned by this org, this returns alreadyRegistered
// without charging again.
const result = await cloud.routes.postApiV1AppsByIdDomainsBuy({
pathParams: { id: appId },
json: { domain: "myapp.com" },
});
// 4. (optional) poll status until verified — cloudflare registration is
// usually live within seconds; ssl provisioning may take 1–2 minutes
const status = await cloud.routes.postApiV1AppsByIdDomainsStatus({
pathParams: { id: appId },
json: { domain: "myapp.com" },
});
```
When this flow runs inside an orchestrated worker, prefer the deterministic
parent-agent commands instead of direct SDK credentials:
```text
USE_SKILL parent-agent {"mode":"list-cloud-commands","query":"domains"}
USE_SKILL parent-agent {"mode":"cloud-command","command":"domains.check","params":{"id":"<appId>","body":{"domain":"myapp.com"}}}
USE_SKILL parent-agent {"mode":"cloud-command","command":"domains.buy","confirmed":true,"params":{"id":"<appId>","body":{"domain":"myapp.com"}}}
```
## Failure modes
The buy route handles refunds and surfaces specific HTTP statuses; treat them like:
| Status | Meaning | Action |
|---|---|---|
| 400 | invalid domain format | re-prompt user for valid domain |
| 402 | insufficient credit balance | tell user to top up at /cloud/billing |
| 404 | app not found / wrong org | re-check appId |
| 409 | domain unavailable or owned by another org | suggest alternates or add a suffix |
| 502 | cloudflare returned an error (refund issued) | retry with different domain |
The buy route is idempotent for domains already owned by the same org. If a
previous run reached Cloudflare but local zone/status metadata arrived late,
retry the same canonical `/buy` route once; report `alreadyRegistered: true` or
`pendingZoneProvisioning: true` honestly. Never try alternate guessed buy routes.
## Read these references in order
1. `references/api-shape.md` — the actual request/response shape for each cloud endpoint
2. `references/dns-and-ssl.md` — what happens after the buy (CNAME setup, SSL provisioning timing)
3. `references/failure-modes.md` — recovery table for the failures you'll actually hit
After the buy succeeds, future "list / edit / delete dns / detach" requests on this domain are handled by the `eliza-cloud-manage-domain` skill — point the user there if they ask follow-up questions.
## What this skill is NOT
- **Not for "attaching a domain you already own elsewhere."** That path goes through `POST /api/v1/apps/[id]/domains` directly (which generates a `_eliza-cloud-verify.<domain>` TXT record the user adds at their existing dns provider, then re-checks via `POST /api/v1/apps/[id]/domains/verify`). Use this `buy-domain` skill only when the user does NOT already own the domain.
- **Not for cancelling a registration.** Cloudflare registrations are non-refundable after they're complete; you can detach from the app via `DELETE /api/v1/apps/[id]/domains` but the registration itself stays active until expiration.
- **Not for transferring an existing domain into eliza cloud.** Out of scope for v1.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!