Docs

Docs

Domains

Prove with one DNS TXT record that an account controls a domain, with the steps for each common DNS provider, the API calls, and how the proof is kept true.

A verified domain is the proof that an account controls a domain. It is made once, with one DNS TXT record, and used by everything that acts on that domain's names:

FeatureNeeds
Single sign-on for a teamthe e-mail domain verified for that team
Checks and load sent from our cloudevery target name inside a verified domain
An agent acting on a named hostthe host inside a verified domain the agent is bound to
An agent acting on an address with no namethe agent's own local policy; no domain can be proved for it

How it works

Add the domain. In the console's Domains section (Settings › Developer), or with POST /v1/accounts/orgs/{org_id}/domains. Choose the scope:

  • domain: the domain and every name under it (company.hr, api.company.hr, staging.company.hr).
  • subdomain: one name under a registered domain and what is under it (staging.company.hr, eu.staging.company.hr), for when the rest of the domain belongs to someone else.

Publish the record. The answer carries one TXT record. The token is 160 random bits in base32, made for this account and this domain:

_inorbit-verify.company.hr.  TXT  "inorbit-verify=<token>"

The name starts with an underscore, so it cannot clash with a website or a mail server. Add it where the domain's DNS is managed; the steps per provider are below.

Check. The accounts service looks the record up through public resolvers in different networks (Cloudflare, Google Public DNS and NextDNS) and validates DNSSEC where the zone is signed. A record seen by only one resolver does not count; two must agree. The console checks by itself every ten seconds while the page is open.

Confirm. Once the record is seen, confirm. The service checks once more and the domain is verified for this account.

An unconfirmed token works for seven days. After that, add the domain again for a new one.

Statuses

StatusMeans
pendingthe record is not seen yet
seentwo or more resolvers agree the record is there; confirm to verify
verifiedproved for this account and checked again every day
unverifiedthe record was missing three days in a row (unverified_reason: dns), or another account proved the domain (transferred)

A check answers per resolver (name, answered, seen, value, dnssec) and one overall status:

Check statusMeans
pendingno resolver sees a record at that name
wrong_valuea TXT record is there with another value; value shows what it is
partialone resolver sees the right value; DNS is still spreading
seentwo or more resolvers see the right value

Kept true

  • Checked every day. Keep the record in place for as long as the domain is used here. If it is gone three days in a row, the domain becomes unverified and everything that relies on it stops: checks and load from our cloud are refused, agents stop acting on its names, and single sign-on falls back to each person's own sign-in. A day on which the resolvers cannot be reached does not count.
  • One account at a time. When a second account proves the same domain, it moves there. The first account's domain becomes unverified with unverified_reason: transferred, and it receives domain.transferred. Both audit logs record the change.
  • Removing a domain stops it counting for the account at once. The TXT record may then be deleted.

Steps per DNS provider

The console names the provider it recognises from the domain's name servers and shows its steps. In every case the record is a TXT record at _inorbit-verify under the domain, with the value exactly as given. Most providers want only _inorbit-verify as the name and add the domain themselves.

Cloudflare

  1. In the Cloudflare dashboard, open the domain, then DNS › Records.
  2. Select Add record, type TXT.
  3. Name: _inorbit-verify. Content: the value.
  4. Keep TTL on Auto and save. It is published within a minute.

Amazon Route 53

  1. In the AWS console, open Route 53 › Hosted zones and select the domain's public zone.
  2. Select Create record.
  3. Record name: _inorbit-verify. Record type: TXT.
  4. Value: the value in double quotes, "inorbit-verify=…". Route 53 needs the quotes.
  5. Create records.

With the AWS CLI:

aws route53 change-resource-record-sets --hosted-zone-id "$ZONE_ID" --change-batch '{
  "Changes": [{"Action": "UPSERT", "ResourceRecordSet": {
    "Name": "_inorbit-verify.company.hr", "Type": "TXT", "TTL": 300,
    "ResourceRecords": [{"Value": "\"inorbit-verify=<token>\""}]}}]}'

Google Cloud DNS

  1. In the Google Cloud console, open Network services › Cloud DNS and select the zone.
  2. Select Add standard.
  3. DNS name: _inorbit-verify. Resource record type: TXT.
  4. TXT data: the value. Create.

With gcloud:

gcloud dns record-sets create _inorbit-verify.company.hr. --zone="$ZONE" \
  --type=TXT --ttl=300 --rrdatas='"inorbit-verify=<token>"'

Azure DNS

  1. In the Azure portal, open the domain's DNS zone.
  2. Select + Record set.
  3. Name: _inorbit-verify. Type: TXT. Value: the value.
  4. OK.

With the Azure CLI:

az network dns record-set txt add-record --resource-group "$GROUP" --zone-name company.hr \
  --record-set-name _inorbit-verify --value "inorbit-verify=<token>"

GoDaddy

  1. In Domain Portfolio, select the domain and open DNS.
  2. Select Add New Record, type TXT.
  3. Name: _inorbit-verify. Value: the value. TTL: the default.
  4. Save. GoDaddy can take up to an hour to publish it.

Namecheap

  1. In Domain List, select Manage beside the domain and open Advanced DNS.
  2. Under Host records, select Add new record, TXT Record.
  3. Host: _inorbit-verify. Value: the value. TTL: Automatic.
  4. Save with the tick. Namecheap publishes it within half an hour.

Any other provider

  1. Sign in where the domain's DNS is managed, often the registrar it was bought from.
  2. Open the domain's DNS records, zone or name server settings.
  3. Add a TXT record. As its name or host, enter _inorbit-verify (or the full _inorbit-verify.company.hr if the form asks for the full name).
  4. Paste the value with no quotes added around it, unless the form says TXT values need them, and keep the default TTL.

To see what the public sees, ask a resolver yourself:

dig +short TXT _inorbit-verify.company.hr @one.one.one.one

Over the API

Reading takes domains:read; adding, checking, confirming and removing take domains:write. In a team, a signed-in member reads and the owner and admins change. org_id is the account's id: org in GET /v1/me.

API=https://api.inorbit.hr/v1/accounts/orgs/$ORG_ID/domains

# Add: the answer carries record_name and record_value.
curl -s -X POST "$API" -H "authorization: Bearer $INORBIT_TOKEN" \
  -H 'content-type: application/json' -d '{"domain":"company.hr","scope":"domain"}'

# After publishing the record: what each resolver sees.
curl -s -X POST "$API/company.hr/check" -H "authorization: Bearer $INORBIT_TOKEN" -d '{}'

# Once the status is "seen": verify.
curl -s -X POST "$API/company.hr/confirm" -H "authorization: Bearer $INORBIT_TOKEN" -d '{}'

# List, read one, remove.
curl -s "$API" -H "authorization: Bearer $INORBIT_TOKEN"
curl -s "$API/company.hr" -H "authorization: Bearer $INORBIT_TOKEN"
curl -s -X DELETE "$API/company.hr" -H "authorization: Bearer $INORBIT_TOKEN"

The Reference has every field. The command line will follow the same steps as iohr domains add|verify|list|rm, printing the record to add and, with --wait, checking until it is seen; it is not released yet.

Events

TypeWhendata
domain.verifieda domain is confirmed for the accountdomain_id, actor
domain.unverifieda verified domain stops counting for the accountdomain_id, reason (dns, removed)
domain.transferredanother account proved a domain this one helddomain_id

Every change is also in the account's audit log as domain.*. Events carry ids, never the domain's name; read it with GET /v1/accounts/orgs/{org_id}/domains.