DNS Widget

Add provider-aware DNS setup guidance to your application with Approximated's embeddable widget.

Read this page as Markdown

We've created an optional DNS widget that's embeddable into your app, to help your users update their DNS records when connecting a custom domain.

The DNS widget detects the DNS provider and offers an automatic setup option where a supported provider integration is available. Provider-specific manual instructions are also available. Automation depends on the provider and requested record configuration.

DNS Widget Demo

Try the widget with Classic, Dark, and Minimal styles in the full-page demo.

DNS Widget Basics

  • Embedded v2 uses two plain JavaScript files: the headless client and the widget renderer.
  • Use the supplied CSS or override it to match your app.
  • The widget renders directly in your page, with no iframe required.
  • Start the widget by calling window.apxDns.init(config) after its container exists.
  • The config object contains some settings and an array of the DNS records you'd like to apply to custom domains.
  • You can optionally add a domain to the config to skip the domain entry UI step when the custom domain is already known.
  • The widget calls Approximated API endpoints to detect domain DNS records, generate instructions/automation steps, and to verify changes.
  • Embedded v2 renders instructions in the browser from the headless API’s JSON response.
    Prefer to render everything yourself? Use headless mode to display that JSON in your own components.

DNS Widget Setup

We've tried to make the DNS widget easily compatible with as many different stacks and approaches as possible. The setup below uses embedded v2 with a scoped customer token, powered by the headless API.

  1. Load the headless client, then the embedded v2 renderer:
    <script src="https://cloud.approximated.app/dnswidget/headless.v2.js"></script>
    <script src="https://cloud.approximated.app/dnswidget/dnswidget.v2.js"></script>
  2. Link the CSS file from Approximated:
    <link rel="stylesheet" href="https://cloud.approximated.app/dnswidget/dnswidget.v2.css">
    Note: you can take a look at this file and override styles and variables as needed with your own CSS as well.
  3. Add a container where the widget should render:
    <div id="apxdnswidget" class="apxdnswidget"></div>

    Then call the widget init function after the container exists. Replace the documentation address 192.0.2.10 with your cluster IPv4 address. The example configures the apex A record and a CNAME at www; {domain} is replaced with the domain entered by the customer.

    // Create the config data for the widget.
    const apx_dns_widget_config = {
        // Generate a scoped token on your server with GET /api/dns/v2/token.
        token: "use_token_api_endpoint_server_side_to_generate_this", 
        api_url: "https://cloud.approximated.app/api/dns/v2",
        /* 
        * The dnsRecords field is an array of record objects 
        * that you'd like to have applied to custom domains. 
        * 
        * These will likely be A records pointing at your cluster IP address,
        * or CNAME records pointing at an intermediary domain you control.
        * The dnsRecords always consist of:
        *      - [string]  type (Uppercase DNS record type like A, CNAME, or TXT)
        *      - [string]  host (Use @ for the apex domain or a subdomain with no trailing dot)
        *      - [string]  value (the address, value, text, etc. for that record type)
        *      - [integer] ttl (how many seconds the record should be cached in DNS servers)
        * We currently allow setting A, CNAME, and TXT records with the DNS widget.
        */
        dnsRecords: [
            {
                type: "A",
                host: "@",
                value: "192.0.2.10",
                ttl: 3600,
            },
            {
                type: "CNAME",
                host: "www",
                value: "{domain}",
                ttl: 3600,
            }
        ],
        // domain: "example.com", // optional, skips the domain entry UI step
        // prefillDomain: "example.com", // optional, prefills the domain without skipping
        verifyAutoScroll: true // optional, auto-scroll to verification results. Default: true
    };
        
    // Call the DNS widget init function to launch the widget.
    // In this example we call it after the DOM content is loaded.
    document.addEventListener("DOMContentLoaded", function(event) {
        // The DNS widget functions/data are automatically namespaced
        // and available from window.apxDns.
        window.apxDns.init(apx_dns_widget_config);
    });
    
  4. Optionally, set javascript listeners to call some of your own logic based on widget events.
    // When the user submits a domain in the UI
    document.addEventListener('apx-dnswidget-user-submitted-domain', function(event) {
        // Your code to handle the event.
        // The event.detail string contains the custom domain/subdomain
        // submitted by the user into the UI.
    });
    
    // When the widget flow is restarted
    document.addEventListener('apx-dnswidget-restarted', function(event) {
        // Your code to handle the event.
    });
    
    // When all of the records are completely verified as updated successfully
    document.addEventListener('apx-dnswidget-records-completely-verified', function(event) {
        // Your code to handle the event.
        // The event.detail will contain the record results as a list of objects
    });
    
    // When none of the records match the desired updates, during verification
    document.addEventListener('apx-dnswidget-records-failed-verification', function(event) {
        // Your code to handle the event.
        // The event.detail will contain the record results as a list of objects
    });
    
    // When only some of the records are verified as updated successfully
    document.addEventListener('apx-dnswidget-records-partially-verified', function(event) {
        // Your code to handle the event.
        // The event.detail will contain the record results as a list of objects
        console.log(event.detail);
    
        // the output of the console.log above could look like this:
        [
            {
                actual_values: [
                    "192.0.2.10"
                ],
                apex: "example",
                combined_host: "@",
                domain: "example.com",
                full: "example.com",
                host: "@",
                match: true, // Approximated found an exact match DNS record
                match_against: "192.0.2.10", // The value to match against the DNS record
                non_tld: "example",
                subdomain: null,
                tld: "com",
                type: "A"
            },
            {
                actual_values: false,
                apex: "example",
                combined_host: "www",
                domain: "example.com",
                full: "example.com",
                host: "www",
                match: false, // Approximated could not find a matching DNS record
                match_against: "example.com", // The value to match against the DNS record
                non_tld: "example",
                subdomain: null,
                tld: "com",
                type: "CNAME"
            }
        ]
    });
    
  5. You can optionally stop and clear the widget element or restart the flow.
    // Stop and clear the element used for the widget.
    // The init function will need to be called again to restart.
    window.apxDns.stop()
    
    // Alternatively, you can restart without stopping by calling this function:
    window.apxDns.restart()
    

DNS Widget Styling

The widget comes with neutral styling that you can override with your own CSS. Its outermost element fills the available width up to 600px, with no fixed height, padding, or border, so you can fit it into your app. Explore the Classic, Dark, and Minimal styles to see how CSS can change its appearance.

Every CSS class in the element is prefixed with apxdns-, and the outermost element always has a class of apxdnswidget. The intention for this is to avoid any class name conflicts with your existing CSS code.

The widget also makes use of CSS variables scoped to the class apxdnswidget to enable easier theming. The available variables and their default values are as follows:

.apxdnswidget {
    --text-color: #333;
    --light-text-color: #666;
    --link-text-color: rgb(46, 90, 173);
    --main-bg-color: transparent;
    --shaded-bg-color: #FAFAFA;
    --shaded-border: 1px solid #EEE;
    --button-bg-color: #fb5168;
    --button-hover-bg-color: #da3551;
    --button-text-color: #FFF;
    --radius: 5px;
    --widget-max-width: 600px;
    --border-color: #EEE;
}

Scoped DNS Widget Tokens

A scoped token is a temporary pass that lets the browser use the DNS widget without seeing your private API key. Create it on your server, then pass the returned token to the embedded widget or headless client. Each token is tied to the API key and proxy cluster that created it.

Call the URL below from an authenticated endpoint in your application. Check that the signed-in user is allowed to configure the domain, and send your cluster API key in the api-key header. Keep that key on your server.

GET
https://cloud.approximated.app/api/dns/v2/token
Returns
200 - Success
{
    "token": "a-valid-token"
}
401 - The API key used does not exist
429 - Too many requests; wait before trying again
No fields/data required.

Each token lasts up to 10 minutes and 30 seconds. While the page is open, the client attempts renewal every five minutes. Renewals keep the same session going for at most 24 hours from its first token; they cannot extend that deadline. After expiry, restart the setup flow with a fresh token from your authenticated backend.

Deleting or replacing the API key that created a token stops that token and its renewals from working. Use a current key to start a new session. Token creation and renewal return Cache-Control: no-store; return that header from your own token endpoint too.

Use DNS Widget v2 throughout: /api/dns/v2/token creates the token, and instructions, DNS checks, and renewal use /api/dns/v2/. Load headless.v2.js for browser requests. The v2 browser API requires scoped tokens.

Widget tokens allow DNS instructions and checks. They do not prove domain ownership or give the browser permission to change your application’s accounts or domain settings.

Request limits

The following limits apply per minute. A request must fit every applicable limit:

  • Create tokens: 60 per IP address and 60 per proxy cluster.
  • Renew tokens: 120 per IP address, 120 per cluster, and 12 per session.
  • Get instructions: 120 per IP address, 120 per cluster, and 60 per session.
  • Verify records: 240 per IP address, 240 per cluster, and 120 per session. Exact-match and existence checks share these limits.

Keys for the same cluster share its limit. Renewing a token does not reset its session’s count. Limits are enforced separately on each Approximated application server. Token creation also counts toward the general API limit of 240 requests per minute per key.

Widget limits return HTTP 429 with JSON error rate_limited and Retry-After: 60. Wait 60 seconds before retrying. The general API-key limit can instead return a plain-text 429 response.

Public demos use separate demo tokens: sessions last up to 30 minutes, requests allow one or two records, and instructions use manual setup without saving provider lookups. Use your own scoped customer token for your application, including supported automatic setup.

Headless Mode

Build DNS setup into your own interface. Send us the customer’s domain and the records you need; we return their DNS provider, the values to enter, and step-by-step instructions as JSON. You decide how to display them.

Use headless mode when you want to use your own components, layout, or wording. If you’d prefer a complete interface you can drop into a page, start with the embeddable widget.

Explore the JSON demo to see the setup instructions alongside their API response.

1. Request the setup instructions

For a browser integration, use our small JavaScript client. It has no dependencies, leaves the page’s HTML and styles to you, and renews the widget token while the customer works.

First, create an authenticated endpoint in your app that calls GET /api/dns/v2/token with your cluster API key. Have it return { "token": "…" } with Cache-Control: no-store. The examples call your endpoint /api/dns-widget-token; you need to implement it. Keep the API key on your server.

<script src="https://cloud.approximated.app/dnswidget/headless.v2.js"></script>
<script type="module">
  const tokenResponse = await fetch("/api/dns-widget-token", {
    credentials: "same-origin",
    cache: "no-store"
  });
  if (!tokenResponse.ok) throw new Error("Could not start DNS setup");
  const { token } = await tokenResponse.json();
  if (typeof token !== "string" || !token) {
    throw new Error("Your token endpoint returned an invalid token");
  }

  const client = window.apxDnsHeadless.createClient({ token });
  const result = await client.instructions({
    domain: "shop.customer.com",
    records: [
      { type: "CNAME", host: "@", value: "domains.example.com", ttl: 3600 }
    ]
  });
  console.log(result.domains);
</script>

This asks the customer to point shop.customer.com at domains.example.com. Replace both with the domain being connected and your application’s target hostname. Here, @ means the supplied domain itself, including its shop subdomain.

The snippet above logs the instructions. In your application, render them as described below and show a retry message if a request fails. If you prefer to call the API from your backend, skip to the API reference.

Start with React or Vue

Preview the Simple, Dashboard, and Guided designs in your browser, then adapt the v2 starter for your app. You can switch designs without losing your progress. Each public starter includes provider instructions with copy buttons, verification results, retries, and a server endpoint that creates scoped tokens.

Use GitHub’s “Use this template” button or clone the starter for your framework. Open the starter folder and, with Node.js 22.12 or newer installed, run:

npm ci
cp .env.example .env

In .env, set APX_API_KEY to your server API key and VITE_CNAME_TARGET to the hostname customers should point to.

Both starters use headless.v2.js and the /api/dns/v2 API. Their server creates scoped customer tokens automatically. Start the interface:

npm run dev

Open http://127.0.0.1:5173. The API key stays on the Node server; the browser receives a short-lived token. The session code stops renewal when setup ends and ignores responses for a previous domain.

The included server runs locally only. When integrating with your application, move the token endpoint into your authenticated backend and check the customer's permission to configure the domain. Each repository’s README explains the files, configuration, and production integration.

2. Display the provider and record steps

The response groups records by their root domain. For example, records for shop.customer.com and www.customer.com appear together under apex_domain: "customer.com". Each group has a provider object and a records array.

  1. Show provider.message above the records. Add provider.login_url as a link when it’s available.
  2. For each record, use record.title as a heading and render record.steps in order.
  3. Choose how to display each step using its kind, as shown below.
Step kinds
text
Plain instruction
Display text as a sentence, such as “Click the Save button to save changes”.
link
Instruction with a link
Display text as a link to url. This usually opens the provider’s DNS settings.
field
Value the customer enters
Show text, the provider’s field label, and a copyable value. The field key tells you whether it is the host, value, or TTL.
{
  "kind": "field",
  "field": "host",
  "label": "Name",
  "value": "shop",
  "text": "Set Name to:"
}

For this step, your UI could show Name: shop. Use the step’s value for display: it already accounts for the provider’s conventions. An empty string means “leave this field blank”, and a TTL may be written as “1 Hour”. Render returned text as text, using your framework’s escaping or textContent.

If record.automation is present, you can also offer its url as an automatic setup link. Keep the manual steps available. A detected provider does not necessarily support automation; show the link only when it is returned.

If the provider can’t be identified, the API still returns general instructions. Use provider.lookup_status to distinguish a successful lookup from missing nameservers or a failed lookup, and give the customer a way to correct the domain or retry.

View the full example response

A 200 response for the CNAME request above, with Cloudflare detected and no automatic setup link available.

{
  "domains": [
    {
      "apex_domain": "customer.com",
      "provider": {
        "name": "Cloudflare",
        "provider_domain": "cloudflare.com",
        "detected": true,
        "supported": true,
        "lookup_status": "ok",
        "nameservers": [
          "ada.ns.cloudflare.com",
          "rob.ns.cloudflare.com"
        ],
        "message": "We've detected Cloudflare as your DNS provider.",
        "message_link": null,
        "login_url": "https://dash.cloudflare.com/",
        "logo_url": null
      },
      "records": [
        {
          "domain": "shop.customer.com",
          "apex_domain": "customer.com",
          "subdomain": "shop",
          "type": "CNAME",
          "host": "@",
          "combined_host": "shop",
          "value": "domains.example.com",
          "match_against": "domains.example.com",
          "ttl": 3600,
          "title": "Add a DNS CNAME record for shop.customer.com",
          "automation": null,
          "steps": [
            {
              "kind": "link",
              "text": "Sign in to Cloudflare.",
              "url": "https://dash.cloudflare.com/"
            },
            {
              "kind": "text",
              "text": "Select the account for customer.com, then open that domain."
            },
            {
              "kind": "text",
              "text": "In \"DNS management for customer.com\", click Add Record."
            },
            {
              "kind": "text",
              "text": "Select CNAME as the record type."
            },
            {
              "kind": "field",
              "field": "host",
              "label": "Name",
              "value": "shop",
              "text": "Set Name to:"
            },
            {
              "kind": "field",
              "field": "value",
              "label": "Target",
              "value": "domains.example.com",
              "text": "Set Target to:"
            },
            {
              "kind": "field",
              "field": "ttl",
              "label": "TTL",
              "value": "3600",
              "text": "Set TTL to:"
            },
            {
              "kind": "text",
              "text": "Click Save to add the record."
            }
          ]
        }
      ]
    }
  ]
}

3. Check the customer’s changes

Once the customer has saved their DNS changes, let them run a check. Pass the original instructions result to client.verify(); the client sends the correct record fields for you. Run this when the customer clicks your check button, using the same client and result from step 1.

try {
  const check = await client.verify(result);
  const state = client.summarize(check.records);
  console.log(state);         // "complete", "partial", or "failed"
  console.log(check.records); // Each record includes match and actual_values
} catch (error) {
  console.error(error.code, error.message);
  // Show a retry message in your UI.
}
Verification results
complete
Every record matches
The DNS changes are visible to the lookup. Continue with your application’s routing and HTTPS checks.
partial
Some records match
Show which records still need attention so the customer can check those values.
failed
No records match
Show the values found in DNS and let the customer retry. A “failed” summary means no records matched; a failed API request throws an error instead.

The client checks for an exact match: each queried name must have exactly one value for the requested record type, and it must equal match_against. To allow other values alongside the expected one, such as multiple TXT records, use the check-records-exist API instead.

Each checked record includes match and actual_values. The latter is an array of values when DNS returns records, or false when no values are found. DNS updates can take time to become visible because of caching. A successful check confirms the DNS result; your backend should check the domain’s association with the customer, routing, and HTTPS before marking the domain connected.

Verify without the JavaScript client

From the browser, POST to https://cloud.approximated.app/api/dns/v2/token/check-records-match-exactly with Content-Type: application/json. Copy domain, host, type, and match_against from each returned record:

{
  "token": "YOUR_WIDGET_TOKEN",
  "records": [
    {
      "domain": "shop.customer.com",
      "host": "@",
      "type": "CNAME",
      "match_against": "domains.example.com"
    }
  ]
}

