Skip to content

Domains ​

Domains and contacts as InfraNest knows them. Registrar actions (register, renew, transfer) stay in the app.

Common tasks

Only in the app: Registering, renewing and transferring domains, nameservers and registrar settings.

How it works in the app: help article.

Scopes: Read with domains.read, change with domains.write. See Tokens and scopes.

Every endpoint below takes a token in the Authorization: Bearer header and answers JSON. Errors use the shared format in Errors. Base address: https://api.infranest.io/api.

Contacts ​

List contacts ​

Your organization’s contacts, paginated with page and per_page (up to 200), with their tags. Filter with search or tag, and sort with sort (name, company, email, city, country) and dir.

GET/organizations/{organization}/contacts
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Request

sh
curl "https://api.infranest.io/api/organizations/42/contacts" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/contacts" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/contacts', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/contacts', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/contacts", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "current_page": 1,
  "data": [
    {
      "id": 1,
      "organization_id": 1,
      "first_name": "Alex",
      "last_name": "Rivera",
      "company": "Northwind Cloud",
      "email": "domains@northwind.example",
      "phone": "+31 20 555 0123",
      "address": "Keizersgracht",
      "city": "Amsterdam",
      "state": null,
      "zip": "1015 CJ",
      "country": "NL",
      "deleted_at": null,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "house_number": "123",
      "vat_number": null,
      "company_number": null,
      "missing_for_registration": [],
      "tags": []
    },
    {
      "id": 3,
      "organization_id": 1,
      "first_name": "Priya",
      "last_name": "Nair",
      "company": "Northwind Cloud",
      "email": "legal@northwind.example",
      "phone": "+44 20 7946 0321",
      "address": "Shoreditch High Street",
      "city": "London",
      "state": "Greater London",
      "zip": "E1 6JJ",
      "country": "GB",
      "deleted_at": null,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "house_number": "42",
      "vat_number": null,
      "company_number": null,
      "missing_for_registration": [],
      "tags": []
    }
  ],
  "first_page_url": "http://localhost/api/organizations/1/contacts?page=1",
  "from": 1,
  "last_page": 1,
  "last_page_url": "http://localhost/api/organizations/1/contacts?page=1",
  "links": [
    {
      "url": null,
      "label": "&laquo; Previous",
      "page": null,
      "active": false
    },
    {
      "url": "http://localhost/api/organizations/1/contacts?page=1",
      "label": "1",
      "page": 1,
      "active": true
    }
  ],
  "next_page_url": null,
  "path": "http://localhost/api/organizations/1/contacts",
  "per_page": 25,
  "prev_page_url": null,
  "to": 4,
  "total": 4,
  "meta": {
    "tags": []
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Create a contact ​

Creates a contact you can assign to domains as registrant, admin, tech or billing contact, optionally tagged with tag_ids.

POST/organizations/{organization}/contacts
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Bodyapplication/json
first_namestringrequired

Must not be greater than 100 characters.

last_namestringrequired

Must not be greater than 100 characters.

companystring, nullableoptional

Must not be greater than 255 characters.

vat_numberstring, nullableoptional

Must not be greater than 50 characters.

company_numberstring, nullableoptional

Must not be greater than 50 characters.

emailstringrequired

Must be a valid email address. Must not be greater than 255 characters.

phonestring, nullableoptional

Must not be greater than 50 characters.

addressstring, nullableoptional

Must not be greater than 255 characters.

house_numberstring, nullableoptional

Must not be greater than 20 characters.

citystring, nullableoptional

Must not be greater than 100 characters.

statestring, nullableoptional

Must not be greater than 100 characters.

zipstring, nullableoptional

Must not be greater than 20 characters.

countrystringrequired

Must be 2 characters.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/contacts" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"first_name":"Ada","last_name":"Brandt","email":"ada@northwind.example","country":"DE"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "first_name": "Ada",
  "last_name": "Brandt",
  "email": "ada@northwind.example",
  "country": "DE"
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/contacts" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/contacts', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'first_name' => 'Ada',
        'last_name' => 'Brandt',
        'email' => 'ada@northwind.example',
        'country' => 'DE',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "first_name": "Ada",
        "last_name": "Brandt",
        "email": "ada@northwind.example",
        "country": "DE",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/contacts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "first_name": "Ada",
    "last_name": "Brandt",
    "email": "ada@northwind.example",
    "country": "DE"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/contacts", strings.NewReader(`{"first_name":"Ada","last_name":"Brandt","email":"ada@northwind.example","country":"DE"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "first_name": "Ada",
  "last_name": "Brandt",
  "email": "ada@northwind.example",
  "country": "DE",
  "organization_id": 1,
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "created_at": "2026-01-15T12:00:00.000000Z",
  "id": 5,
  "missing_for_registration": [
    "address",
    "city"
  ],
  "tags": []
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The first name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "first_name": [
      "The first name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Get a contact ​

One contact with the domains it is assigned to.

GET/organizations/{organization}/contacts/{id}
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

idintegerrequired

The id's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/contacts/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/contacts/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/contacts/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/contacts/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/contacts/1', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/contacts/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "first_name": "Alex",
  "last_name": "Rivera",
  "company": "Northwind Cloud",
  "email": "domains@northwind.example",
  "phone": "+31 20 555 0123",
  "address": "Keizersgracht",
  "city": "Amsterdam",
  "state": null,
  "zip": "1015 CJ",
  "country": "NL",
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "house_number": "123",
  "vat_number": null,
  "company_number": null,
  "missing_for_registration": [],
  "domains": []
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Update a contact ​

Updates the contact and, when tag_ids is sent, its tags. Recorded in InfraNest only; nothing is sent to a registrar.

PUT/organizations/{organization}/contacts/{id}
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

idintegerrequired

The id's ID.

Bodyapplication/json
first_namestringoptional

Must not be greater than 100 characters.

last_namestringoptional

Must not be greater than 100 characters.

companystring, nullableoptional

Must not be greater than 255 characters.

vat_numberstring, nullableoptional

Must not be greater than 50 characters.

company_numberstring, nullableoptional

Must not be greater than 50 characters.

emailstringoptional

Must be a valid email address. Must not be greater than 255 characters.

phonestring, nullableoptional

Must not be greater than 50 characters.

addressstring, nullableoptional

Must not be greater than 255 characters.

house_numberstring, nullableoptional

Must not be greater than 20 characters.

citystring, nullableoptional

Must not be greater than 100 characters.

statestring, nullableoptional

Must not be greater than 100 characters.

zipstring, nullableoptional

Must not be greater than 20 characters.

countrystringoptional

Must be 2 characters.

Request

sh
curl -X PUT "https://api.infranest.io/api/organizations/42/contacts/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"company":"Northwind Cloud GmbH","city":"Köln"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "company": "Northwind Cloud GmbH",
  "city": "Köln"
}
'@
Invoke-RestMethod -Method Put -Uri "https://api.infranest.io/api/organizations/42/contacts/1" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('PUT', 'https://api.infranest.io/api/organizations/42/contacts/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'company' => 'Northwind Cloud GmbH',
        'city' => 'Köln',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.put(
    "https://api.infranest.io/api/organizations/42/contacts/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "company": "Northwind Cloud GmbH",
        "city": "Köln",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/contacts/1', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "company": "Northwind Cloud GmbH",
    "city": "Köln"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PUT", "https://api.infranest.io/api/organizations/42/contacts/1", strings.NewReader(`{"company":"Northwind Cloud GmbH","city":"Köln"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "first_name": "Alex",
  "last_name": "Rivera",
  "company": "Northwind Cloud GmbH",
  "email": "domains@northwind.example",
  "phone": "+31 20 555 0123",
  "address": "Keizersgracht",
  "city": "Köln",
  "state": null,
  "zip": "1015 CJ",
  "country": "NL",
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "house_number": "123",
  "vat_number": null,
  "company_number": null,
  "missing_for_registration": [],
  "tags": []
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The first name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "first_name": [
      "The first name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
422 validation_failed
429 rate_limited


Delete a contact ​

Deletes the contact from your organization.

DELETE/organizations/{organization}/contacts/{id}
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

idintegerrequired

The id's ID.

Request

sh
curl -X DELETE "https://api.infranest.io/api/organizations/42/contacts/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Delete -Uri "https://api.infranest.io/api/organizations/42/contacts/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.infranest.io/api/organizations/42/contacts/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.delete(
    "https://api.infranest.io/api/organizations/42/contacts/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.status_code)
js
const response = await fetch('https://api.infranest.io/api/organizations/42/contacts/1', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.infranest.io/api/organizations/42/contacts/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

text
No content.
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
429 rate_limited

Domain findings ​

List domain findings ​

Advisor findings across all your domains, most urgent first, with one finding per cause naming every domain it affects.

GET/organizations/{organization}/domain-findings
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domain-findings" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domain-findings" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domain-findings', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domain-findings",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domain-findings', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domain-findings", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "data": [
    {
      "key": "expiry",
      "check": "expiry",
      "status": "error",
      "variant": "lapsed",
      "params": {
        "days": -6,
        "expires_at": "2026-01-09"
      },
      "action": "renew",
      "cause": "domain:18:expiry",
      "rank": 390,
      "home": {
        "source": "domain_expiring",
        "key": "domain:18",
        "fingerprint": "2026-01-09"
      },
      "snoozed": false,
      "domains": [
        {
          "id": 18,
          "name": "nwcloud.app"
        }
      ]
    },
    {
      "key": "dnssec",
      "check": "dnssec",
      "status": "error",
      "variant": "notValidating",
      "params": {
        "since": "2026-01-13T12:00:00.000000Z"
      },
      "action": null,
      "cause": "domain:9:dnssec",
      "rank": 350,
      "home": {
        "source": "dnssec_broken",
        "key": "dnssec_broken:9",
        "fingerprint": ""
      },
      "snoozed": false,
      "domains": [
        {
          "id": 9,
          "name": "northwind.de"
        }
      ]
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited

Domains ​

List domains ​

Your domains, paginated with page and per_page (up to 200), each with its tags, advisor issue count and who hosts its website and mail. Filter with search, credential, tag, active, expiring_soon, autorenew_off, website, mail or archived (archived domains are left out unless asked for). Registration orders that failed are not domains you hold and are left out too; pass include_failed=1 to list them, and meta.counts.failed says how many there are. Sort with sort (domain, registrar, expires) and dir.

GET/organizations/{organization}/domains
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "current_page": 1,
  "data": [
    {
      "id": 11,
      "organization_id": 1,
      "name": "northwind",
      "tld": "cloud",
      "registrar": "Porkbun",
      "registered_at": "2024-01-14T00:00:00.000000Z",
      "expires_at": "2026-11-12T00:00:00.000000Z",
      "auto_renew": true,
      "status": "active",
      "notes": null,
      "deleted_at": null,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "provider_credential_id": null,
      "nameservers": [
        "hydrogen.ns.hetzner.com",
        "oxygen.ns.hetzner.com"
      ],
      "transfer_lock": true,
      "whois_privacy": true,
      "registrar_contacts": null,
      "dnssec_entries": null,
      "has_dnssec": null,
      "renewal_price": "22.00",
      "renewal_price_currency": "EUR",
      "pricing_cached_at": null,
      "last_details_synced_at": null,
      "status_message": null,
      "expected_issuers": null,
      "renewal_price_source": "manual",
      "purchase_price": null,
      "purchase_price_currency": null,
      "registrar_price": null,
      "registrar_price_currency": null,
      "registrar_flags": null,
      "requested_whois_privacy": null,
      "requested_auto_renew": null,
      "archived_at": null,
      "requested_nameservers": null,
      "missing_since": null,
      "serves_website": null,
      "billing_interval": "yearly",
      "interval_count": 1,
      "dnssec_state": null,
      "dnssec_checked_at": null,
      "dnssec_broken_since": null,
      "requested_dns_credential_id": null,
      "requested_dns_template": null,
      "status_detail": null,
      "ordered_by_user_id": null,
      "ns_health": null,
      "ns_health_checked_at": null,
      "unused_since": null,
      "registry_statuses": null,
      "registry_checked_at": null,
      "registry_dnssec": null,
      "custom_fields": {
        "1": "Marketing"
      },
      "advisor_issues": 0,
      "uses": {
        "website": {
          "kind": "server",
          "label": "web-01",
          "url": "/servers/1",
          "flagged": false,
          "since": null,
          "provider": "Hetzner",
          "note": null,
          "ours": false
        },
        "site": {
          "key": "host:hetzner",
          "label": "Hetzner"
        },
        "mail": {
          "key": "none",
          "label": null
        },
        "no_zone": null
      },
      "full_name": "northwind.cloud",
      "archivable": true,
      "dns_host": "hetzner",
      "management": "tracked",
      "sync_halt": null,
      "provider_credential": null,
      "tags": [
        {
          "id": 4,
          "name": "Internal",
          "color": "#8b5cf6",
          "pivot": {
            "taggable_type": "App\\Models\\Domain",
            "taggable_id": 11,
            "tag_id": 4
          }
        }
      ]
    },
    {
      "id": 1,
      "organization_id": 1,
      "name": "northwind",
      "tld": "com",
      "registrar": "Namecheap",
      "registered_at": "2023-12-28T00:00:00.000000Z",
      "expires_at": "2026-02-02T00:00:00.000000Z",
      "auto_renew": true,
      "status": "active",
      "notes": null,
      "deleted_at": null,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "provider_credential_id": null,
      "nameservers": [
        "nina.ns.cloudflare.com",
        "rick.ns.cloudflare.com"
      ],
      "transfer_lock": true,
      "whois_privacy": true,
      "registrar_contacts": null,
      "dnssec_entries": [
        {
          "key_tag": 62949,
          "algorithm": 13,
          "digest_type": 2,
          "digest": "FBF66B8D019C1EEC1E1A0B5A9D3C2E7F4A8B60D5C93E71F2A6B8D04C7E19A35B"
        }
      ],
      "has_dnssec": true,
      "renewal_price": "12.50",
      "renewal_price_currency": "EUR",
      "pricing_cached_at": null,
      "last_details_synced_at": null,
      "status_message": null,
      "expected_issuers": null,
      "renewal_price_source": "manual",
      "purchase_price": null,
      "purchase_price_currency": null,
      "registrar_price": null,
      "registrar_price_currency": null,
      "registrar_flags": null,
      "requested_whois_privacy": null,
      "requested_auto_renew": null,
      "archived_at": null,
      "requested_nameservers": null,
      "missing_since": null,
      "serves_website": null,
      "billing_interval": "yearly",
      "interval_count": 1,
      "dnssec_state": "signed",
      "dnssec_checked_at": "2026-01-15T11:25:00.000000Z",
      "dnssec_broken_since": null,
      "requested_dns_credential_id": null,
      "requested_dns_template": null,
      "status_detail": null,
      "ordered_by_user_id": null,
      "ns_health": null,
      "ns_health_checked_at": null,
      "unused_since": null,
      "registry_statuses": null,
      "registry_checked_at": null,
      "registry_dnssec": null,
      "custom_fields": {
        "1": "Marketing"
      },
      "advisor_issues": 0,
      "uses": {
        "website": {
          "kind": "server",
          "label": "web-01",
          "url": "/servers/1",
          "flagged": false,
          "since": null,
          "provider": "Hetzner",
          "note": {
            "key": "proxied",
            "params": {
              "provider": "Cloudflare"
            }
          },
          "ours": false
        },
        "site": {
          "key": "host:hetzner",
          "label": "Hetzner"
        },
        "mail": {
          "key": "other",
          "label": "mx.northwind.com"
        },
        "no_zone": null
      },
      "full_name": "northwind.com",
      "archivable": true,
      "dns_host": "cloudflare",
      "management": "tracked",
      "sync_halt": null,
      "provider_credential": null,
      "tags": [
        {
          "id": 3,
          "name": "Customer-facing",
          "color": "#3b82f6",
          "pivot": {
            "taggable_type": "App\\Models\\Domain",
            "taggable_id": 1,
            "tag_id": 3
          }
        },
        {
          "id": 5,
          "name": "Northwind Retail",
          "color": "#0ea5e9",
          "pivot": {
            "taggable_type": "App\\Models\\Domain",
            "taggable_id": 1,
            "tag_id": 5
          }
        }
      ]
    }
  ],
  "first_page_url": "http://localhost/api/organizations/1/domains?page=1",
  "from": 1,
  "last_page": 1,
  "last_page_url": "http://localhost/api/organizations/1/domains?page=1",
  "links": [
    {
      "url": null,
      "label": "&laquo; Previous",
      "page": null,
      "active": false
    },
    {
      "url": "http://localhost/api/organizations/1/domains?page=1",
      "label": "1",
      "page": 1,
      "active": true
    }
  ],
  "next_page_url": null,
  "path": "http://localhost/api/organizations/1/domains",
  "per_page": 25,
  "prev_page_url": null,
  "to": 20,
  "total": 20,
  "meta": {
    "locked_ids": [],
    "expiry_window_days": 60,
    "counts": {
      "total": 20,
      "active": 19,
      "expiring_soon": 3,
      "autorenew_off": 5,
      "failed": 0,
      "archived": 0
    },
    "integrations": [],
    "tags": [
      {
        "id": 3,
        "name": "Customer-facing",
        "color": "#3b82f6"
      },
      {
        "id": 4,
        "name": "Internal",
        "color": "#8b5cf6"
      }
    ],
    "uses": {
      "sites": [
        {
          "key": "host:hetzner",
          "label": "Hetzner",
          "count": 12
        },
        {
          "key": "none",
          "label": null,
          "count": 1
        }
      ],
      "mail": [
        {
          "key": "other",
          "label": null,
          "count": 7
        },
        {
          "key": "none",
          "label": null,
          "count": 6
        }
      ]
    },
    "custom_fields": [
      {
        "id": 1,
        "key": "cost_centre",
        "label": "Cost centre",
        "type": "select",
        "options": [
          "Platform",
          "Marketing"
        ]
      }
    ]
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List a domain’s running registrar actions ​

The action currently running at the registrar for this domain, where the registrar reports one; can_retry says whether it can be retried. An empty list when no registrar is linked or the registrar does not offer this.

GET/organizations/{organization}/domains/{domain}/actions
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/actions" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/actions" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/actions', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/actions",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/actions', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/actions", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "actions": []
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get a domain’s advisor findings ​

The current advisor findings for one domain, taking into account what its registrar supports.

GET/organizations/{organization}/domains/{domain}/advisor
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/advisor" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/advisor" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/advisor', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/advisor",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/advisor', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/advisor", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "expiry_window_days": 60,
  "findings": [
    {
      "key": "expiry",
      "check": "expiry",
      "status": "info",
      "variant": "renewalUnknown",
      "params": {
        "days": 18,
        "expires_at": "2026-02-02",
        "where": {
          "label": "Namecheap",
          "url": "https://ap.www.namecheap.com/domains/list/"
        }
      },
      "action": null,
      "cause": "domain:1:expiry",
      "rank": 222,
      "home": {
        "source": "domain_finding",
        "key": "domain_finding:domain:1:expiry",
        "fingerprint": ""
      },
      "snoozed": false
    },
    {
      "key": "auto_renew",
      "check": "auto_renew",
      "status": "info",
      "variant": "unknown",
      "params": {
        "where": {
          "label": "Namecheap",
          "url": "https://ap.www.namecheap.com/domains/list/"
        }
      },
      "action": null,
      "cause": "portfolio:auto_renew",
      "rank": 150,
      "home": {
        "source": "domain_finding",
        "key": "domain_finding:portfolio:auto_renew",
        "fingerprint": ""
      },
      "snoozed": false
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Archive a domain ​

Takes the domain out of your working list while keeping it, its costs and its links; it keeps syncing and stops counting toward your plan’s domain limit. Refused with 422 while the domain is still active at a connected registrar.

POST/organizations/{organization}/domains/{domain}/archive
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/domains/1/archive" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/domains/1/archive" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/domains/1/archive', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/domains/1/archive",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/archive', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/domains/1/archive", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "name": "northwind",
  "tld": "com",
  "registrar": "Namecheap",
  "registered_at": "2023-12-28T00:00:00.000000Z",
  "expires_at": "2026-02-02T00:00:00.000000Z",
  "auto_renew": true,
  "status": "active",
  "notes": null,
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "provider_credential_id": null,
  "nameservers": [
    "nina.ns.cloudflare.com",
    "rick.ns.cloudflare.com"
  ],
  "transfer_lock": true,
  "whois_privacy": true,
  "registrar_contacts": null,
  "dnssec_entries": [
    {
      "key_tag": 62949,
      "algorithm": 13,
      "digest_type": 2,
      "digest": "FBF66B8D019C1EEC1E1A0B5A9D3C2E7F4A8B60D5C93E71F2A6B8D04C7E19A35B"
    }
  ],
  "has_dnssec": true,
  "renewal_price": "12.50",
  "renewal_price_currency": "EUR",
  "pricing_cached_at": null,
  "last_details_synced_at": null,
  "status_message": null,
  "expected_issuers": null,
  "renewal_price_source": "manual",
  "purchase_price": null,
  "purchase_price_currency": null,
  "registrar_price": null,
  "registrar_price_currency": null,
  "registrar_flags": null,
  "requested_whois_privacy": null,
  "requested_auto_renew": null,
  "archived_at": "2026-01-15T12:00:00.000000Z",
  "requested_nameservers": null,
  "missing_since": null,
  "serves_website": null,
  "billing_interval": "yearly",
  "interval_count": 1,
  "dnssec_state": "signed",
  "dnssec_checked_at": "2026-01-15T11:25:00.000000Z",
  "dnssec_broken_since": null,
  "requested_dns_credential_id": null,
  "requested_dns_template": null,
  "status_detail": null,
  "ordered_by_user_id": null,
  "ns_health": null,
  "ns_health_checked_at": null,
  "unused_since": null,
  "registry_statuses": null,
  "registry_checked_at": null,
  "registry_dnssec": null,
  "full_name": "northwind.com",
  "archivable": true,
  "dns_host": "cloudflare",
  "management": "tracked",
  "sync_halt": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "name": [
      "The name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Get a domain’s registrar capabilities ​

Which registrar operations are available for this domain, given what its registrar and extension support, with a reason when something is unavailable.

GET/organizations/{organization}/domains/{domain}/capabilities
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/capabilities" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/capabilities" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/capabilities', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/capabilities",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/capabilities', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/capabilities", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "capabilities": {
    "nameservers": false,
    "contacts": false,
    "dnssec": false,
    "transfer_lock": false,
    "whois_privacy": false,
    "auto_renew": false,
    "auto_renew_reenable": false,
    "complete_domain_list": false,
    "epp_code": false,
    "register": false,
    "transfer": false,
    "renew": false
  },
  "reason": "no_registrar_credential",
  "registry_withheld": [],
  "contact_roles": [
    "registrant",
    "admin"
  ],
  "dnssec_fields": [
    "key_tag",
    "flags"
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List a domain’s contacts ​

The contacts assigned to the domain, each with its role in pivot.type.

GET/organizations/{organization}/domains/{domain}/contacts
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/contacts" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/contacts" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/contacts', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/contacts', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/contacts", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
[]
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Assign a contact to a domain ​

Assigns one of your contacts (contact_id) to the domain as registrant, admin, tech or billing, replacing whoever held that role. Recorded in InfraNest only; nothing is sent to the registrar.

POST/organizations/{organization}/domains/{domain}/contacts
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Bodyapplication/json
contact_idintegerrequired
typestringrequired

One of: registrant, admin, tech, billing

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/domains/1/contacts" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"contact_id":1,"type":"admin"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "contact_id": 1,
  "type": "admin"
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/domains/1/contacts" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/domains/1/contacts', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'contact_id' => 1,
        'type' => 'admin',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/domains/1/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "contact_id": 1,
        "type": "admin",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/contacts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "contact_id": 1,
    "type": "admin"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/domains/1/contacts", strings.NewReader(`{"contact_id":1,"type":"admin"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "first_name": "Alex",
  "last_name": "Rivera",
  "company": "Northwind Cloud",
  "email": "domains@northwind.example",
  "phone": "+31 20 555 0123",
  "address": "Keizersgracht",
  "city": "Amsterdam",
  "state": null,
  "zip": "1015 CJ",
  "country": "NL",
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "house_number": "123",
  "vat_number": null,
  "company_number": null,
  "missing_for_registration": [],
  "pivot": {
    "type": "admin"
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The contact id field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "contact_id": [
      "The contact id field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Remove a contact from a domain ​

Unassigns the contact from the domain in every role it held. The contact itself is kept.

DELETE/organizations/{organization}/domains/{domain}/contacts/{contact}
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

contactintegerrequired

The contact's ID.

Request

sh
curl -X DELETE "https://api.infranest.io/api/organizations/42/domains/1/contacts/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Delete -Uri "https://api.infranest.io/api/organizations/42/domains/1/contacts/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.infranest.io/api/organizations/42/domains/1/contacts/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.delete(
    "https://api.infranest.io/api/organizations/42/domains/1/contacts/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.status_code)
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/contacts/1', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.infranest.io/api/organizations/42/domains/1/contacts/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

text
No content.
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
429 rate_limited


Get a domain’s transfer code ​

Fetches the domain’s EPP (auth) code live from its registrar; InfraNest never stores it. Needs write access; answers 404 when no registrar is linked or the registrar cannot provide the code.

GET/organizations/{organization}/domains/{domain}/epp-code
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/epp-code" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/epp-code" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/epp-code', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/epp-code",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/epp-code', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/epp-code", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited

No success response is recorded for this endpoint yet.


Get a domain’s audit history ​

The 50 most recent audit-log entries for the domain and its manual cost items, newest first.

GET/organizations/{organization}/domains/{domain}/history
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/history" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/history" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/history', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/history",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/history', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/history", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
[]
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Check a domain’s nameservers ​

Checks each of the domain’s nameservers now: whether it answers on port 53 and is authoritative, whether the nameservers agree with each other, and whether DNSSEC validates. Empty when the domain has no nameservers; the result is kept for the advisor.

GET/organizations/{organization}/domains/{domain}/ns-health
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/ns-health" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/ns-health" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/ns-health', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/ns-health",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/ns-health', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/ns-health", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "checks": [
    {
      "ns": "nina.ns.cloudflare.com",
      "authoritative": true,
      "reachable": true
    },
    {
      "ns": "rick.ns.cloudflare.com",
      "authoritative": true,
      "reachable": true
    }
  ],
  "ns_consistency": {
    "consistent": true,
    "resolvers": {
      "cloudflare": [
        "nina.ns.cloudflare.com",
        "rick.ns.cloudflare.com"
      ],
      "google": [
        "nina.ns.cloudflare.com",
        "rick.ns.cloudflare.com"
      ],
      "dnssb": [
        "nina.ns.cloudflare.com",
        "rick.ns.cloudflare.com"
      ],
      "adguard": [
        "nina.ns.cloudflare.com",
        "rick.ns.cloudflare.com"
      ],
      "nextdns": [
        "nina.ns.cloudflare.com",
        "rick.ns.cloudflare.com"
      ]
    }
  },
  "dnssec_validates": true,
  "zone_delegation": {
    "zone_id": 1,
    "zone_name": "northwind.com",
    "provider": "cloudflare",
    "delegated": true,
    "delegated_to": null
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get a domain’s registrar pricing ​

The registrar’s current prices for the domain’s extension, asked live. Answers 404 when no registrar connection is linked; pricing is null when the registrar does not allow price lookups with your key.

GET/organizations/{organization}/domains/{domain}/pricing
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/pricing" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/pricing" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/pricing', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/pricing",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/pricing', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/pricing", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited

No success response is recorded for this endpoint yet.


Get a domain’s registry record ​

What the registry itself says about the domain: its status codes, created and updated dates, the source (RDAP or WHOIS) and an excerpt of the raw answer.

GET/organizations/{organization}/domains/{domain}/registry-record
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/registry-record" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/registry-record" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/registry-record', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/registry-record",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/registry-record', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/registry-record", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "statuses": [],
  "created_at": null,
  "updated_at": null,
  "source": null,
  "raw": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get how a domain is set up ​

Who hosts the domain’s DNS and whether its nameservers answer, its mail provider, and the servers, certificates, monitors and status pages behind its addresses. Based on the DNS zone InfraNest holds; a domain whose DNS is hosted elsewhere gets no website or email details.

GET/organizations/{organization}/domains/{domain}/setup
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/setup" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/setup" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/setup', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/setup",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/setup', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/setup", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "zone": {
    "id": 1,
    "name": "northwind.com"
  },
  "registrar": {
    "label": "Namecheap",
    "managed": false,
    "credential_id": null,
    "provider": null
  },
  "dns": {
    "provider": "cloudflare",
    "provider_label": "Cloudflare",
    "connected": true,
    "zone_here": true,
    "nameservers": [
      "nina.ns.cloudflare.com",
      "rick.ns.cloudflare.com"
    ],
    "answering": null,
    "checked_at": null
  },
  "email": {
    "provider": null,
    "hosts": [
      "mx.northwind.com"
    ]
  },
  "website": {
    "records": [
      {
        "type": "A",
        "value": "198.51.100.10",
        "url": "/dns/1?record=1"
      }
    ],
    "server": {
      "type": "server",
      "id": 1,
      "label": "web-01",
      "sublabel": "198.51.100.10",
      "url": "/servers/1",
      "meta": []
    }
  },
  "runs_on": [
    {
      "record_id": 1,
      "zone_id": 1,
      "host": "northwind.com",
      "type": "A",
      "value": "198.51.100.10",
      "url": "/dns/1?record=1",
      "server": {
        "type": "server",
        "id": 1,
        "label": "web-01",
        "sublabel": "198.51.100.10",
        "url": "/servers/1",
        "meta": []
      },
      "certificate": {
        "type": "certificate",
        "id": 1,
        "label": "northwind.com",
        "sublabel": "2026-03-30",
        "url": "/certificates/1",
        "meta": []
      },
      "monitors": [
        {
          "type": "monitor",
          "id": 1,
          "label": "Marketing site",
          "sublabel": "https://northwind.com",
          "url": "/monitoring/1",
          "meta": {
            "type": "http",
            "last_status": "up",
            "last_checked_at": "2026-01-15T11:58:00.000000Z"
          }
        },
        {
          "type": "monitor",
          "id": 4,
          "label": "Checkout flow",
          "sublabel": "https://northwind.com/checkout",
          "url": "/monitoring/4",
          "meta": {
            "type": "http",
            "last_status": "down",
            "last_checked_at": "2026-01-15T11:58:00.000000Z"
          }
        }
      ],
      "status_pages": []
    },
    {
      "record_id": 3,
      "zone_id": 1,
      "host": "api.northwind.com",
      "type": "CNAME",
      "value": "northwind.com",
      "url": "/dns/1?record=3",
      "server": null,
      "certificate": {
        "type": "certificate",
        "id": 3,
        "label": "api.northwind.com",
        "sublabel": "2026-04-13",
        "url": "/certificates/3",
        "meta": []
      },
      "monitors": [
        {
          "type": "monitor",
          "id": 3,
          "label": "API health",
          "sublabel": "https://api.northwind.com/health",
          "url": "/monitoring/3",
          "meta": {
            "type": "http",
            "last_status": "up",
            "last_checked_at": "2026-01-15T11:58:00.000000Z"
          }
        },
        {
          "type": "monitor",
          "id": 6,
          "label": "Search API",
          "sublabel": "https://api.northwind.com/v1/search",
          "url": "/monitoring/6",
          "meta": {
            "type": "api",
            "last_status": "degraded",
            "last_checked_at": "2026-01-15T11:58:00.000000Z"
          }
        }
      ],
      "status_pages": []
    }
  ],
  "mail": [
    {
      "record_id": 4,
      "value": "mx.northwind.com",
      "url": "/dns/1?record=4"
    }
  ],
  "unmonitored": [
    "archive.northwind.com",
    "cdn.northwind.com"
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Unarchive a domain ​

Brings an archived domain back into your working list, where it counts toward your plan’s domain limit again. A domain that is not archived is returned unchanged.

POST/organizations/{organization}/domains/{domain}/unarchive
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/domains/1/unarchive" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/domains/1/unarchive" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/domains/1/unarchive', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/domains/1/unarchive",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/unarchive', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/domains/1/unarchive", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "name": "northwind",
  "tld": "com",
  "registrar": "Namecheap",
  "registered_at": "2023-12-28T00:00:00.000000Z",
  "expires_at": "2026-02-02T00:00:00.000000Z",
  "auto_renew": true,
  "status": "active",
  "notes": null,
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "provider_credential_id": null,
  "nameservers": [
    "nina.ns.cloudflare.com",
    "rick.ns.cloudflare.com"
  ],
  "transfer_lock": true,
  "whois_privacy": true,
  "registrar_contacts": null,
  "dnssec_entries": [
    {
      "key_tag": 62949,
      "algorithm": 13,
      "digest_type": 2,
      "digest": "FBF66B8D019C1EEC1E1A0B5A9D3C2E7F4A8B60D5C93E71F2A6B8D04C7E19A35B"
    }
  ],
  "has_dnssec": true,
  "renewal_price": "12.50",
  "renewal_price_currency": "EUR",
  "pricing_cached_at": null,
  "last_details_synced_at": null,
  "status_message": null,
  "expected_issuers": null,
  "renewal_price_source": "manual",
  "purchase_price": null,
  "purchase_price_currency": null,
  "registrar_price": null,
  "registrar_price_currency": null,
  "registrar_flags": null,
  "requested_whois_privacy": null,
  "requested_auto_renew": null,
  "archived_at": null,
  "requested_nameservers": null,
  "missing_since": null,
  "serves_website": null,
  "billing_interval": "yearly",
  "interval_count": 1,
  "dnssec_state": "signed",
  "dnssec_checked_at": "2026-01-15T11:25:00.000000Z",
  "dnssec_broken_since": null,
  "requested_dns_credential_id": null,
  "requested_dns_template": null,
  "status_detail": null,
  "ordered_by_user_id": null,
  "ns_health": null,
  "ns_health_checked_at": null,
  "unused_since": null,
  "registry_statuses": null,
  "registry_checked_at": null,
  "registry_dnssec": null,
  "full_name": "northwind.com",
  "archivable": true,
  "dns_host": "cloudflare",
  "management": "tracked",
  "sync_halt": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "name": [
      "The name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Look up a domain’s WHOIS ​

A live WHOIS lookup for the domain. Answers 422 with a message when the lookup fails.

GET/organizations/{organization}/domains/{domain}/whois
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

domainintegerrequired

The domain's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1/whois" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1/whois" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1/whois', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1/whois",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1/whois', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1/whois", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "server": "whois.verisign-grs.com",
  "output": "   Domain Name: NORTHWIND.COM\r\n   Registry Domain ID: 4516866_DOMAIN_COM-VRSN\r\n   Registrar WHOIS Server: whois.godaddy.…"
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get a domain ​

One domain with its full details. A domain over your plan’s domain limit is locked and cannot be opened; stale renewal pricing is refreshed in the background.

GET/organizations/{organization}/domains/{id}
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

idintegerrequired

The id's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "name": "northwind",
  "tld": "com",
  "registrar": "Namecheap",
  "registered_at": "2023-12-28T00:00:00.000000Z",
  "expires_at": "2026-02-02T00:00:00.000000Z",
  "auto_renew": true,
  "status": "active",
  "notes": null,
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "provider_credential_id": null,
  "nameservers": [
    "nina.ns.cloudflare.com",
    "rick.ns.cloudflare.com"
  ],
  "transfer_lock": true,
  "whois_privacy": true,
  "registrar_contacts": null,
  "dnssec_entries": [
    {
      "key_tag": 62949,
      "algorithm": 13,
      "digest_type": 2,
      "digest": "FBF66B8D019C1EEC1E1A0B5A9D3C2E7F4A8B60D5C93E71F2A6B8D04C7E19A35B"
    }
  ],
  "has_dnssec": true,
  "renewal_price": "12.50",
  "renewal_price_currency": "EUR",
  "pricing_cached_at": null,
  "last_details_synced_at": null,
  "status_message": null,
  "expected_issuers": null,
  "renewal_price_source": "manual",
  "purchase_price": null,
  "purchase_price_currency": null,
  "registrar_price": null,
  "registrar_price_currency": null,
  "registrar_flags": null,
  "requested_whois_privacy": null,
  "requested_auto_renew": null,
  "archived_at": null,
  "requested_nameservers": null,
  "missing_since": null,
  "serves_website": null,
  "billing_interval": "yearly",
  "interval_count": 1,
  "dnssec_state": "signed",
  "dnssec_checked_at": "2026-01-15T11:25:00.000000Z",
  "dnssec_broken_since": null,
  "requested_dns_credential_id": null,
  "requested_dns_template": null,
  "status_detail": null,
  "ordered_by_user_id": null,
  "ns_health": null,
  "ns_health_checked_at": null,
  "unused_since": null,
  "registry_statuses": null,
  "registry_checked_at": null,
  "registry_dnssec": null,
  "full_name": "northwind.com",
  "archivable": true,
  "dns_host": "cloudflare",
  "management": "tracked",
  "sync_halt": null,
  "contacts": [],
  "provider_credential": null,
  "tags": [
    {
      "id": 3,
      "name": "Customer-facing",
      "color": "#3b82f6",
      "pivot": {
        "taggable_type": "App\\Models\\Domain",
        "taggable_id": 1,
        "tag_id": 3
      }
    },
    {
      "id": 5,
      "name": "Northwind Retail",
      "color": "#0ea5e9",
      "pivot": {
        "taggable_type": "App\\Models\\Domain",
        "taggable_id": 1,
        "tag_id": 5
      }
    }
  ],
  "dns_zone": {
    "id": 1,
    "name": "northwind.com",
    "provider": "cloudflare",
    "provider_label": "Cloudflare",
    "points_here": true,
    "can_sign": true
  },
  "tracked": {
    "registrar": "Namecheap",
    "provider": {
      "key": "namecheap",
      "label": "Namecheap",
      "integrable": true
    },
    "connected": true,
    "checked_at": null
  },
  "capabilities": {
    "nameservers": false,
    "contacts": false,
    "dnssec": false,
    "transfer_lock": false,
    "whois_privacy": false,
    "auto_renew": false,
    "auto_renew_reenable": false,
    "complete_domain_list": false,
    "epp_code": false,
    "register": false,
    "transfer": false,
    "renew": false
  },
  "capabilities_reason": "no_registrar_credential",
  "registry_withheld": [],
  "contact_roles": [
    "registrant",
    "admin"
  ],
  "settings": {
    "transfer_lock": {
      "state": "on",
      "source": "registry",
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "auto_renew": {
      "state": "unknown",
      "source": null,
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "whois_privacy": {
      "state": "on",
      "source": "registrar",
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "dnssec": {
      "state": "unknown",
      "source": null,
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "caa": {
      "state": "off",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "spf": {
      "state": "on",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "dmarc": {
      "state": "on",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "email": {
      "state": "on",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "dkim": {
      "state": "off",
      "source": "zone",
      "route": "elsewhere",
      "where": null
    },
    "no_mail": {
      "state": "none",
      "source": null,
      "route": null,
      "where": null
    }
  },
  "advisor": {
    "expiry_window_days": 60,
    "findings": [
      {
        "key": "expiry",
        "check": "expiry",
        "status": "info",
        "variant": "renewalUnknown",
        "params": {
          "days": 18,
          "expires_at": "2026-02-02",
          "where": {
            "label": "Namecheap",
            "url": "https://ap.www.namecheap.com/domains/list/"
          }
        },
        "action": null,
        "cause": "domain:1:expiry",
        "rank": 222,
        "home": {
          "source": "domain_finding",
          "key": "domain_finding:domain:1:expiry",
          "fingerprint": ""
        },
        "snoozed": false
      },
      {
        "key": "auto_renew",
        "check": "auto_renew",
        "status": "info",
        "variant": "unknown",
        "params": {
          "where": {
            "label": "Namecheap",
            "url": "https://ap.www.namecheap.com/domains/list/"
          }
        },
        "action": null,
        "cause": "portfolio:auto_renew",
        "rank": 150,
        "home": {
          "source": "domain_finding",
          "key": "domain_finding:portfolio:auto_renew",
          "fingerprint": ""
        },
        "snoozed": false
      }
    ]
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Update a domain ​

Updates what InfraNest keeps for the domain: notes, serves_website, expected_issuers, nameservers, registrar_contacts, pricing and tag_ids. Registration data such as the expiry date and auto-renew is not accepted here; returns the domain’s full details.

PUT/organizations/{organization}/domains/{id}
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

idintegerrequired

The id's ID.

Bodyapplication/json
notesstring, nullableoptional

Must not be greater than 10000 characters.

tag_idsarrayoptional
serves_websiteboolean, nullableoptional
expected_issuersarrayoptional

Must not be greater than 100 characters.

nameserversarrayoptional

Must not be greater than 253 characters.

registrar_contactsobject, nullableoptional
renewal_pricenumber, nullableoptional

Must be at least 0. Must not be greater than 9999999.99.

renewal_price_currencystring, nullableoptional

Must be 3 characters.

billing_intervalstringoptional

One of: hourly, daily, weekly, monthly, quarterly, yearly

interval_countintegeroptional

Must be at least 1. Must not be greater than 120.

purchase_pricenumber, nullableoptional

Must be at least 0. Must not be greater than 9999999.99.

purchase_price_currencystring, nullableoptional

Must be 3 characters.

Request

sh
curl -X PUT "https://api.infranest.io/api/organizations/42/domains/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"notes":"Main brand domain. Renew three years ahead."}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "notes": "Main brand domain. Renew three years ahead."
}
'@
Invoke-RestMethod -Method Put -Uri "https://api.infranest.io/api/organizations/42/domains/1" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('PUT', 'https://api.infranest.io/api/organizations/42/domains/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'notes' => 'Main brand domain. Renew three years ahead.',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.put(
    "https://api.infranest.io/api/organizations/42/domains/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "notes": "Main brand domain. Renew three years ahead.",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/1', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "notes": "Main brand domain. Renew three years ahead."
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PUT", "https://api.infranest.io/api/organizations/42/domains/1", strings.NewReader(`{"notes":"Main brand domain. Renew three years ahead."}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "name": "northwind",
  "tld": "com",
  "registrar": "Namecheap",
  "registered_at": "2023-12-28T00:00:00.000000Z",
  "expires_at": "2026-02-02T00:00:00.000000Z",
  "auto_renew": true,
  "status": "active",
  "notes": "Main brand domain. Renew three years ahead.",
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "provider_credential_id": null,
  "nameservers": [
    "nina.ns.cloudflare.com",
    "rick.ns.cloudflare.com"
  ],
  "transfer_lock": true,
  "whois_privacy": true,
  "registrar_contacts": null,
  "dnssec_entries": [
    {
      "key_tag": 62949,
      "algorithm": 13,
      "digest_type": 2,
      "digest": "FBF66B8D019C1EEC1E1A0B5A9D3C2E7F4A8B60D5C93E71F2A6B8D04C7E19A35B"
    }
  ],
  "has_dnssec": true,
  "renewal_price": "12.50",
  "renewal_price_currency": "EUR",
  "pricing_cached_at": null,
  "last_details_synced_at": null,
  "status_message": null,
  "expected_issuers": null,
  "renewal_price_source": "manual",
  "purchase_price": null,
  "purchase_price_currency": null,
  "registrar_price": null,
  "registrar_price_currency": null,
  "registrar_flags": null,
  "requested_whois_privacy": null,
  "requested_auto_renew": null,
  "archived_at": null,
  "requested_nameservers": null,
  "missing_since": null,
  "serves_website": null,
  "billing_interval": "yearly",
  "interval_count": 1,
  "dnssec_state": "signed",
  "dnssec_checked_at": "2026-01-15T11:25:00.000000Z",
  "dnssec_broken_since": null,
  "requested_dns_credential_id": null,
  "requested_dns_template": null,
  "status_detail": null,
  "ordered_by_user_id": null,
  "ns_health": null,
  "ns_health_checked_at": null,
  "unused_since": null,
  "registry_statuses": null,
  "registry_checked_at": null,
  "registry_dnssec": null,
  "full_name": "northwind.com",
  "archivable": true,
  "dns_host": "cloudflare",
  "management": "tracked",
  "sync_halt": null,
  "contacts": [
    {
      "id": 1,
      "organization_id": 1,
      "first_name": "Alex",
      "last_name": "Rivera",
      "company": "Northwind Cloud",
      "email": "domains@northwind.example",
      "phone": "+31 20 555 0123",
      "address": "Keizersgracht",
      "city": "Amsterdam",
      "state": null,
      "zip": "1015 CJ",
      "country": "NL",
      "deleted_at": null,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "house_number": "123",
      "vat_number": null,
      "company_number": null,
      "missing_for_registration": [],
      "pivot": {
        "domain_id": 1,
        "contact_id": 1,
        "type": "tech",
        "created_at": "2026-01-15T12:00:00.000000Z",
        "updated_at": "2026-01-15T12:00:00.000000Z"
      }
    }
  ],
  "provider_credential": null,
  "tags": [
    {
      "id": 3,
      "name": "Customer-facing",
      "color": "#3b82f6",
      "pivot": {
        "taggable_type": "App\\Models\\Domain",
        "taggable_id": 1,
        "tag_id": 3
      }
    },
    {
      "id": 5,
      "name": "Northwind Retail",
      "color": "#0ea5e9",
      "pivot": {
        "taggable_type": "App\\Models\\Domain",
        "taggable_id": 1,
        "tag_id": 5
      }
    }
  ],
  "dns_zone": {
    "id": 1,
    "name": "northwind.com",
    "provider": "cloudflare",
    "provider_label": "Cloudflare",
    "points_here": true,
    "can_sign": true
  },
  "tracked": {
    "registrar": "Namecheap",
    "provider": {
      "key": "namecheap",
      "label": "Namecheap",
      "integrable": true
    },
    "connected": true,
    "checked_at": null
  },
  "capabilities": {
    "nameservers": false,
    "contacts": false,
    "dnssec": false,
    "transfer_lock": false,
    "whois_privacy": false,
    "auto_renew": false,
    "auto_renew_reenable": false,
    "complete_domain_list": false,
    "epp_code": false,
    "register": false,
    "transfer": false,
    "renew": false
  },
  "capabilities_reason": "no_registrar_credential",
  "registry_withheld": [],
  "contact_roles": [
    "registrant",
    "admin"
  ],
  "settings": {
    "transfer_lock": {
      "state": "on",
      "source": "registry",
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "auto_renew": {
      "state": "unknown",
      "source": null,
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "whois_privacy": {
      "state": "on",
      "source": "registrar",
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "dnssec": {
      "state": "unknown",
      "source": null,
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      }
    },
    "caa": {
      "state": "off",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "spf": {
      "state": "on",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "dmarc": {
      "state": "on",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "email": {
      "state": "on",
      "source": "zone",
      "route": "here",
      "where": {
        "label": "Cloudflare",
        "url": null
      }
    },
    "dkim": {
      "state": "off",
      "source": "zone",
      "route": "elsewhere",
      "where": null
    },
    "no_mail": {
      "state": "none",
      "source": null,
      "route": null,
      "where": null
    }
  },
  "advisor": {
    "expiry_window_days": 60,
    "findings": [
      {
        "key": "expiry",
        "check": "expiry",
        "status": "info",
        "variant": "renewalUnknown",
        "params": {
          "days": 18,
          "expires_at": "2026-02-02",
          "where": {
            "label": "Namecheap",
            "url": "https://ap.www.namecheap.com/domains/list/"
          }
        },
        "action": null,
        "cause": "domain:1:expiry",
        "rank": 222,
        "home": {
          "source": "domain_finding",
          "key": "domain_finding:domain:1:expiry",
          "fingerprint": ""
        },
        "snoozed": false
      },
      {
        "key": "auto_renew",
        "check": "auto_renew",
        "status": "info",
        "variant": "unknown",
        "params": {
          "where": {
            "label": "Namecheap",
            "url": "https://ap.www.namecheap.com/domains/list/"
          }
        },
        "action": null,
        "cause": "portfolio:auto_renew",
        "rank": 150,
        "home": {
          "source": "domain_finding",
          "key": "domain_finding:portfolio:auto_renew",
          "fingerprint": ""
        },
        "snoozed": false
      }
    ]
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The notes field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "notes": [
      "The notes field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
422 validation_failed
429 rate_limited


Plan CAA protection across domains ​

For each domain in ids (up to 200), the CAA plan and its route, as for the email protection plan. Changes nothing; apply it through each zone’s CAA protection endpoint, which checks the zone’s certificates first.

GET/organizations/{organization}/domains/caa-protection-plan
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Query parameters
idsarrayoptional

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/caa-protection-plan" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/caa-protection-plan" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/caa-protection-plan', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/caa-protection-plan",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/caa-protection-plan', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/caa-protection-plan", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "domains": [
    {
      "id": 1,
      "name": "northwind.com",
      "zone_id": 1,
      "route": "here",
      "plan": {
        "zone_id": 1,
        "zone": "northwind.com",
        "route": "here",
        "where": {
          "label": "Cloudflare",
          "url": null
        },
        "records": [
          {
            "key": "kept:7",
            "action": "none",
            "type": "CAA",
            "name": "@",
            "value": "0 issue \"letsencrypt.org\"",
            "current": null,
            "record_id": null,
            "reason": "caa_kept",
            "params": []
          },
          {
            "key": "issue:globalsign.com",
            "action": "create",
            "type": "CAA",
            "name": "@",
            "value": "0 issue \"globalsign.com\"",
            "current": null,
            "record_id": null,
            "reason": "caa_cert",
            "params": {
              "subject": "shop.northwind.com"
            }
          }
        ],
        "refusals": [],
        "certificates": [
          {
            "id": 1,
            "subject": "northwind.com",
            "issuer": "Let's Encrypt (R3)",
            "ca": "letsencrypt.org",
            "wildcard": false,
            "state": "stays_renewable"
          },
          {
            "id": 13,
            "subject": "cdn.northwind.com",
            "issuer": "Let's Encrypt (R3)",
            "ca": "letsencrypt.org",
            "wildcard": false,
            "state": "stays_renewable"
          }
        ],
        "fronts": [
          {
            "label": "Cloudflare",
            "ids": [
              "letsencrypt.org",
              "pki.goog"
            ],
            "publishes_own": true
          }
        ]
      }
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Plan email protection across domains ​

For each domain in ids (up to 200), the email protection plan for mode (protect or no_mail) and its route: here, elsewhere (records to copy to your DNS host), reconnect, unchanged, refused or none (no zone held). Changes nothing; apply it through each zone’s email protection endpoint.

GET/organizations/{organization}/domains/email-protection-plan
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Query parameters
modestringrequired
idsarrayoptional

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/email-protection-plan?mode=%3Cmode%3E" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/email-protection-plan?mode=%3Cmode%3E" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/email-protection-plan?mode=%3Cmode%3E', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/email-protection-plan?mode=%3Cmode%3E",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/email-protection-plan?mode=%3Cmode%3E', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/email-protection-plan?mode=%3Cmode%3E", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "mode": "no_mail",
  "domains": [
    {
      "id": 1,
      "name": "northwind.com",
      "zone_id": 1,
      "route": "refused",
      "plan": {
        "zone_id": 1,
        "zone": "northwind.com",
        "mode": "no_mail",
        "route": "here",
        "where": {
          "label": "Cloudflare",
          "url": null
        },
        "provider": null,
        "providers": [],
        "records": [],
        "refusals": [
          {
            "key": "mode",
            "reason": "receives_mail",
            "params": []
          }
        ],
        "lookups": null,
        "dkim": null
      }
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get the domains overview ​

A summary of your domains: what needs your attention, what the next year of renewals costs in your base currency, and how the portfolio is protected.

GET/organizations/{organization}/domains/overview
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/overview" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/overview" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/overview', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/overview",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/overview', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/overview", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "summary": {
    "total": 20,
    "fine": 16,
    "need_you": 4,
    "this_week": 2,
    "registrars": 7,
    "renewal_cost": 327.5,
    "currency": "EUR",
    "auto_renewing": 0,
    "synced_at": null,
    "next_renewal": {
      "domain_id": 14,
      "name": "northwind-labs.com",
      "expires_at": "2026-01-24",
      "auto_renew": false
    }
  },
  "needs_you": [
    {
      "key": "expiry",
      "check": "expiry",
      "status": "error",
      "variant": "lapsed",
      "params": {
        "days": -6,
        "expires_at": "2026-01-09"
      },
      "action": "renew",
      "cause": "domain:18:expiry",
      "rank": 390,
      "home": {
        "source": "domain_expiring",
        "key": "domain:18",
        "fingerprint": "2026-01-09"
      },
      "snoozed": false,
      "domains": [
        {
          "id": 18,
          "name": "nwcloud.app"
        }
      ],
      "attention_keys": [
        "domain:18"
      ],
      "due_in_days": 0,
      "renewal": null,
      "evidence": [
        {
          "source": "registrar",
          "state": "auto_renew_off",
          "tone": "bad"
        }
      ],
      "prevention": {
        "template": "auto_renew_expiring_domains",
        "active": false
      }
    },
    {
      "key": "dnssec",
      "check": "dnssec",
      "status": "error",
      "variant": "notValidating",
      "params": {
        "since": "2026-01-13T12:00:00.000000Z"
      },
      "action": null,
      "cause": "domain:9:dnssec",
      "rank": 350,
      "home": {
        "source": "dnssec_broken",
        "key": "dnssec_broken:9",
        "fingerprint": ""
      },
      "snoozed": false,
      "domains": [
        {
          "id": 9,
          "name": "northwind.de"
        }
      ],
      "attention_keys": [
        "dnssec_broken:9"
      ],
      "due_in_days": 0,
      "renewal": null,
      "evidence": [],
      "prevention": null
    }
  ],
  "decided": [],
  "renewals": {
    "currency": "EUR",
    "priced": true,
    "total": 327.5,
    "items": 18,
    "unpriced": 0,
    "months": [
      {
        "month": "2026-01",
        "cost": 44.5,
        "items": 2,
        "unpriced": 0,
        "decide_cost": 44.5,
        "decide_items": 2,
        "domains": [
          {
            "id": 10,
            "name": "northwind.shop",
            "cost": 32,
            "decide": true
          },
          {
            "id": 14,
            "name": "northwind-labs.com",
            "cost": 12.5,
            "decide": true
          }
        ],
        "more": 0
      },
      {
        "month": "2026-02",
        "cost": 12.5,
        "items": 1,
        "unpriced": 0,
        "decide_cost": 12.5,
        "decide_items": 1,
        "domains": [
          {
            "id": 1,
            "name": "northwind.com",
            "cost": 12.5,
            "decide": true
          }
        ],
        "more": 0
      }
    ],
    "savings": {
      "unused": [],
      "total": 0
    }
  },
  "protection": [
    {
      "setting": "transfer_lock",
      "on": 14,
      "applicable": 16,
      "off": [
        14,
        18
      ],
      "applies": true,
      "here": [],
      "reconnect": [],
      "elsewhere": [
        {
          "label": "Namecheap",
          "url": "https://ap.www.namecheap.com/domains/list/",
          "ids": [
            14,
            18
          ]
        }
      ],
      "unknown": 0,
      "none": 3
    },
    {
      "setting": "auto_renew",
      "on": 0,
      "applicable": 5,
      "off": [
        4,
        10
      ],
      "applies": true,
      "here": [],
      "reconnect": [],
      "elsewhere": [
        {
          "label": "Cloudflare",
          "url": "https://dash.cloudflare.com/?to=/:account/domains",
          "ids": [
            4
          ]
        },
        {
          "label": "Porkbun",
          "url": "https://porkbun.com/account/domainsSpeedy",
          "ids": [
            10
          ]
        }
      ],
      "unknown": 14,
      "none": 0
    }
  ],
  "stale": [],
  "found_elsewhere": [],
  "cheaper_registrar": {
    "groups": [],
    "set_aside": []
  },
  "setup": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List registrar moves ​

The 200 most recent moves of domains to another registrar you have connected, newest first, each with its domain, source and target connection, and current state.

GET/organizations/{organization}/domains/registrar-moves
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/registrar-moves" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/registrar-moves" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/registrar-moves', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/registrar-moves",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/registrar-moves', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/registrar-moves", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "data": []
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get registration requirements for an extension ​

The extra fields a registrar needs to register a domain under tld (for example the nexus details some country extensions ask for) and the registration periods it offers. credential_id and tld are required; unknown is true when the registrar could not be asked, in which case it may still refuse.

GET/organizations/{organization}/domains/registration-fields
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Query parameters
credential_idintegerrequired

Must match an existing stored value.

tldstringoptional

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/registration-fields?credential_id=16" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/registration-fields?credential_id=16" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/registration-fields?credential_id=16', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/registration-fields?credential_id=16",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/registration-fields?credential_id=16', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/registration-fields?credential_id=16", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "fields": [],
  "unknown": true,
  "periods": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Plan a settings change across domains ​

For each domain in ids (up to 500), who would carry out turning setting on or off (value, default true). Changes nothing; each setting is changed through its own endpoint.

GET/organizations/{organization}/domains/settings-plan
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Query parameters
settingstringrequired
valuebooleanoptional
idsarrayoptional

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/settings-plan?setting=%3Csetting%3E" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/settings-plan?setting=%3Csetting%3E" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/settings-plan?setting=%3Csetting%3E', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/settings-plan?setting=%3Csetting%3E",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/settings-plan?setting=%3Csetting%3E', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/settings-plan?setting=%3Csetting%3E", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "setting": "auto_renew",
  "value": true,
  "applies": true,
  "domains": [
    {
      "id": 1,
      "name": "northwind.com",
      "state": "unknown",
      "route": "elsewhere",
      "where": {
        "label": "Namecheap",
        "url": "https://ap.www.namecheap.com/domains/list/"
      },
      "dnssec": null,
      "zone_id": null
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Track a domain by name ​

Adds a domain held at a registrar InfraNest is not connected to; its registrar, dates, status and nameservers are read from the public registry, now and daily. Only name is accepted; it counts toward your plan’s domain limit, and a domain already in your organization is refused with 422.

POST/organizations/{organization}/domains/track
Scope domains.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Bodyapplication/json
namestringrequired

Must not be greater than 253 characters.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/domains/track" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"northwind-studio.com"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "name": "northwind-studio.com"
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/domains/track" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/domains/track', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'name' => 'northwind-studio.com',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/domains/track",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "name": "northwind-studio.com",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/track', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "name": "northwind-studio.com"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/domains/track", strings.NewReader(`{"name":"northwind-studio.com"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 21,
  "organization_id": 1,
  "name": "northwind-studio",
  "tld": "com",
  "registrar": null,
  "registered_at": null,
  "expires_at": null,
  "auto_renew": true,
  "status": "active",
  "notes": null,
  "deleted_at": null,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "provider_credential_id": null,
  "nameservers": null,
  "transfer_lock": null,
  "whois_privacy": null,
  "registrar_contacts": null,
  "dnssec_entries": null,
  "has_dnssec": null,
  "renewal_price": null,
  "renewal_price_currency": null,
  "pricing_cached_at": null,
  "last_details_synced_at": null,
  "status_message": null,
  "expected_issuers": null,
  "renewal_price_source": "api",
  "purchase_price": null,
  "purchase_price_currency": null,
  "registrar_price": null,
  "registrar_price_currency": null,
  "registrar_flags": null,
  "requested_whois_privacy": null,
  "requested_auto_renew": null,
  "archived_at": null,
  "requested_nameservers": null,
  "missing_since": null,
  "serves_website": null,
  "billing_interval": "yearly",
  "interval_count": 1,
  "dnssec_state": null,
  "dnssec_checked_at": null,
  "dnssec_broken_since": null,
  "requested_dns_credential_id": null,
  "requested_dns_template": null,
  "status_detail": null,
  "ordered_by_user_id": null,
  "ns_health": null,
  "ns_health_checked_at": null,
  "unused_since": null,
  "registry_statuses": null,
  "registry_checked_at": null,
  "registry_dnssec": null,
  "full_name": "northwind-studio.com",
  "archivable": true,
  "dns_host": null,
  "management": "tracked",
  "sync_halt": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "name": [
      "The name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Check a domain before transferring it in ​

Checks the usual reasons an inbound transfer fails for the domain given by name and tld, before you submit it. Optionally pass credential_id for the registrar that would receive it; counts toward your plan’s hourly domain-check limit.

GET/organizations/{organization}/domains/transfer-preflight
Scope domains.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Query parameters
namestringrequired

Must not be greater than 100 characters.

tldstringrequired

Must not be greater than 30 characters.

credential_idinteger, nullableoptional

Which of the org's registrars the transfer would go to. Optional: the registry checks below are about the losing side and run without it. Scoped to the org rather than taken on trust — a credential id from another tenant would otherwise make one API call on their key.

Request

sh
curl "https://api.infranest.io/api/organizations/42/domains/transfer-preflight?name=www&tld=%3Ctld%3E" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/domains/transfer-preflight?name=www&tld=%3Ctld%3E" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/domains/transfer-preflight?name=www&tld=%3Ctld%3E', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/domains/transfer-preflight?name=www&tld=%3Ctld%3E",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/domains/transfer-preflight?name=www&tld=%3Ctld%3E', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/domains/transfer-preflight?name=www&tld=%3Ctld%3E", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "domain": "northwind.com",
  "registrar": "Namecheap",
  "expires_at": "2026-02-02",
  "source": "fixture",
  "checks": [
    {
      "key": "not_locked",
      "status": "warn",
      "detail": []
    },
    {
      "key": "sixty_day_rule",
      "status": "pass",
      "detail": {
        "days": 749,
        "free_on": "2024-02-26",
        "since": "registration"
      }
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the domains.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "domains.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited