{
  "openapi": "3.1.0",
  "info": {
    "title": "name.ai public API",
    "version": "1.0.0",
    "description": "Public, no-authentication-required endpoints for domain search/availability, WHOIS lookup, and TLD pricing/requirements. These are the same endpoints backing the name.ai MCP server (see /.well-known/mcp.json) — this spec documents them as plain REST for any client that isn't speaking MCP.",
    "contact": { "url": "https://name.ai/get-in-touch" }
  },
  "servers": [{ "url": "https://name.ai" }],
  "paths": {
    "/api/domain/search": {
      "post": {
        "operationId": "searchDomain",
        "summary": "Check a domain and its alternate-TLD siblings",
        "description": "Checks the given domain and, for a simple label.tld query, its common alternate TLDs (e.g. querying acme.com also returns acme.ai, acme.io, ...). Streams newline-delimited JSON (NDJSON): one 'header' event, then one 'row' event per domain, a 'primary_done' marker after the queried domain, and a final 'done' event. Buy-now/aftermarket prices are hidden unless the caller has a verified, signed-in session; new-registration pricing is always included.",
        "security": [{}, { "oauth2": ["pricing:read"] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["q"],
                "properties": {
                  "q": { "type": "string", "description": "Domain to check, e.g. \"example.ai\".", "example": "example.ai" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "NDJSON stream of search events. Include a Bearer access token (scope pricing:read — see /AUTH.md) to unmask aftermarket/marketplace prices; omit it for the same response with those prices hidden.",
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string",
                  "description": "One JSON object per line. `kind` discriminates the event: \"header\" ({request_id, primary, domains, primary_index}), \"row\" ({domain, state, state_label, available, price, listing, whois_summary, cached, meta}), \"primary_done\" (marker, no other fields), or \"done\" ({duration_ms, count})."
                }
              }
            }
          },
          "400": { "description": "q missing or not a valid domain." }
        }
      }
    },
    "/api/tools/whois": {
      "post": {
        "operationId": "whoisLookup",
        "summary": "WHOIS/RDAP lookup for a domain",
        "description": "Looks up registrar, registrant, creation/expiration dates, and nameservers via RDAP (falling back to DomainIQ). Rate-limited to 10 lookups/day per caller IP for anonymous callers.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["domain"],
                "properties": {
                  "domain": { "type": "string", "example": "example.com" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lookup succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "lookup": {
                      "type": "object",
                      "properties": {
                        "id": { "type": ["string", "null"] },
                        "domain": { "type": "string" },
                        "result": {
                          "type": "object",
                          "properties": {
                            "domain": { "type": "string" },
                            "status": { "type": "string" },
                            "registrar": { "type": "string" },
                            "registrant": { "type": "string" },
                            "creation_date": { "type": "string" },
                            "expiration_date": { "type": "string" },
                            "update_date": { "type": "string" },
                            "nameservers": { "type": "array", "items": { "type": "string" } },
                            "emails": { "type": "array", "items": { "type": "string" } },
                            "raw_source": { "type": "string", "enum": ["RDAP", "DomainIQ"] }
                          }
                        },
                        "created_at": { "type": "string", "format": "date-time" }
                      }
                    },
                    "used": { "type": "integer" },
                    "cap": { "type": "integer", "example": 10 },
                    "remaining": { "type": "integer" }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid domain name." },
          "404": { "description": "WHOIS data unavailable for this domain." },
          "429": { "description": "Daily lookup quota exceeded (10/day per IP for anonymous callers)." }
        }
      }
    },
    "/api/pricing/tld": {
      "get": {
        "operationId": "tldRegistrationPrice",
        "summary": "Current price for a TLD lifecycle operation",
        "description": "New-registration pricing (not an aftermarket/marketplace price) — never gated by sign-in status.",
        "parameters": [
          { "name": "tld", "in": "query", "required": true, "schema": { "type": "string" }, "example": "ai" },
          {
            "name": "op",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "enum": ["transfer", "register", "renew", "restore"], "default": "transfer" }
          }
        ],
        "responses": {
          "200": {
            "description": "Price for the requested TLD/operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tld": { "type": "string" },
                    "op": { "type": "string" },
                    "priceCents": { "type": ["integer", "null"], "description": "USD cents. null if the TLD/op combination isn't supported." }
                  }
                }
              }
            }
          },
          "400": { "description": "tld missing, or op not one of transfer/register/renew/restore." }
        }
      }
    },
    "/api/tlds/{tld}/metadata": {
      "get": {
        "operationId": "tldRequirements",
        "summary": "Registration requirements for a TLD",
        "description": "Allowed registration period range, organization/nameserver requirements, and other registry policy, resolved from live registry data.",
        "parameters": [
          { "name": "tld", "in": "path", "required": true, "schema": { "type": "string" }, "example": "ai" }
        ],
        "responses": {
          "200": {
            "description": "TLD metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tld": { "type": "string" },
                    "provider": { "type": "string", "example": "Donuts" },
                    "periodsMonths": { "type": "array", "items": { "type": "integer" }, "description": "Allowed registration lengths, in months." },
                    "minPeriodMonths": { "type": "integer" },
                    "maxPeriodMonths": { "type": "integer" },
                    "allowedYears": { "type": "array", "items": { "type": "integer" } },
                    "minYears": { "type": "integer" },
                    "maxYears": { "type": "integer" },
                    "organizationRequired": { "type": "boolean" },
                    "organizationAllowed": { "type": "boolean" },
                    "allowedCountries": { "type": "array", "items": { "type": "string" }, "description": "Empty array means no country restriction." },
                    "minNameservers": { "type": "integer" },
                    "maxNameservers": { "type": "integer" },
                    "nameserversRequired": { "type": "boolean" },
                    "idnSupport": { "type": "boolean" },
                    "premiumSupport": { "type": "string", "example": "REGULAR" },
                    "transferRequiresAuthcode": { "type": "boolean" },
                    "featuresAvailable": {
                      "type": "array",
                      "items": { "type": "string", "enum": ["CREATE", "RENEW", "TRANSFER", "UPDATE", "DELETE", "RESTORE", "PRIVACY_PROTECT"] }
                    },
                    "source": { "type": "string", "enum": ["rtr"] },
                    "lastSyncedAt": { "type": "string", "format": "date-time" },
                    "stale": { "type": "boolean" }
                  }
                }
              }
            }
          },
          "404": { "description": "No metadata available for this TLD." }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "Optional — only /api/domain/search reads it, and only to unmask aftermarket prices. Every endpoint in this spec works with no auth at all. See /AUTH.md for the full flow (RFC 7591 dynamic client registration, PKCE required, no client secret).",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://name.ai/oauth/authorize",
            "tokenUrl": "https://name.ai/api/oauth/token",
            "scopes": {
              "pricing:read": "See real marketplace/aftermarket prices instead of the signed-out placeholder."
            }
          }
        }
      }
    }
  }
}