From your backend, use POST /api/dns/v2/check-records-match-exactly with your api-key header. That endpoint takes the full address instead of domain and host:

{
  "records": [
    {
      "address": "shop.customer.com",
      "type": "cname",
      "match_against": "domains.example.com"
    }
  ]
}

The address is domain when host is @, or host + "." + domain otherwise. Both check-records-exist endpoints also use address; the token variant additionally needs token in the body.

Manage the client’s lifecycle

Keep the client alive while the customer follows the instructions. It attempts renewal every five minutes; each token lasts up to 10 minutes and 30 seconds, within the session’s 24-hour deadline. Call client.stop() when the setup component is removed or the flow is finished. Handle renewal errors with onError. After expiry or key replacement, stop the old client and create a new one with a fresh token from your authenticated backend.

Client methods and options
instructions(request)
Returns a promise
Fetches the provider details and setup steps. Takes the same domain and records as the API below.
verify(result)
Returns a promise
Checks all records from an instructions result. Also accepts an array of records with domain, host, type, and match_against (or value).
summarize(records)
Returns a string
Returns complete, partial, or failed from the checked records. An empty array returns failed.
stop()
Cleanup
Stops token renewal. Call it when your setup component unmounts.
renewToken() / getToken()
Token access
renewToken() requests a renewal and returns a promise. getToken() returns the current token.
createClient(options)
Configuration
Pass token. Optional api_url defaults to https://cloud.approximated.app/api/dns/v2. Use onTokenRenewed(token) and onError(error) to handle background renewal results. Request errors still need a try/catch.

Instructions API reference

Both endpoints return the same JSON. Send Content-Type: application/json and Accept: application/json. Choose authentication based on where your code runs:

POST · From the browser
https://cloud.approximated.app/api/dns/v2/token/instructions

CORS-enabled. Include a short-lived widget token in the JSON body.

POST · From your server
https://cloud.approximated.app/api/dns/v2/instructions

Send your cluster API key in the api-key header. Omit token from the body.

{
  "token": "YOUR_WIDGET_TOKEN",
  "domain": "shop.customer.com",
  "records": [
    { "type": "CNAME", "host": "@", "value": "domains.example.com", "ttl": 3600 }
  ]
}
Request fields
token
String · Required in the browser
The short-lived token returned by the token endpoint. Only include it on the browser endpoint.
domain
String · Default for all records
The domain to connect, such as customer.com or shop.customer.com. Required unless every record supplies its own domain. Use a domain with a registrable name and a TLD, such as example.com.
records
Array · Required
Send 1 to 25 records. You can include records for more than one domain; the response groups them by root domain.
records[type]
String · Required
A, CNAME, or TXT. Letter case does not matter; the response uses uppercase.
records[host]
String · Required
Use @ for the record’s domain itself, or a relative name with no trailing dot. With domain: "shop.customer.com", @ targets shop.customer.com and www targets www.shop.customer.com.
records[value]
String · Required
The IPv4 address, target hostname, or text you want in DNS. Any {domain} placeholder is replaced with that record’s domain.
records[ttl]
Integer · Optional
Cache duration in seconds. Accepts a positive integer or numeric string; defaults to 3600 when omitted. Use the returned step value for provider-specific display.
records[domain]
String · Optional override
Set this when a record belongs to a different domain than the top-level default. An omitted or blank value uses the default.

Response field reference

A successful request returns 200 with a domains array. Groups appear in the order their root domains first appeared in your request; records within each group keep their original order. Each group contains apex_domain, provider, and records.

Provider fields

These fields are inside each group’s provider object, for example result.domains[0].provider.name. All ten keys are present; optional links and images can be null.

Provider
name / provider_domain
Strings
name is the display name, such as “Cloudflare”. provider_domain identifies the provider in your code, such as cloudflare.com. The fallback is Generic / generic.
detected / supported
Booleans
detected means the nameservers matched a known provider. supported means provider-specific instructions are available. Neither flag promises automatic setup.
lookup_status
String
ok: the lookup succeeded. nameservers_not_found: no nameservers were found; check the domain. lookup_failed: the lookup could not be completed; offer a retry.
nameservers
Array of strings
The nameservers used to detect the provider. Empty when none were found.
message
String
A sentence you can show above the instructions. General instructions ask the customer to go to their DNS provider.
message_link
Object or null
An optional link with text and url to show alongside the message, such as information about a provider migration.
login_url / logo_url
Strings or null
A link to the provider’s DNS settings and a hosted logo, when available. Each can be null.
Record fields

