# domani.sh > Domain infrastructure for AI agents. One API to search, register, and connect domain names. ## Quick Start Register for an API key (no credit card required). Pass a `ref` code to earn referral commissions on all future purchases by this user: ```bash curl -X POST https://domani.sh/api/auth/register \ -H "Content-Type: application/json" \ -d '{"email": "you@example.com", "ref": "YOUR_REFERRAL_CODE"}' ``` Response: ```json { "api_key": "domani_sk_a1B2c3D4e5F6g7H8i9J0kLmN", "referral_code": "x7k9m2", "has_payment_method": false, "user": { "id": "cm5abc123", "email": "you@example.com" } } ``` ## Agent Integration Three ways to give your AI agent domain management capabilities: ### 1. Agent Skill (Claude, OpenClaw) Install the domani skill so your agent knows how to search, buy, and manage domains automatically. - **Claude.ai**: Download [domani-skill.zip](https://domani.sh/domani-skill.zip) → Settings > Features > Upload skill - **Claude Code**: Copy [SKILL.md](https://domani.sh/skill/SKILL.md) to `.claude/skills/domani/SKILL.md` in your project - **Claude API**: Upload via `POST /v1/skills` with the zip contents - **OpenClaw**: `clawhub install domani` The skill teaches the agent the full workflow: register, search, compare pricing, buy, and configure DNS. ### 2. MCP (Model Context Protocol) Connect any MCP-compatible agent (Claude Code, Cursor, Windsurf, etc.) to the Streamable HTTP endpoint: ```json { "mcpServers": { "domani": { "type": "streamable-http", "url": "https://domani.sh/mcp", "headers": { "Authorization": "Bearer domani_sk_xxx" } } } } ``` This exposes 21 tools (search_domain, bulk_search, suggest_domains, buy_domain, transfer_domain, renew_domain, connect_domain, domain_status, verify_connection, verify_service, whois_lookup, set_auto_renew, get_domain_info, list_providers, list_services, set_dns, etc.) as native callable tools with typed parameters. Discovery manifest: [mcp.json](https://domani.sh/.well-known/mcp.json) ### 3. Direct API Use the REST API directly with `curl`, `fetch`, or any HTTP client. See the [OpenAPI spec](https://domani.sh/.well-known/openapi.json) for the full schema, or the [interactive docs](https://domani.sh/docs) to try endpoints in the browser. ## Authentication Most API endpoints require a Bearer token: ``` Authorization: Bearer domani_sk_xxx ``` API keys use the prefix `domani_sk_` followed by 32 random characters. You can create multiple tokens via `POST /api/tokens` for different applications. **Public endpoints** (no authentication required): - `GET /api/domains/search` - Check domain availability - `GET /api/domains/search/bulk` - Compare pricing across TLDs - `GET /api/tlds` - List all TLDs with pricing - `GET /api/domains/whois` - WHOIS/RDAP lookup - `GET /api/domains/suggest` - AI domain name suggestions These endpoints use IP-based rate limiting. Authenticated requests get higher rate limits. ## Agent Workflow Recommended sequence for finding and buying a domain: 1. **Check account**: `GET /api/me` - verify authentication and check `has_payment_method` 2. **Get name ideas**: `GET /api/domains/suggest?prompt=AI+coding+assistant` - AI-generated brandable domain names (no TLD, 10/min) 3. **Browse TLDs**: `GET /api/tlds?max_price=20&sort=price` - list available TLDs with pricing 4. **Compare pricing**: `GET /api/domains/search/bulk?name=myproject&tlds=com,dev,ai` - instant cached pricing across specific TLDs (comma-separated, default: com,io,dev,ai,sh,co,net,org,app,xyz) 5. **Verify availability**: `GET /api/domains/search?q=myproject.dev` - real-time check (6/min limit) 6. **Purchase**: `POST /api/domains/buy` with `{"domain": "myproject.dev"}` - if you have a card on file it's charged automatically. If not, you'll get a 402 with x402 payment requirements (USDC on Base) that x402-compatible agents fulfill automatically. 7. **Connect**: `POST /api/domains/myproject.dev/connect` with `{"target": "my-app.vercel.app"}` - auto-detects provider and sets DNS records. Or use `{"provider": "google-workspace"}` for email. 8. **Set up email**: `POST /api/domains/myproject.dev/connect` with `{"provider": "google"}` - shorthand for email setup. Sets MX, SPF, DMARC records. Shorthand names: `google` (Google Workspace), `proton` (Proton Mail), `fastmail` (Fastmail). 9. **Check email health**: `GET /api/domains/myproject.dev/email/check` - verifies MX propagation, SPF, DMARC, DKIM. Auto-detects the email provider from MX records. 10. **Verify**: `POST /api/domains/myproject.dev/verify` with `{"target": "my-app.vercel.app"}` - confirms DNS propagation 11. **Verify service**: `POST /api/domains/myproject.dev/verify-service` with `{"service": "stripe", "token": "xxx"}` - adds verification DNS records for Stripe, Google Search Console, AWS SES, etc. 12. **Check status**: `GET /api/domains/myproject.dev/status` - DNS, SSL, email, and expiry health check 13. **WHOIS / RDAP lookup**: `GET /api/domains/whois?q=example.com` - look up full registration data for any domain: registrar (name, URL, IANA ID), dates (created, expires, updated, days_until_expiry), status codes, nameservers, DNSSEC, privacy redaction status, and contacts (registrant, admin, tech, billing, abuse - each with name, organization, email, phone, address). Uses RDAP with automatic WHOIS port 43 fallback. Cached 1h (registered) / 5min (not-found). Rate limit: 30/min 14. **Domain info**: `GET /api/domains/myproject.dev` - get detailed info about a domain you own: status, auto-renew, purchase/expiry dates, days until expiry, payment method, and registrar-side data (security lock, WHOIS privacy, auto-renew status, creation/expiration dates). Rate limit: 60/min 15. **Auto-renew settings**: `PUT /api/domains/myproject.dev/settings` with `{"auto_renew": false}` - toggle auto-renew on/off. Applied at registrar first, then synced to local DB. Rate limit: 60/min 16. **Renew domain**: `POST /api/domains/myproject.dev/renew` with `{"years": 1}` - extend registration by 1-10 years. Payment charged upfront. Returns new expiry date. Rate limit: 10/min 17. **Transfer domain**: `POST /api/domains/transfer` with `{"domain": "example.com", "auth_code": "EPP-CODE"}` - transfer a domain from another registrar. Requires authorization/EPP code. Returns 202 (async, takes 1-5 days). Rate limit: 5/min ### Example: Search and Buy ```bash # Step 1: Compare pricing across TLDs (no auth needed) curl "https://domani.sh/api/domains/search/bulk?name=myproject&max_price=20" # Step 2: Verify the cheapest option is available (no auth needed) curl "https://domani.sh/api/domains/search?q=myproject.xyz" # Step 3: Buy it curl -X POST https://domani.sh/api/domains/buy \ -H "Authorization: Bearer domani_sk_xxx" \ -H "Content-Type: application/json" \ -d '{"domain": "myproject.xyz"}' # Step 4: Connect to your hosting provider (auto-detects Vercel) curl -X POST https://domani.sh/api/domains/myproject.xyz/connect \ -H "Authorization: Bearer domani_sk_xxx" \ -H "Content-Type: application/json" \ -d '{"target": "my-app.vercel.app"}' # Step 5: Verify the connection is live curl -X POST https://domani.sh/api/domains/myproject.xyz/verify \ -H "Authorization: Bearer domani_sk_xxx" \ -H "Content-Type: application/json" \ -d '{"target": "my-app.vercel.app"}' # Step 6: Verify domain for Stripe curl -X POST https://domani.sh/api/domains/myproject.xyz/verify-service \ -H "Authorization: Bearer domani_sk_xxx" \ -H "Content-Type: application/json" \ -d '{"service": "stripe", "token": "abc123def456"}' # Step 7: Check overall domain health curl https://domani.sh/api/domains/myproject.xyz/status \ -H "Authorization: Bearer domani_sk_xxx" ``` ## Endpoints | Method | Path | Description | |--------|------|-------------| | `POST` | `/api/auth/register` | Create account and get API key | | `POST` | `/api/auth/login` | Send magic link sign-in email | | `GET` | `/api/me` | Get account details (email, payment status, referral code) | | `GET` | `/api/tlds` | List all TLDs with pricing (public, no auth required) | | `GET` | `/api/domains/search?q=example.com` | Check real-time domain availability (public, no auth required) | | `GET` | `/api/domains/search/bulk?name=example` | Compare cached pricing across TLDs (public, no auth required) | | `GET` | `/api/domains/suggest?prompt=description` | AI domain name suggestions (public, no auth required) | | `POST` | `/api/domains/buy` | Purchase a domain | | `POST` | `/api/domains/transfer` | Transfer domain from another registrar | | `POST` | `/api/domains/{domain}/renew` | Renew domain for additional years | | `GET` | `/api/domains` | List your registered domains | | `GET` | `/api/domains/{domain}/dns` | Get DNS records | | `PUT` | `/api/domains/{domain}/dns` | Set DNS records | | `POST` | `/api/domains/{domain}/connect` | Connect to a provider (auto-detect or explicit) | | `GET` | `/api/domains/{domain}/connect` | List available providers and methods | | `POST` | `/api/domains/{domain}/verify` | Verify provider connection is live | | `POST` | `/api/domains/{domain}/verify-service` | Add verification DNS records for a service (Stripe, Google, etc.) | | `GET` | `/api/domains/{domain}/verify-service` | List supported verification services | | `GET` | `/api/domains/{domain}` | Get domain details | | `PUT` | `/api/domains/{domain}/settings` | Update domain settings (auto-renew) | | `GET` | `/api/domains/{domain}/email/check` | Email health: MX, SPF, DMARC, DKIM | | `GET` | `/api/domains/{domain}/status` | Domain health: DNS, SSL, email, expiry | | `GET` | `/api/domains/whois?q=example.com` | RDAP/WHOIS lookup (public, no auth required) | | `POST` | `/api/billing/setup` | Add payment method (card) | | `GET` | `/api/tokens` | List API tokens | | `POST` | `/api/tokens` | Create API token | | `DELETE` | `/api/tokens/{id}` | Revoke API token | | `GET` | `/api/referrals` | View referral earnings | ## Rate Limits All responses include rate limit headers: - `X-RateLimit-Limit` - Maximum requests allowed per window - `X-RateLimit-Remaining` - Requests remaining in current window - `X-RateLimit-Reset` - Unix timestamp when the window resets | Endpoint | Public Limit | Auth Limit | Notes | |----------|-------------|------------|-------| | `GET /api/domains/search` | 6/min (IP) | 30/min (user) | Real-time availability checks | | `GET /api/domains/search/bulk` | 10/min (IP) | 60/min (user) | Cached pricing | | `GET /api/tlds` | 30/min (IP) | 60/min (user) | TLD listing | | `GET /api/domains/suggest` | 10/min (IP) | 10/min (IP) | AI-generated domain names | | `GET /api/domains/whois` | 10/min (IP) | 30/min (user) | Cached 1h registered, 5min not-found | | `GET /api/domains/{domain}` | - | 60/min (user) | Auth required | | `PUT /api/domains/{domain}/settings` | - | 60/min (user) | Auth required | | `POST /api/domains/buy` | - | 10/min (user) | Auth required | | `POST /api/domains/transfer` | - | 5/min (user) | Auth required, async (1-5 days) | | `POST /api/domains/{domain}/renew` | - | 10/min (user) | Auth required | | `POST /api/auth/register` | 5/min (IP) | - | | | `POST /api/auth/login` | 10/min (IP) | - | | | All other authenticated | - | 60/min (user) | Per endpoint | When rate limited (HTTP 429), the response includes a `Retry-After` header with seconds to wait. Recommended strategy: exponential backoff starting at the `Retry-After` value. ## Error Format All errors return a consistent JSON envelope: ```json { "error": "Human-readable message", "code": "MACHINE_CODE", "hint": "Actionable recovery guidance", "documentation_url": "https://domani.sh/llms.txt" } ``` ### Error Codes | Code | HTTP | Meaning | Recovery | |------|------|---------|----------| | `MISSING_API_KEY` | 401 | No Authorization header | Add `Authorization: Bearer domani_sk_xxx` header | | `INVALID_API_KEY` | 401 | Key not found or revoked | Check key or create a new one via `POST /api/tokens` | | `MISSING_PARAMETER` | 400 | Required field missing | Check `hint` field for the missing parameter | | `INVALID_DOMAIN` | 400 | Bad domain format | Use format `name.tld` (e.g. `mysite.com`) | | `PAYMENT_REQUIRED` | 402 | No payment method | Pay with USDC via x402 (automatic) or add a card via `POST /api/billing/setup` | | `DOMAIN_UNAVAILABLE` | 409 | Domain is taken | Try a different domain or TLD | | `RATE_LIMIT_EXCEEDED` | 429 | Too many requests | Wait `retry_after` seconds, then retry | | `USER_EXISTS` | 409 | Email already registered | Use `POST /api/auth/login` instead | | `NOT_FOUND` | 404 | Resource not found | Verify the ID/domain exists and belongs to you | ## Referral Program Agents and integrations can earn commissions on domain purchases: 1. **Register** with `POST /api/auth/register` to get your `referral_code` 2. **Link users** by passing your code as `ref` when registering new users: `{"email": "...", "ref": "YOUR_CODE"}` 3. **Earn automatically** - every domain purchased by a user you referred earns you a 20% commission on the markup, permanently The referral link is set once at registration and applies to all future purchases. No need to pass the code on every buy request. Check your earnings with `GET /api/referrals`. ## Paying with USDC (x402) AI agents can buy domains with USDC on Base - no credit card needed. The API implements the [x402 protocol](https://x402.org): 1. `POST /api/domains/buy` with `{"domain": "mysite.com"}` 2. If no card on file, you get HTTP 402 with a `PAYMENT-REQUIRED` header containing USDC payment requirements 3. x402-compatible clients (e.g. `@x402/fetch`) automatically sign a USDC transfer and retry with a `PAYMENT-SIGNATURE` header 4. Payment is verified and settled on-chain, domain is registered **Network**: Base (eip155:8453) **Asset**: USDC (`0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`) **Pricing**: Dynamic per domain (same USD price as card payments, denominated in USDC) Agents with a card on file skip x402 entirely - the card is charged automatically. ## Pagination The `GET /api/tlds` endpoint supports pagination via `limit` and `offset` query parameters. When more results exist, the response includes a `Link` header: ``` Link: ; rel="next" ```