// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../resource'; import * as Core from '../../core'; import * as DomainsAPI from './domains'; import { Domain as DomainsAPIDomain, DomainGetParams, DomainGetResponse, DomainListParams, DomainUpdateParams, DomainUpdateResponse, Domains, DomainsSinglePage, } from './domains'; import * as RegistrationStatusAPI from './registration-status'; import { RegistrationStatus, RegistrationStatusGetParams } from './registration-status'; import * as UpdateStatusAPI from './update-status'; import { UpdateStatus, UpdateStatusGetParams } from './update-status'; export class Registrar extends APIResource { domains: DomainsAPI.Domains = new DomainsAPI.Domains(this._client); registrationStatus: RegistrationStatusAPI.RegistrationStatus = new RegistrationStatusAPI.RegistrationStatus( this._client, ); updateStatus: UpdateStatusAPI.UpdateStatus = new UpdateStatusAPI.UpdateStatus(this._client); /** * Performs real-time, authoritative availability checks directly against domain * registries. Use this endpoint to verify a domain is available before attempting * registration via `POST /registrations`. * * **Important:** Unlike the Search endpoint, these results are authoritative and * reflect current registry status. Always check availability immediately before * registration as domain status can change rapidly. * * **Note:** This endpoint uses POST to accept a list of domains in the request * body. It is a read-only operation — it does not create, modify, or reserve any * domains. * * ### Extension support * * Only domains on extensions supported for programmatic registration by this API * can be registered. If you check a domain on an unsupported extension, the * response will include `registrable: false` with a `reason` field explaining why: * * - `extension_not_supported_via_api` — Cloudflare Registrar supports this * extension in the dashboard, but it is not yet available for programmatic * registration via this API. Register via * `https://dash.cloudflare.com/{account_id}/domains/registrations` instead. * - `extension_not_supported` — This extension is not supported by Cloudflare * Registrar. * - `extension_disallows_registration` — The extension's registry has temporarily * or permanently frozen new registrations. No registrar can register domains on * this extension at this time. * - `domain_premium` — The domain is premium priced. Premium registration is not * currently supported by this API. * - `domain_unavailable` — The domain is already registered, reserved, or * otherwise not available for registration on a supported extension. * * The `reason` field is only present when `registrable` is `false`. * * ### Behavior * * - Maximum 20 domains per request * - Pricing is only returned for domains where `registrable: true` * - Results are not cached; each request queries the registry * * ### Workflow * * 1. Call this endpoint with domains the user wants to register. * 2. For each domain where `registrable: true`, present pricing to the user. * 3. If `tier: premium`, note that premium registration is not currently supported * by this API and do not proceed to `POST /registrations`. * 4. Proceed to `POST /registrations` only for supported non-premium domains. * * @example * ```ts * const response = await client.registrar.check({ * account_id: '023e105f4ecef8ad9ca31a8372d0c353', * domains: [ * 'myawesomebrand.com', * 'myawesomebrand.net', * 'myawesomebrand.org', * 'myawesomebrand.app', * 'myawesomebrand.dev', * ], * }); * ``` */ check( params: RegistrarCheckParams, options?: Core.RequestOptions, ): Core.APIPromise { const { account_id, ...body } = params; return ( this._client.post(`/accounts/${account_id}/registrar/domain-check`, { body, ...options, }) as Core.APIPromise<{ result: RegistrarCheckResponse }> )._thenUnwrap((obj) => obj.result); } /** * Searches for domain name suggestions based on a keyword, phrase, or partial * domain name. Returns a list of potentially available domains with pricing * information. * * **Important:** Results are non-authoritative and based on cached data. Always * use the `/domain-check` endpoint to verify real-time availability before * attempting registration. * * Suggestions are scoped to extensions supported for programmatic registration via * this API (`POST /registrations`). Domains on unsupported extensions will not * appear in results, even if they are available at the registry level. * * ### Use cases * * - Brand name discovery (e.g., "acme corp" → acmecorp.com, acmecorp.dev) * - Keyword-based suggestions (e.g., "coffee shop" → coffeeshop.com, * mycoffeeshop.net) * - Alternative extension discovery (e.g., "example.com" → example.com, * example.app, example.xyz) * * ### Workflow * * 1. Call this endpoint with a keyword or domain name. * 2. Present suggestions to the user. * 3. Call `/domain-check` with the user's chosen domains to confirm real-time * availability and pricing. * 4. Proceed to `POST /registrations` only for supported non-premium domains where * the Check response returns `registrable: true`. * * **Note:** Searching with just a domain extension (e.g., "com" or ".app") is not * supported. Provide a keyword or domain name. * * @example * ```ts * const response = await client.registrar.search({ * account_id: '023e105f4ecef8ad9ca31a8372d0c353', * q: 'x', * }); * ``` */ search( params: RegistrarSearchParams, options?: Core.RequestOptions, ): Core.APIPromise { const { account_id, ...query } = params; return ( this._client.get(`/accounts/${account_id}/registrar/domain-search`, { query, ...options, }) as Core.APIPromise<{ result: RegistrarSearchResponse }> )._thenUnwrap((obj) => obj.result); } } /** * A domain registration resource representing the current state of a registered * domain. */ export interface Registration { /** * Whether the domain will be automatically renewed before expiration. */ auto_renew: boolean; /** * When the domain was registered. Present when the registration resource exists. */ created_at: string; /** * Fully qualified domain name (FQDN) including the extension (e.g., `example.com`, * `mybrand.app`). The domain name uniquely identifies a registration — the same * domain cannot be registered twice, making it a natural idempotency key for * registration requests. */ domain_name: string; /** * When the domain registration expires. Present when the registration is ready; * may be null only while `status` is `registration_pending`. */ expires_at: string | null; /** * Whether the domain is locked for transfer. */ locked: boolean; /** * Current WHOIS privacy mode for the registration. */ privacy_mode: 'redaction'; /** * Current registration status. * * - `active`: Domain is registered and operational * - `registration_pending`: Registration is in progress * - `expired`: Domain has expired * - `suspended`: Domain is suspended by the registry * - `redemption_period`: Domain is in the redemption grace period * - `pending_delete`: Domain is pending deletion by the registry */ status: | 'active' | 'registration_pending' | 'expired' | 'suspended' | 'redemption_period' | 'pending_delete'; } /** * Status of an async registration workflow. */ export interface WorkflowStatus { /** * Whether the workflow has reached a terminal state. `true` when `state` is * `succeeded` or `failed`. `false` for `pending`, `in_progress`, * `action_required`, and `blocked`. */ completed: boolean; created_at: string; links: WorkflowStatus.Links; /** * Workflow lifecycle state. * * - `pending`: Workflow has been created but not yet started processing. * - `in_progress`: Actively processing. Continue polling `links.self`. The * workflow has an internal deadline and will not remain in this state * indefinitely. * - `action_required`: Paused — requires action by the user (not the system). See * `context.action` for what is needed. An automated polling loop must break on * this state; it will not resolve on its own without user intervention. * - `blocked`: The workflow cannot make progress due to a third party such as the * domain extension's registry or a losing registrar. No user action will help. * Continue polling — the block may resolve when the third party responds. * - `succeeded`: Terminal. The operation completed successfully. `completed` will * be `true`. For registrations, `context.registration` contains the resulting * registration resource. * - `failed`: Terminal. The operation failed. `completed` will be `true`. See * `error.code` and `error.message` for the reason. Do not auto-retry without * user review. */ state: 'pending' | 'in_progress' | 'action_required' | 'blocked' | 'succeeded' | 'failed'; updated_at: string; /** * Workflow-specific data for this workflow. * * The workflow subject is identified by `context.domain_name` for domain-centric * workflows. */ context?: { [key: string]: unknown }; /** * Error details when a workflow reaches the `failed` state. The specific error * codes and messages depend on the workflow type (registration, update, etc.) and * the underlying registry response. These workflow error codes are separate from * immediate HTTP error `errors[].code` values returned by non-2xx responses. * Surface `error.message` to the user for context. */ error?: WorkflowStatus.Error | null; } export namespace WorkflowStatus { export interface Links { /** * URL to this status resource. */ self: string; /** * URL to the domain resource. */ resource?: string; } /** * Error details when a workflow reaches the `failed` state. The specific error * codes and messages depend on the workflow type (registration, update, etc.) and * the underlying registry response. These workflow error codes are separate from * immediate HTTP error `errors[].code` values returned by non-2xx responses. * Surface `error.message` to the user for context. */ export interface Error { /** * Machine-readable error code identifying the failure reason. */ code: string; /** * Human-readable explanation of the failure. May include registry-specific * details. */ message: string; } } /** * Contains the availability check results. */ export interface RegistrarCheckResponse { /** * Array of domain availability results. Domains on unsupported extensions are * included with `registrable: false` and a `reason` field. Malformed domain names * may be omitted. */ domains: Array; } export namespace RegistrarCheckResponse { /** * Represents a single authoritative domain availability result returned by the * Check endpoint. Check results reflect current registry status and should be used * immediately before registration. */ export interface Domain { /** * The fully qualified domain name (FQDN) in punycode format for internationalized * domain names (IDNs). */ name: string; /** * Indicates whether this domain can be registered programmatically through this * API based on a real-time registry check. * * - `true`: Domain is available for registration. The `pricing` object will be * included. * - `false`: Domain is not available. See the `reason` field for why. `tier` may * still be present on some non-registrable results, such as premium domains. */ registrable: boolean; /** * Annual pricing information for a registrable domain. This object is only present * when `registrable` is `true`. All prices are per year and returned as strings to * preserve decimal precision. * * `registration_cost` and `renewal_cost` are frequently the same value, but may * differ — especially for premium domains where registries set different rates for * initial registration vs. renewal. For a multi-year registration (e.g., 4 years), * the first year is charged at `registration_cost` and each subsequent year at * `renewal_cost`. Registry pricing may change over time; the values returned here * reflect the current registry rate. Premium pricing may be surfaced by Search and * Check, but premium registration is not currently supported by this API. */ pricing?: Domain.Pricing; /** * Present only when `registrable` is `false`. Explains why the domain cannot be * registered via this API. * * - `extension_not_supported_via_api`: Cloudflare Registrar supports this * extension in the dashboard but it is not yet available for programmatic * registration via this API. The user can register via * `https://dash.cloudflare.com/{account_id}/domains/registrations`. * - `extension_not_supported`: This extension is not supported by Cloudflare * Registrar at all. * - `extension_disallows_registration`: The extension's registry has temporarily * or permanently frozen new registrations. No registrar can register domains on * this extension at this time. * - `domain_premium`: The domain is premium priced. Premium registration is not * currently supported by this API. * - `domain_unavailable`: The domain is already registered, reserved, or otherwise * not available on a supported extension. */ reason?: | 'extension_not_supported_via_api' | 'extension_not_supported' | 'extension_disallows_registration' | 'domain_premium' | 'domain_unavailable'; /** * The pricing tier for this domain. Always present when `registrable` is `true`; * defaults to `standard` for most domains. May be absent when `registrable` is * `false`. * * - `standard`: Standard registry pricing * - `premium`: Premium domain with higher pricing set by the registry */ tier?: 'standard' | 'premium'; } export namespace Domain { /** * Annual pricing information for a registrable domain. This object is only present * when `registrable` is `true`. All prices are per year and returned as strings to * preserve decimal precision. * * `registration_cost` and `renewal_cost` are frequently the same value, but may * differ — especially for premium domains where registries set different rates for * initial registration vs. renewal. For a multi-year registration (e.g., 4 years), * the first year is charged at `registration_cost` and each subsequent year at * `renewal_cost`. Registry pricing may change over time; the values returned here * reflect the current registry rate. Premium pricing may be surfaced by Search and * Check, but premium registration is not currently supported by this API. */ export interface Pricing { /** * ISO-4217 currency code for the prices (e.g., "USD", "EUR", "GBP"). */ currency: string; /** * The first-year cost to register this domain. For premium domains * (`tier: premium`), this price is set by the registry and may be significantly * higher than standard pricing. For multi-year registrations, this cost applies to * the first year only; subsequent years are charged at `renewal_cost`. */ registration_cost: string; /** * Per-year renewal cost for this domain. Applied to each year beyond the first * year of a multi-year registration, and to each annual auto-renewal thereafter. * May differ from `registration_cost`, especially for premium domains where * initial registration often costs more than renewals. */ renewal_cost: string; } } } /** * Contains the search results. */ export interface RegistrarSearchResponse { /** * Array of domain suggestions sorted by relevance. May be empty if no domains * match the search criteria. */ domains: Array; } export namespace RegistrarSearchResponse { /** * Represents a single domain suggestion returned by the Search endpoint. Search * results are non-authoritative and may be based on cached data. Use POST * /domain-check to confirm real-time availability and pricing before registration. */ export interface Domain { /** * The fully qualified domain name (FQDN) in punycode format for internationalized * domain names (IDNs). */ name: string; /** * Indicates whether this domain appears available based on search data. Search * results are non-authoritative and may be stale. - `true`: The domain appears * available. Use POST /domain-check to confirm before registration. * * - `false`: The domain does not appear available in search results. */ registrable: boolean; /** * Annual pricing information for a registrable domain. This object is only present * when `registrable` is `true`. All prices are per year and returned as strings to * preserve decimal precision. * * `registration_cost` and `renewal_cost` are frequently the same value, but may * differ — especially for premium domains where registries set different rates for * initial registration vs. renewal. For a multi-year registration (e.g., 4 years), * the first year is charged at `registration_cost` and each subsequent year at * `renewal_cost`. Registry pricing may change over time; the values returned here * reflect the current registry rate. Premium pricing may be surfaced by Search and * Check, but premium registration is not currently supported by this API. */ pricing?: Domain.Pricing; /** * Present only when `registrable` is `false` on search results. Explains why the * domain does not appear registrable through this API. These values are advisory; * use POST /domain-check for authoritative status. * * - `extension_not_supported_via_api`: Cloudflare Registrar supports this * extension in the dashboard but it is not yet available for programmatic * registration via this API. * - `extension_not_supported`: This extension is not supported by Cloudflare * Registrar at all. * - `extension_disallows_registration`: The extension's registry has temporarily * or permanently frozen new registrations. * - `domain_premium`: The domain is premium priced. Premium registration is not * currently supported by this API. * - `domain_unavailable`: The domain appears unavailable. */ reason?: | 'extension_not_supported_via_api' | 'extension_not_supported' | 'extension_disallows_registration' | 'domain_premium' | 'domain_unavailable'; /** * The pricing tier for this domain. Always present when `registrable` is `true`; * defaults to `standard` for most domains. May be absent when `registrable` is * `false`. * * - `standard`: Standard registry pricing * - `premium`: Premium domain with higher pricing set by the registry */ tier?: 'standard' | 'premium'; } export namespace Domain { /** * Annual pricing information for a registrable domain. This object is only present * when `registrable` is `true`. All prices are per year and returned as strings to * preserve decimal precision. * * `registration_cost` and `renewal_cost` are frequently the same value, but may * differ — especially for premium domains where registries set different rates for * initial registration vs. renewal. For a multi-year registration (e.g., 4 years), * the first year is charged at `registration_cost` and each subsequent year at * `renewal_cost`. Registry pricing may change over time; the values returned here * reflect the current registry rate. Premium pricing may be surfaced by Search and * Check, but premium registration is not currently supported by this API. */ export interface Pricing { /** * ISO-4217 currency code for the prices (e.g., "USD", "EUR", "GBP"). */ currency: string; /** * The first-year cost to register this domain. For premium domains * (`tier: premium`), this price is set by the registry and may be significantly * higher than standard pricing. For multi-year registrations, this cost applies to * the first year only; subsequent years are charged at `renewal_cost`. */ registration_cost: string; /** * Per-year renewal cost for this domain. Applied to each year beyond the first * year of a multi-year registration, and to each annual auto-renewal thereafter. * May differ from `registration_cost`, especially for premium domains where * initial registration often costs more than renewals. */ renewal_cost: string; } } } export interface RegistrarCheckParams { /** * Path param: Identifier */ account_id: string; /** * Body param: List of fully qualified domain names (FQDNs) to check for * availability. Each domain must include the extension. * * - Minimum: 1 domain * - Maximum: 20 domains per request * - Domains on unsupported extensions are returned with `registrable: false` and a * `reason` field * - Malformed domain names (e.g., missing extension) may be omitted from the * response */ domains: Array; } export interface RegistrarSearchParams { /** * Path param: Identifier */ account_id: string; /** * Query param: The search term to find domain suggestions. Accepts keywords, * phrases, or full domain names. * * - Phrases: "coffee shop" returns coffeeshop.com, mycoffeeshop.net, etc. * - Domain names: "example.com" returns example.com and variations across * extensions */ q: string; /** * Query param: Limits results to specific domain extensions from the supported * set. If not specified, returns results across all supported extensions. * Extensions not in the supported set are silently ignored. */ extensions?: Array; /** * Query param: Maximum number of domain suggestions to return. Defaults to 20 if * not specified. */ limit?: number; } Registrar.Domains = Domains; Registrar.DomainsSinglePage = DomainsSinglePage; Registrar.RegistrationStatus = RegistrationStatus; Registrar.UpdateStatus = UpdateStatus; export declare namespace Registrar { export { type Registration as Registration, type WorkflowStatus as WorkflowStatus, type RegistrarCheckResponse as RegistrarCheckResponse, type RegistrarSearchResponse as RegistrarSearchResponse, type RegistrarCheckParams as RegistrarCheckParams, type RegistrarSearchParams as RegistrarSearchParams, }; export { Domains as Domains, type DomainsAPIDomain as Domain, type DomainUpdateResponse as DomainUpdateResponse, type DomainGetResponse as DomainGetResponse, DomainsSinglePage as DomainsSinglePage, type DomainUpdateParams as DomainUpdateParams, type DomainListParams as DomainListParams, type DomainGetParams as DomainGetParams, }; export { RegistrationStatus as RegistrationStatus, type RegistrationStatusGetParams as RegistrationStatusGetParams, }; export { UpdateStatus as UpdateStatus, type UpdateStatusGetParams as UpdateStatusGetParams }; }