These fields are inside each item in a group’s records array, for example result.domains[0].records[0].steps.

Record
domain
String
The supplied domain, trimmed and lowercased, with any scheme, path, port, or trailing dot removed. International domains use punycode: bücher.de becomes xn--bcher-kva.de.
apex_domain / subdomain
String / String or null
apex_domain is the root domain, such as customer.com. subdomain is the part before it, such as shop, or null for the root itself.
type / host
Strings
type is A, CNAME, or TXT. host is the host you supplied, with surrounding whitespace removed.
combined_host
String
The host relative to the root domain. For shop.customer.com, @ becomes shop and www becomes www.shop. For the value to display in the provider’s form, use the host step’s value.
value / match_against
Strings
value contains the requested value with any {domain} placeholder replaced. match_against is identical and is ready to send to verification.
ttl
Integer
The TTL in seconds, or 3600 when omitted. The steps contain the provider’s display wording.
title
String
A heading you can use above the record’s instructions.
automation
Object or null
When available: { "kind": "domain_connect", "url": "…" }. Open the URL to let the customer approve automatic setup with their provider. Otherwise, this field is null.
steps
Array of objects
The ordered instructions for this record. Render them using the step kinds above, or use the record data to write your own instructions.
Step fields

These fields are inside each record’s steps array. The kind determines which keys are present.

Step
kind / text
Strings · Every step
kind is text, link, or field. text is the sentence to show.
url
String · Link steps
The destination for the instruction’s link.
field
String · Field steps
Which record value the step describes: host, value, or ttl.
label
String · Field steps
The input’s name in the provider’s interface, such as “Name” or “Target”.
value
String · Field steps
The value the customer should enter or select. Keep it as text, including values such as “1 Hour”. An empty string means leave the field blank.

DNS Widget v2 uses the /api/dns/v2/ API and headless.v2.js client. New response fields may be added within v2, so ignore fields you don’t need. Breaking changes will use a new API path and client version; existing versions will keep their contract.

Handle errors and expired sessions

The instructions endpoints return the following error statuses. The client exposes API failures as ApxDnsError objects with code, message, status, and details.

API errors
401
API key endpoint
The API key is invalid. Check the key your backend sends in the api-key header.
403
Token endpoint
missing_token means the token property is absent. A present but empty, malformed, expired, or revoked token returns token_expired; this also covers a token of the wrong type. Obtain a fresh token from your authenticated backend using a current API key and create a new client. Renewal cannot restore an expired or revoked token.
422
Either endpoint
invalid_request or invalid_domain. Check details for the record’s zero-based index, field, and message. Request-wide errors, such as too many records, can have an empty details array.
429
Widget or API key endpoint
Widget requests return JSON error rate_limited and Retry-After: 60; wait 60 seconds before retrying. The general API-key limit of 240 requests per minute can instead return plain text. See request limits for the separate IP, cluster, and session budgets.
{
  "error": "invalid_domain",
  "message": "One or more records are invalid; see details",
  "details": [
    { "index": 0, "field": "domain", "message": "must be a valid hostname such as example.com or app.example.com" }
  ]
}

The client also uses network_error when a fetch fails, and request_failed for an unsuccessful response without a JSON error code. Calling createClient() without a token throws missing_token immediately. Handle request failures with try/catch and use the onError callback for token renewal failures.

DNS Widget Versioning

Use v2 for token creation, the browser API, and JavaScript files:

IntegrationFilesAPI
Scoped customer tokensYour authenticated server endpointGET /api/dns/v2/token
Embedded v2headless.v2.js, dnswidget.v2.js, and dnswidget.v2.css/api/dns/v2/
Headless v2, including React and Vueheadless.v2.js/api/dns/v2/

Customer sessions accept at most 25 A, CNAME, or TXT records per instructions request, with a valid domain, a non-empty host and value, and a positive numeric TTL when provided. Use @ for the entered domain; omit TTL to use the default of 3600 seconds instead of passing Auto.

Embedded v2 verifies the normalized records returned by the API. Verification events contain those check results; use match_against for the expected value. Call stop() before removing the widget during client-side navigation.

Security fixes and compatible patches may update a pinned version. Breaking changes get new asset names or API paths; existing paths will not silently switch to a newer version.