# Registrar ## Search for available domains `client.Registrar.Search(ctx, params) (*RegistrarSearchResponse, error)` **get** `/accounts/{account_id}/registrar/domain-search` 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. 1. Present suggestions to the user. 1. Call `/domain-check` with the user's chosen domains to confirm real-time availability and pricing. 1. 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. ### Parameters - `params RegistrarSearchParams` - `AccountID param.Field[string]` Path param: Identifier - `Q param.Field[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 - `Extensions param.Field[[]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. - `Limit param.Field[int64]` Query param: Maximum number of domain suggestions to return. Defaults to 20 if not specified. ### Returns - `type RegistrarSearchResponse struct{…}` Contains the search results. - `Domains []RegistrarSearchResponseDomain` Array of domain suggestions sorted by relevance. May be empty if no domains match the search criteria. - `Name string` The fully qualified domain name (FQDN) in punycode format for internationalized domain names (IDNs). - `Registrable bool` 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. - `Pricing RegistrarSearchResponseDomainsPricing` 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. - `Currency string` ISO-4217 currency code for the prices (e.g., "USD", "EUR", "GBP"). - `RegistrationCost 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`. - `RenewalCost 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. - `Reason RegistrarSearchResponseDomainsReason` 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. - `const RegistrarSearchResponseDomainsReasonExtensionNotSupportedViaAPI RegistrarSearchResponseDomainsReason = "extension_not_supported_via_api"` - `const RegistrarSearchResponseDomainsReasonExtensionNotSupported RegistrarSearchResponseDomainsReason = "extension_not_supported"` - `const RegistrarSearchResponseDomainsReasonExtensionDisallowsRegistration RegistrarSearchResponseDomainsReason = "extension_disallows_registration"` - `const RegistrarSearchResponseDomainsReasonDomainPremium RegistrarSearchResponseDomainsReason = "domain_premium"` - `const RegistrarSearchResponseDomainsReasonDomainUnavailable RegistrarSearchResponseDomainsReason = "domain_unavailable"` - `Tier RegistrarSearchResponseDomainsTier` 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 - `const RegistrarSearchResponseDomainsTierStandard RegistrarSearchResponseDomainsTier = "standard"` - `const RegistrarSearchResponseDomainsTierPremium RegistrarSearchResponseDomainsTier = "premium"` ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) response, err := client.Registrar.Search(context.TODO(), registrar.RegistrarSearchParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), Q: cloudflare.F("x"), }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", response.Domains) } ``` #### Response ```json { "errors": [], "messages": [], "result": { "domains": [ { "name": "acmecorp.com", "pricing": { "currency": "USD", "registration_cost": "8.57", "renewal_cost": "8.57" }, "registrable": true, "tier": "standard" }, { "name": "acmecorp.dev", "pricing": { "currency": "USD", "registration_cost": "10.11", "renewal_cost": "10.11" }, "registrable": true, "tier": "standard" }, { "name": "acmecorp.app", "pricing": { "currency": "USD", "registration_cost": "11.00", "renewal_cost": "11.00" }, "registrable": true, "tier": "standard" } ] }, "success": true } ``` ## Check domain availability `client.Registrar.Check(ctx, params) (*RegistrarCheckResponse, error)` **post** `/accounts/{account_id}/registrar/domain-check` 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. 1. For each domain where `registrable: true`, present pricing to the user. 1. If `tier: premium`, note that premium registration is not currently supported by this API and do not proceed to `POST /registrations`. 1. Proceed to `POST /registrations` only for supported non-premium domains. ### Parameters - `params RegistrarCheckParams` - `AccountID param.Field[string]` Path param: Identifier - `Domains param.Field[[]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 ### Returns - `type RegistrarCheckResponse struct{…}` Contains the availability check results. - `Domains []RegistrarCheckResponseDomain` Array of domain availability results. Domains on unsupported extensions are included with `registrable: false` and a `reason` field. Malformed domain names may be omitted. - `Name string` The fully qualified domain name (FQDN) in punycode format for internationalized domain names (IDNs). - `Registrable bool` 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. - `Pricing RegistrarCheckResponseDomainsPricing` 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. - `Currency string` ISO-4217 currency code for the prices (e.g., "USD", "EUR", "GBP"). - `RegistrationCost 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`. - `RenewalCost 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. - `Reason RegistrarCheckResponseDomainsReason` 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. - `const RegistrarCheckResponseDomainsReasonExtensionNotSupportedViaAPI RegistrarCheckResponseDomainsReason = "extension_not_supported_via_api"` - `const RegistrarCheckResponseDomainsReasonExtensionNotSupported RegistrarCheckResponseDomainsReason = "extension_not_supported"` - `const RegistrarCheckResponseDomainsReasonExtensionDisallowsRegistration RegistrarCheckResponseDomainsReason = "extension_disallows_registration"` - `const RegistrarCheckResponseDomainsReasonDomainPremium RegistrarCheckResponseDomainsReason = "domain_premium"` - `const RegistrarCheckResponseDomainsReasonDomainUnavailable RegistrarCheckResponseDomainsReason = "domain_unavailable"` - `Tier RegistrarCheckResponseDomainsTier` 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 - `const RegistrarCheckResponseDomainsTierStandard RegistrarCheckResponseDomainsTier = "standard"` - `const RegistrarCheckResponseDomainsTierPremium RegistrarCheckResponseDomainsTier = "premium"` ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) response, err := client.Registrar.Check(context.TODO(), registrar.RegistrarCheckParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), Domains: cloudflare.F([]string{"myawesomebrand.com", "myawesomebrand.net", "myawesomebrand.org", "myawesomebrand.app", "myawesomebrand.dev"}), }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", response.Domains) } ``` #### Response ```json { "errors": [], "messages": [], "result": { "domains": [ { "name": "xq7mz9brand.com", "pricing": { "currency": "USD", "registration_cost": "8.57", "renewal_cost": "8.57" }, "registrable": true, "tier": "standard" }, { "name": "xq7mz9brand.net", "pricing": { "currency": "USD", "registration_cost": "9.95", "renewal_cost": "9.95" }, "registrable": true, "tier": "standard" } ] }, "success": true } ``` ## Domain Types ### Registration - `type Registration struct{…}` A domain registration resource representing the current state of a registered domain. - `AutoRenew bool` Whether the domain will be automatically renewed before expiration. - `CreatedAt Time` When the domain was registered. Present when the registration resource exists. - `DomainName 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. - `ExpiresAt Time` When the domain registration expires. Present when the registration is ready; may be null only while `status` is `registration_pending`. - `Locked bool` Whether the domain is locked for transfer. - `PrivacyMode RegistrationPrivacyMode` Current WHOIS privacy mode for the registration. - `const RegistrationPrivacyModeRedaction RegistrationPrivacyMode = "redaction"` - `Status RegistrationStatus` 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 - `const RegistrationStatusActive RegistrationStatus = "active"` - `const RegistrationStatusRegistrationPending RegistrationStatus = "registration_pending"` - `const RegistrationStatusExpired RegistrationStatus = "expired"` - `const RegistrationStatusSuspended RegistrationStatus = "suspended"` - `const RegistrationStatusRedemptionPeriod RegistrationStatus = "redemption_period"` - `const RegistrationStatusPendingDelete RegistrationStatus = "pending_delete"` ### Workflow Status - `type WorkflowStatus struct{…}` Status of an async registration workflow. - `Completed bool` Whether the workflow has reached a terminal state. `true` when `state` is `succeeded` or `failed`. `false` for `pending`, `in_progress`, `action_required`, and `blocked`. - `CreatedAt Time` - `Links WorkflowStatusLinks` - `Self string` URL to this status resource. - `Resource string` URL to the domain resource. - `State WorkflowStatusState` 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. - `const WorkflowStatusStatePending WorkflowStatusState = "pending"` - `const WorkflowStatusStateInProgress WorkflowStatusState = "in_progress"` - `const WorkflowStatusStateActionRequired WorkflowStatusState = "action_required"` - `const WorkflowStatusStateBlocked WorkflowStatusState = "blocked"` - `const WorkflowStatusStateSucceeded WorkflowStatusState = "succeeded"` - `const WorkflowStatusStateFailed WorkflowStatusState = "failed"` - `UpdatedAt Time` - `Context map[string, unknown]` Workflow-specific data for this workflow. The workflow subject is identified by `context.domain_name` for domain-centric workflows. - `Error WorkflowStatusError` 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. - `Code string` Machine-readable error code identifying the failure reason. - `Message string` Human-readable explanation of the failure. May include registry-specific details. # Domains ## List domains `client.Registrar.Domains.List(ctx, query) (*SinglePage[Domain], error)` **get** `/accounts/{account_id}/registrar/domains` List domains handled by Registrar. ### Parameters - `query DomainListParams` - `AccountID param.Field[string]` Identifier ### Returns - `type Domain struct{…}` - `ID string` Domain identifier. - `Available bool` Shows if a domain is available for transferring into Cloudflare Registrar. - `CanRegister bool` Indicates if the domain can be registered as a new domain. - `CreatedAt Time` Shows time of creation. - `CurrentRegistrar string` Shows name of current registrar. - `ExpiresAt Time` Shows when domain name registration expires. - `Locked bool` Shows whether a registrar lock is in place for a domain. - `RegistrantContact DomainRegistrantContact` Shows contact information for domain registrant. - `Address string` Address. - `City string` City. - `Country string` The country in which the user lives. - `FirstName string` User's first name - `LastName string` User's last name - `Organization string` Name of organization. - `Phone string` User's telephone number - `State string` State. - `Zip string` The zipcode or postal code where the user lives. - `ID string` Contact Identifier. - `Address2 string` Optional address line for unit, floor, suite, etc. - `Email string` The contact email address of the user. - `Fax string` Contact fax number. - `RegistryStatuses string` A comma-separated list of registry status codes. A full list of status codes can be found at [EPP Status Codes](https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en). - `SupportedTLD bool` Whether a particular TLD is currently supported by Cloudflare Registrar. Refer to [TLD Policies](https://www.cloudflare.com/tld-policies/) for a list of supported TLDs. - `TransferIn DomainTransferIn` Statuses for domain transfers into Cloudflare Registrar. - `AcceptFoa DomainTransferInAcceptFoa` Form of authorization has been accepted by the registrant. - `const DomainTransferInAcceptFoaNeeded DomainTransferInAcceptFoa = "needed"` - `const DomainTransferInAcceptFoaOk DomainTransferInAcceptFoa = "ok"` - `ApproveTransfer DomainTransferInApproveTransfer` Shows transfer status with the registry. - `const DomainTransferInApproveTransferNeeded DomainTransferInApproveTransfer = "needed"` - `const DomainTransferInApproveTransferOk DomainTransferInApproveTransfer = "ok"` - `const DomainTransferInApproveTransferPending DomainTransferInApproveTransfer = "pending"` - `const DomainTransferInApproveTransferTrying DomainTransferInApproveTransfer = "trying"` - `const DomainTransferInApproveTransferRejected DomainTransferInApproveTransfer = "rejected"` - `const DomainTransferInApproveTransferUnknown DomainTransferInApproveTransfer = "unknown"` - `CanCancelTransfer bool` Indicates if cancellation is still possible. - `DisablePrivacy DomainTransferInDisablePrivacy` Privacy guards are disabled at the foreign registrar. - `const DomainTransferInDisablePrivacyNeeded DomainTransferInDisablePrivacy = "needed"` - `const DomainTransferInDisablePrivacyOk DomainTransferInDisablePrivacy = "ok"` - `const DomainTransferInDisablePrivacyUnknown DomainTransferInDisablePrivacy = "unknown"` - `EnterAuthCode DomainTransferInEnterAuthCode` Auth code has been entered and verified. - `const DomainTransferInEnterAuthCodeNeeded DomainTransferInEnterAuthCode = "needed"` - `const DomainTransferInEnterAuthCodeOk DomainTransferInEnterAuthCode = "ok"` - `const DomainTransferInEnterAuthCodePending DomainTransferInEnterAuthCode = "pending"` - `const DomainTransferInEnterAuthCodeTrying DomainTransferInEnterAuthCode = "trying"` - `const DomainTransferInEnterAuthCodeRejected DomainTransferInEnterAuthCode = "rejected"` - `UnlockDomain DomainTransferInUnlockDomain` Domain is unlocked at the foreign registrar. - `const DomainTransferInUnlockDomainNeeded DomainTransferInUnlockDomain = "needed"` - `const DomainTransferInUnlockDomainOk DomainTransferInUnlockDomain = "ok"` - `const DomainTransferInUnlockDomainPending DomainTransferInUnlockDomain = "pending"` - `const DomainTransferInUnlockDomainTrying DomainTransferInUnlockDomain = "trying"` - `const DomainTransferInUnlockDomainUnknown DomainTransferInUnlockDomain = "unknown"` - `UpdatedAt Time` Last updated. ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) page, err := client.Registrar.Domains.List(context.TODO(), registrar.DomainListParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", page) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": [ { "id": "ea95132c15732412d22c1476fa83f27a", "available": false, "can_register": false, "created_at": "2018-08-28T17:26:26Z", "current_registrar": "Cloudflare", "expires_at": "2019-08-28T23:59:59Z", "locked": false, "registrant_contact": { "address": "123 Sesame St.", "city": "Austin", "country": "US", "first_name": "John", "last_name": "Appleseed", "organization": "Cloudflare, Inc.", "phone": "+1 123-123-1234", "state": "TX", "zip": "12345", "id": "ea95132c15732412d22c1476fa83f27a", "address2": "Suite 430", "email": "user@example.com", "fax": "123-867-5309" }, "registry_statuses": "ok,serverTransferProhibited", "supported_tld": true, "transfer_in": { "accept_foa": "needed", "approve_transfer": "unknown", "can_cancel_transfer": true, "disable_privacy": "ok", "enter_auth_code": "needed", "unlock_domain": "ok" }, "updated_at": "2018-08-28T17:26:26Z" } ], "success": true, "result_info": { "count": 1, "page": 1, "per_page": 20, "total_count": 2000 } } ``` ## Get domain `client.Registrar.Domains.Get(ctx, domainName, query) (*DomainGetResponse, error)` **get** `/accounts/{account_id}/registrar/domains/{domain_name}` Show individual domain. ### Parameters - `domainName 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. - `query DomainGetParams` - `AccountID param.Field[string]` Identifier ### Returns - `type DomainGetResponse interface{…}` ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) domain, err := client.Registrar.Domains.Get( context.TODO(), "example.com", registrar.DomainGetParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", domain) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": {}, "success": true } ``` ## Update domain `client.Registrar.Domains.Update(ctx, domainName, params) (*DomainUpdateResponse, error)` **put** `/accounts/{account_id}/registrar/domains/{domain_name}` Update individual domain. ### Parameters - `domainName 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. - `params DomainUpdateParams` - `AccountID param.Field[string]` Path param: Identifier - `AutoRenew param.Field[bool]` Body param: Auto-renew controls whether subscription is automatically renewed upon domain expiration. - `Locked param.Field[bool]` Body param: Shows whether a registrar lock is in place for a domain. - `Privacy param.Field[bool]` Body param: Privacy option controls redacting WHOIS information. ### Returns - `type DomainUpdateResponse interface{…}` ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) domain, err := client.Registrar.Domains.Update( context.TODO(), "example.com", registrar.DomainUpdateParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", domain) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": {}, "success": true } ``` ## Domain Types ### Domain - `type Domain struct{…}` - `ID string` Domain identifier. - `Available bool` Shows if a domain is available for transferring into Cloudflare Registrar. - `CanRegister bool` Indicates if the domain can be registered as a new domain. - `CreatedAt Time` Shows time of creation. - `CurrentRegistrar string` Shows name of current registrar. - `ExpiresAt Time` Shows when domain name registration expires. - `Locked bool` Shows whether a registrar lock is in place for a domain. - `RegistrantContact DomainRegistrantContact` Shows contact information for domain registrant. - `Address string` Address. - `City string` City. - `Country string` The country in which the user lives. - `FirstName string` User's first name - `LastName string` User's last name - `Organization string` Name of organization. - `Phone string` User's telephone number - `State string` State. - `Zip string` The zipcode or postal code where the user lives. - `ID string` Contact Identifier. - `Address2 string` Optional address line for unit, floor, suite, etc. - `Email string` The contact email address of the user. - `Fax string` Contact fax number. - `RegistryStatuses string` A comma-separated list of registry status codes. A full list of status codes can be found at [EPP Status Codes](https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en). - `SupportedTLD bool` Whether a particular TLD is currently supported by Cloudflare Registrar. Refer to [TLD Policies](https://www.cloudflare.com/tld-policies/) for a list of supported TLDs. - `TransferIn DomainTransferIn` Statuses for domain transfers into Cloudflare Registrar. - `AcceptFoa DomainTransferInAcceptFoa` Form of authorization has been accepted by the registrant. - `const DomainTransferInAcceptFoaNeeded DomainTransferInAcceptFoa = "needed"` - `const DomainTransferInAcceptFoaOk DomainTransferInAcceptFoa = "ok"` - `ApproveTransfer DomainTransferInApproveTransfer` Shows transfer status with the registry. - `const DomainTransferInApproveTransferNeeded DomainTransferInApproveTransfer = "needed"` - `const DomainTransferInApproveTransferOk DomainTransferInApproveTransfer = "ok"` - `const DomainTransferInApproveTransferPending DomainTransferInApproveTransfer = "pending"` - `const DomainTransferInApproveTransferTrying DomainTransferInApproveTransfer = "trying"` - `const DomainTransferInApproveTransferRejected DomainTransferInApproveTransfer = "rejected"` - `const DomainTransferInApproveTransferUnknown DomainTransferInApproveTransfer = "unknown"` - `CanCancelTransfer bool` Indicates if cancellation is still possible. - `DisablePrivacy DomainTransferInDisablePrivacy` Privacy guards are disabled at the foreign registrar. - `const DomainTransferInDisablePrivacyNeeded DomainTransferInDisablePrivacy = "needed"` - `const DomainTransferInDisablePrivacyOk DomainTransferInDisablePrivacy = "ok"` - `const DomainTransferInDisablePrivacyUnknown DomainTransferInDisablePrivacy = "unknown"` - `EnterAuthCode DomainTransferInEnterAuthCode` Auth code has been entered and verified. - `const DomainTransferInEnterAuthCodeNeeded DomainTransferInEnterAuthCode = "needed"` - `const DomainTransferInEnterAuthCodeOk DomainTransferInEnterAuthCode = "ok"` - `const DomainTransferInEnterAuthCodePending DomainTransferInEnterAuthCode = "pending"` - `const DomainTransferInEnterAuthCodeTrying DomainTransferInEnterAuthCode = "trying"` - `const DomainTransferInEnterAuthCodeRejected DomainTransferInEnterAuthCode = "rejected"` - `UnlockDomain DomainTransferInUnlockDomain` Domain is unlocked at the foreign registrar. - `const DomainTransferInUnlockDomainNeeded DomainTransferInUnlockDomain = "needed"` - `const DomainTransferInUnlockDomainOk DomainTransferInUnlockDomain = "ok"` - `const DomainTransferInUnlockDomainPending DomainTransferInUnlockDomain = "pending"` - `const DomainTransferInUnlockDomainTrying DomainTransferInUnlockDomain = "trying"` - `const DomainTransferInUnlockDomainUnknown DomainTransferInUnlockDomain = "unknown"` - `UpdatedAt Time` Last updated. # Registrations ## Create Registration `client.Registrar.Registrations.New(ctx, params) (*WorkflowStatus, error)` **post** `/accounts/{account_id}/registrar/registrations` Starts a domain registration workflow. This is a billable operation — successful registration charges the account's default payment method. All successful domain registrations are non-refundable — once the workflow completes with `state: succeeded`, the charge cannot be reversed. ### Prerequisites - The account must have a billing profile with a valid default payment method. Set this up at `https://dash.cloudflare.com/{account_id}/billing/payment-info`. - The account must not already be at the maximum supported domain limit. A single account may own up to 100 domains in total across registrations created through either the dashboard or this API. - The domain must be on a supported extension for programmatic registration. - Use `POST /domain-check` immediately before calling this endpoint to confirm real-time availability and pricing. ### Supported extensions In this API, "extension" means the full registrable suffix after the domain label. For example, in `example.co.uk`, the extension is `co.uk`. Programmatic registration is currently supported for: `com`, `org`, `net`, `app`, `dev`, `cc`, `xyz`, `info`, `cloud`, `studio`, `live`, `link`, `pro`, `tech`, `fyi`, `shop`, `online`, `tools`, `run`, `games`, `build`, `systems`, `world`, `news`, `site`, `network`, `chat`, `space`, `family`, `page`, `life`, `group`, `email`, `solutions`, `day`, `blog`, `ing`, `icu`, `academy`, `today` Cloudflare Registrar supports 400+ extensions in the dashboard. Extensions not listed above can still be registered at `https://dash.cloudflare.com/{account_id}/domains/registrations`. ### Express mode The only required field is `domain_name`. If `contacts` is omitted, the system uses the account's default address book entry as the registrant. If no default exists and no contact is provided, the request fails. Set up a default address book entry and accept the required agreement at `https://dash.cloudflare.com/{account_id}/domains/registrations`. ### Defaults - `years`: defaults to the extension's minimum registration period (1 year for most extensions, but varies — for example, `.ai` (if supported) requires a minimum of 2 years). - `auto_renew`: defaults to `false`. Setting it to `true` is an explicit opt-in authorizing Cloudflare to charge the account's default payment method up to 30 days before domain expiry to renew the registration. Renewal pricing may change over time based on registry pricing. - `privacy_mode`: defaults to `redaction`. ### Premium domains Premium domain registration is not currently supported by this API. If `POST /domain-check` returns `tier: premium`, do not call this endpoint for that domain. ### Response behavior By default, the server holds the connection for a bounded, server-defined amount of time while the registration completes. Most registrations finish within this window and return `201 Created` with a completed workflow status. If the registration is still processing after this synchronous wait window, the server returns `202 Accepted`. Poll the URL in `links.self` to track progress. To skip the wait and receive an immediate `202`, send `Prefer: respond-async`. ### Parameters - `params RegistrationNewParams` - `AccountID param.Field[string]` Path param: Identifier - `DomainName param.Field[string]` Body param: 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. - `AutoRenew param.Field[bool]` Body param: Enable or disable automatic renewal. Defaults to `false` if omitted. Setting this field to `true` is an explicit opt-in authorizing Cloudflare to charge the account's default payment method up to 30 days before domain expiry to renew the domain automatically. Renewal pricing may change over time based on registry pricing. - `Contacts param.Field[RegistrationNewParamsContacts]` Body param: Contact data for the registration request. If the `contacts` object is omitted entirely from the request, or if `contacts.registrant` is not provided, the system will use the account's default address book entry as the registrant contact. This default must be pre-configured by the account owner at `https://dash.cloudflare.com/{account_id}/domains/registrations`, where they can create or update the address book entry and accept the required agreement. No API exists for managing address book entries at this time. If no default address book entry exists and no registrant contact is provided, the registration request will fail with a validation error. - `Registrant RegistrationNewParamsContactsRegistrant` Registrant contact data for the domain registration. This information is submitted to the domain registry and, depending on extension and privacy settings, may appear in public WHOIS records. - `Email string` Email address for the registrant. Used for domain-related communications from the registry, including ownership verification and renewal notices. - `Phone string` Phone number in E.164 format: `+{country_code}.{number}` with no spaces or dashes. Examples: `+1.5555555555` (US), `+44.2071234567` (UK), `+81.312345678` (Japan). - `PostalInfo RegistrationNewParamsContactsRegistrantPostalInfo` Postal/mailing information for the registrant contact. - `Address RegistrationNewParamsContactsRegistrantPostalInfoAddress` Physical mailing address for the registrant contact. - `City string` City or locality name. - `CountryCode string` Two-letter country code per ISO 3166-1 alpha-2 (e.g., `US`, `GB`, `CA`, `DE`). - `PostalCode string` Postal or ZIP code. - `State string` State, province, or region. Use the standard abbreviation where applicable (e.g., `TX` for Texas, `ON` for Ontario). - `Street string` Street address including building/suite number. - `Name string` Full legal name of the registrant (individual or authorized representative). - `Organization string` Organization or company name. Optional for individual registrants. - `Fax string` Fax number in E.164 format (e.g., `+1.5555555555`). Optional. Most registrations do not require a fax number. - `PrivacyMode param.Field[RegistrationNewParamsPrivacyMode]` Body param: WHOIS privacy mode for the registration. Defaults to `redaction`. - `off`: Do not request WHOIS privacy. - `redaction`: Request WHOIS redaction where supported by the extension. Some extensions do not support privacy/redaction. - `const RegistrationNewParamsPrivacyModeRedaction RegistrationNewParamsPrivacyMode = "redaction"` - `Years param.Field[int64]` Body param: Number of years to register (1–10). If omitted, defaults to the minimum registration period required by the registry for this extension. For most extensions this is 1 year, but some extensions require longer minimum terms (e.g., `.ai` requires a minimum of 2 years). The registry for each extension may also enforce its own maximum registration term. If the requested value exceeds the registry's maximum, the registration will be rejected. When in doubt, use the default by omitting this field. - `Prefer param.Field[string]` Header param: Set to `respond-async` to receive an immediate `202 Accepted` without waiting for the operation to complete (RFC 7240). The header may be combined with other preferences using standard comma-separated syntax. ### Returns - `type WorkflowStatus struct{…}` Status of an async registration workflow. - `Completed bool` Whether the workflow has reached a terminal state. `true` when `state` is `succeeded` or `failed`. `false` for `pending`, `in_progress`, `action_required`, and `blocked`. - `CreatedAt Time` - `Links WorkflowStatusLinks` - `Self string` URL to this status resource. - `Resource string` URL to the domain resource. - `State WorkflowStatusState` 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. - `const WorkflowStatusStatePending WorkflowStatusState = "pending"` - `const WorkflowStatusStateInProgress WorkflowStatusState = "in_progress"` - `const WorkflowStatusStateActionRequired WorkflowStatusState = "action_required"` - `const WorkflowStatusStateBlocked WorkflowStatusState = "blocked"` - `const WorkflowStatusStateSucceeded WorkflowStatusState = "succeeded"` - `const WorkflowStatusStateFailed WorkflowStatusState = "failed"` - `UpdatedAt Time` - `Context map[string, unknown]` Workflow-specific data for this workflow. The workflow subject is identified by `context.domain_name` for domain-centric workflows. - `Error WorkflowStatusError` 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. - `Code string` Machine-readable error code identifying the failure reason. - `Message string` Human-readable explanation of the failure. May include registry-specific details. ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) workflowStatus, err := client.Registrar.Registrations.New(context.TODO(), registrar.RegistrationNewParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), DomainName: cloudflare.F("my-new-startup.com"), }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", workflowStatus.Completed) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": { "completed": false, "created_at": "2019-12-27T18:11:19.117Z", "links": { "self": "/accounts/{account_id}/registrar/registrations/example.com/registration-status", "resource": "/accounts/{account_id}/registrar/registrations/example.com" }, "state": "in_progress", "updated_at": "2019-12-27T18:11:19.117Z", "context": { "foo": "bar" }, "error": { "code": "registry_rejected", "message": "Registry rejected the request." } }, "success": true } ``` ## List Registrations `client.Registrar.Registrations.List(ctx, params) (*CursorPagination[Registration], error)` **get** `/accounts/{account_id}/registrar/registrations` Returns a paginated list of domain registrations owned by the account. This endpoint uses cursor-based pagination. Results are ordered by registration date by default. To fetch the next page, pass the `cursor` value from the `result_info` object in the response as the `cursor` query parameter in your next request. An empty `cursor` string indicates there are no more pages. ### Parameters - `params RegistrationListParams` - `AccountID param.Field[string]` Path param: Identifier - `Cursor param.Field[string]` Query param: Opaque token from a previous response's `result_info.cursor`. Pass this value to fetch the next page of results. Omit (or pass an empty string) for the first page. - `Direction param.Field[RegistrationListParamsDirection]` Query param: Sort direction for results. Defaults to ascending order. - `const RegistrationListParamsDirectionAsc RegistrationListParamsDirection = "asc"` - `const RegistrationListParamsDirectionDesc RegistrationListParamsDirection = "desc"` - `PerPage param.Field[int64]` Query param: Number of items to return per page. - `SortBy param.Field[RegistrationListParamsSortBy]` Query param: Column to sort results by. Defaults to registration date (`registry_created_at`) when omitted. - `const RegistrationListParamsSortByRegistryCreatedAt RegistrationListParamsSortBy = "registry_created_at"` - `const RegistrationListParamsSortByRegistryExpiresAt RegistrationListParamsSortBy = "registry_expires_at"` - `const RegistrationListParamsSortByName RegistrationListParamsSortBy = "name"` ### Returns - `type Registration struct{…}` A domain registration resource representing the current state of a registered domain. - `AutoRenew bool` Whether the domain will be automatically renewed before expiration. - `CreatedAt Time` When the domain was registered. Present when the registration resource exists. - `DomainName 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. - `ExpiresAt Time` When the domain registration expires. Present when the registration is ready; may be null only while `status` is `registration_pending`. - `Locked bool` Whether the domain is locked for transfer. - `PrivacyMode RegistrationPrivacyMode` Current WHOIS privacy mode for the registration. - `const RegistrationPrivacyModeRedaction RegistrationPrivacyMode = "redaction"` - `Status RegistrationStatus` 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 - `const RegistrationStatusActive RegistrationStatus = "active"` - `const RegistrationStatusRegistrationPending RegistrationStatus = "registration_pending"` - `const RegistrationStatusExpired RegistrationStatus = "expired"` - `const RegistrationStatusSuspended RegistrationStatus = "suspended"` - `const RegistrationStatusRedemptionPeriod RegistrationStatus = "redemption_period"` - `const RegistrationStatusPendingDelete RegistrationStatus = "pending_delete"` ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) page, err := client.Registrar.Registrations.List(context.TODO(), registrar.RegistrationListParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", page) } ``` #### Response ```json { "errors": [], "messages": [], "result": [], "result_info": { "count": 0, "cursor": "", "per_page": 20 }, "success": true } ``` ## Get Registration `client.Registrar.Registrations.Get(ctx, domainName, query) (*Registration, error)` **get** `/accounts/{account_id}/registrar/registrations/{domain_name}` Returns the current state of a domain registration. This is the canonical read endpoint for a domain you own. It returns the full registration resource including current settings and expiration. When the registration resource is ready, both `created_at` and `expires_at` are present in the response. ### Parameters - `domainName 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. - `query RegistrationGetParams` - `AccountID param.Field[string]` Identifier ### Returns - `type Registration struct{…}` A domain registration resource representing the current state of a registered domain. - `AutoRenew bool` Whether the domain will be automatically renewed before expiration. - `CreatedAt Time` When the domain was registered. Present when the registration resource exists. - `DomainName 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. - `ExpiresAt Time` When the domain registration expires. Present when the registration is ready; may be null only while `status` is `registration_pending`. - `Locked bool` Whether the domain is locked for transfer. - `PrivacyMode RegistrationPrivacyMode` Current WHOIS privacy mode for the registration. - `const RegistrationPrivacyModeRedaction RegistrationPrivacyMode = "redaction"` - `Status RegistrationStatus` 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 - `const RegistrationStatusActive RegistrationStatus = "active"` - `const RegistrationStatusRegistrationPending RegistrationStatus = "registration_pending"` - `const RegistrationStatusExpired RegistrationStatus = "expired"` - `const RegistrationStatusSuspended RegistrationStatus = "suspended"` - `const RegistrationStatusRedemptionPeriod RegistrationStatus = "redemption_period"` - `const RegistrationStatusPendingDelete RegistrationStatus = "pending_delete"` ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) registration, err := client.Registrar.Registrations.Get( context.TODO(), "example.com", registrar.RegistrationGetParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", registration.AutoRenew) } ``` #### Response ```json { "errors": [], "messages": [], "result": { "auto_renew": true, "created_at": "2025-01-15T10:00:00Z", "domain_name": "example.com", "expires_at": "2026-01-15T10:00:00Z", "locked": true, "privacy_mode": "redaction", "status": "active" }, "success": true } ``` ## Update Registration `client.Registrar.Registrations.Edit(ctx, domainName, params) (*WorkflowStatus, error)` **patch** `/accounts/{account_id}/registrar/registrations/{domain_name}` Updates an existing domain registration. By default, the server holds the connection for a bounded, server-defined amount of time while the update completes. Most updates finish within this window and return `200 OK` with a completed workflow status. If the update is still processing after this synchronous wait window, the server returns `202 Accepted`. Poll the URL in `links.self` to track progress. To skip the wait and receive an immediate `202`, send `Prefer: respond-async`. This endpoint currently supports updating `auto_renew` only. ### Parameters - `domainName 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. - `params RegistrationEditParams` - `AccountID param.Field[string]` Path param: Identifier - `AutoRenew param.Field[bool]` Body param: Enable or disable automatic renewal. Setting this field to `true` authorizes Cloudflare to charge the account's default payment method up to 30 days before domain expiry to renew the domain automatically. Renewal pricing may change over time based on registry pricing. - `Prefer param.Field[RegistrationEditParamsPrefer]` Header param: Set to `respond-async` to receive an immediate `202 Accepted` without waiting for the operation to complete (RFC 7240). - `const RegistrationEditParamsPreferRespondAsync RegistrationEditParamsPrefer = "respond-async"` ### Returns - `type WorkflowStatus struct{…}` Status of an async registration workflow. - `Completed bool` Whether the workflow has reached a terminal state. `true` when `state` is `succeeded` or `failed`. `false` for `pending`, `in_progress`, `action_required`, and `blocked`. - `CreatedAt Time` - `Links WorkflowStatusLinks` - `Self string` URL to this status resource. - `Resource string` URL to the domain resource. - `State WorkflowStatusState` 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. - `const WorkflowStatusStatePending WorkflowStatusState = "pending"` - `const WorkflowStatusStateInProgress WorkflowStatusState = "in_progress"` - `const WorkflowStatusStateActionRequired WorkflowStatusState = "action_required"` - `const WorkflowStatusStateBlocked WorkflowStatusState = "blocked"` - `const WorkflowStatusStateSucceeded WorkflowStatusState = "succeeded"` - `const WorkflowStatusStateFailed WorkflowStatusState = "failed"` - `UpdatedAt Time` - `Context map[string, unknown]` Workflow-specific data for this workflow. The workflow subject is identified by `context.domain_name` for domain-centric workflows. - `Error WorkflowStatusError` 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. - `Code string` Machine-readable error code identifying the failure reason. - `Message string` Human-readable explanation of the failure. May include registry-specific details. ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) workflowStatus, err := client.Registrar.Registrations.Edit( context.TODO(), "example.com", registrar.RegistrationEditParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", workflowStatus.Completed) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": { "completed": false, "created_at": "2019-12-27T18:11:19.117Z", "links": { "self": "/accounts/{account_id}/registrar/registrations/example.com/registration-status", "resource": "/accounts/{account_id}/registrar/registrations/example.com" }, "state": "in_progress", "updated_at": "2019-12-27T18:11:19.117Z", "context": { "foo": "bar" }, "error": { "code": "registry_rejected", "message": "Registry rejected the request." } }, "success": true } ``` # Registration Status ## Get Registration Status `client.Registrar.RegistrationStatus.Get(ctx, domainName, query) (*WorkflowStatus, error)` **get** `/accounts/{account_id}/registrar/registrations/{domain_name}/registration-status` Returns the current status of a domain registration workflow. Use this endpoint to poll for completion when the POST response returned `202 Accepted`. The URL is provided in the `links.self` field of the workflow status response. Poll this endpoint until the workflow reaches a terminal state or a state that requires user attention. **Terminal states:** `succeeded` and `failed` are terminal and always have `completed: true`. **Non-terminal states:** - `action_required` has `completed: false` and will not resolve on its own. The workflow is paused pending user intervention. - `blocked` has `completed: false` and indicates the workflow is waiting on a third party such as the extension registry or losing registrar. Continue polling while informing the user of the delay. Use increasing backoff between polls. When `state: blocked`, use a longer polling interval and do not poll indefinitely. A naive polling loop that only checks `completed` can run indefinitely when `state: action_required`. Break explicitly on `action_required`: ```js let status; do { await new Promise(r => setTimeout(r, 2000)); status = await cloudflare.request({ method: 'GET', path: reg.result.links.self, }); } while ( !status.result.completed && status.result.state !== 'action_required' ); if (status.result.state === 'action_required') { // Surface context.action and context.confirmation_sent_to to the user. // Do not re-submit the registration request. } ``` ### Parameters - `domainName 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. - `query RegistrationStatusGetParams` - `AccountID param.Field[string]` Identifier ### Returns - `type WorkflowStatus struct{…}` Status of an async registration workflow. - `Completed bool` Whether the workflow has reached a terminal state. `true` when `state` is `succeeded` or `failed`. `false` for `pending`, `in_progress`, `action_required`, and `blocked`. - `CreatedAt Time` - `Links WorkflowStatusLinks` - `Self string` URL to this status resource. - `Resource string` URL to the domain resource. - `State WorkflowStatusState` 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. - `const WorkflowStatusStatePending WorkflowStatusState = "pending"` - `const WorkflowStatusStateInProgress WorkflowStatusState = "in_progress"` - `const WorkflowStatusStateActionRequired WorkflowStatusState = "action_required"` - `const WorkflowStatusStateBlocked WorkflowStatusState = "blocked"` - `const WorkflowStatusStateSucceeded WorkflowStatusState = "succeeded"` - `const WorkflowStatusStateFailed WorkflowStatusState = "failed"` - `UpdatedAt Time` - `Context map[string, unknown]` Workflow-specific data for this workflow. The workflow subject is identified by `context.domain_name` for domain-centric workflows. - `Error WorkflowStatusError` 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. - `Code string` Machine-readable error code identifying the failure reason. - `Message string` Human-readable explanation of the failure. May include registry-specific details. ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) workflowStatus, err := client.Registrar.RegistrationStatus.Get( context.TODO(), "example.com", registrar.RegistrationStatusGetParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", workflowStatus.Completed) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": { "completed": false, "created_at": "2019-12-27T18:11:19.117Z", "links": { "self": "/accounts/{account_id}/registrar/registrations/example.com/registration-status", "resource": "/accounts/{account_id}/registrar/registrations/example.com" }, "state": "in_progress", "updated_at": "2019-12-27T18:11:19.117Z", "context": { "foo": "bar" }, "error": { "code": "registry_rejected", "message": "Registry rejected the request." } }, "success": true } ``` # Update Status ## Get Update Status `client.Registrar.UpdateStatus.Get(ctx, domainName, query) (*WorkflowStatus, error)` **get** `/accounts/{account_id}/registrar/registrations/{domain_name}/update-status` Returns the current status of a domain update workflow. Use this endpoint to poll for completion when the PATCH response returned `202 Accepted`. The URL is provided in the `links.self` field of the workflow status response. Poll this endpoint until the workflow reaches a terminal state or a state that requires user attention. Use increasing backoff between polls. When the workflow remains blocked on a third party, use a longer polling interval and do not poll indefinitely. ### Parameters - `domainName 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. - `query UpdateStatusGetParams` - `AccountID param.Field[string]` Identifier ### Returns - `type WorkflowStatus struct{…}` Status of an async registration workflow. - `Completed bool` Whether the workflow has reached a terminal state. `true` when `state` is `succeeded` or `failed`. `false` for `pending`, `in_progress`, `action_required`, and `blocked`. - `CreatedAt Time` - `Links WorkflowStatusLinks` - `Self string` URL to this status resource. - `Resource string` URL to the domain resource. - `State WorkflowStatusState` 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. - `const WorkflowStatusStatePending WorkflowStatusState = "pending"` - `const WorkflowStatusStateInProgress WorkflowStatusState = "in_progress"` - `const WorkflowStatusStateActionRequired WorkflowStatusState = "action_required"` - `const WorkflowStatusStateBlocked WorkflowStatusState = "blocked"` - `const WorkflowStatusStateSucceeded WorkflowStatusState = "succeeded"` - `const WorkflowStatusStateFailed WorkflowStatusState = "failed"` - `UpdatedAt Time` - `Context map[string, unknown]` Workflow-specific data for this workflow. The workflow subject is identified by `context.domain_name` for domain-centric workflows. - `Error WorkflowStatusError` 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. - `Code string` Machine-readable error code identifying the failure reason. - `Message string` Human-readable explanation of the failure. May include registry-specific details. ### Example ```go package main import ( "context" "fmt" "github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go/option" "github.com/cloudflare/cloudflare-go/registrar" ) func main() { client := cloudflare.NewClient( option.WithAPIToken("Sn3lZJTBX6kkg7OdcBUAxOO963GEIyGQqnFTOFYY"), ) workflowStatus, err := client.Registrar.UpdateStatus.Get( context.TODO(), "example.com", registrar.UpdateStatusGetParams{ AccountID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }, ) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", workflowStatus.Completed) } ``` #### Response ```json { "errors": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "messages": [ { "code": 1000, "message": "message", "documentation_url": "documentation_url", "source": { "pointer": "pointer" } } ], "result": { "completed": false, "created_at": "2019-12-27T18:11:19.117Z", "links": { "self": "/accounts/{account_id}/registrar/registrations/example.com/registration-status", "resource": "/accounts/{account_id}/registrar/registrations/example.com" }, "state": "in_progress", "updated_at": "2019-12-27T18:11:19.117Z", "context": { "foo": "bar" }, "error": { "code": "registry_rejected", "message": "Registry rejected the request." } }, "success": true } ```