Integrations
Connected providers and messaging apps. Read only: credentials are managed in the app.
Common tasks
Only in the app: Connecting, reconnecting and removing providers and their credentials.
How it works in the app: help article.
Scopes: Read with cloud.read or monitoring.read. 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.
Integrations
List connected integrations
Everything the organization has connected — cloud, DNS, registrar and certificate accounts, alert destinations, outbound webhooks, automation connections and calendars — each with its status and health. Also returns summary counts and the integrations your plan does not include (locks).
/organizations/{organization}/integrationscloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
Request
curl "https://api.infranest.io/api/organizations/42/integrations" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/integrations" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/integrations', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/integrations",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/integrations', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/integrations", 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
{
"connections": [
{
"id": 1,
"kind": "provider",
"provider": "hetzner",
"integration_key": "hetzner",
"name": "Hetzner — Production",
"categories": [
"cloud",
"dns"
],
"capabilities": [
"cloud",
"dns"
],
"counts": {
"servers": 6,
"zones": 2,
"domains": 0,
"certs": 1
},
"suspended_capabilities": [],
"incident": null,
"auth_kind": "api_token",
"enabled": true,
"status": "connected",
"locked": false,
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 97,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
},
"rate_limited": null,
"last_activity_at": "2026-01-15T12:00:00Z"
},
{
"id": 2,
"kind": "provider",
"provider": "cloudflare",
"integration_key": "cloudflare",
"name": "Cloudflare DNS",
"categories": [
"dns",
"domains"
],
"capabilities": [
"dns",
"registrar"
],
"counts": {
"servers": 0,
"zones": 5,
"domains": 0,
"certs": 1
},
"suspended_capabilities": [],
"incident": null,
"auth_kind": "api_token",
"enabled": true,
"status": "connected",
"locked": false,
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 49,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
},
"rate_limited": null,
"last_activity_at": "2026-01-15T12:00:00Z"
}
],
"summary": {
"total": 22,
"connected": 16,
"degraded": 3,
"failing": 2,
"disabled": 1,
"issues": 5,
"locked": 0
},
"locks": []
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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 an integration
What the integration offers, the organization’s connections to it, and whether your plan allows connecting it. Returns 404 for an unknown integration.
/organizations/{organization}/integrations/{provider}cloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
providerintegerrequiredThe provider's ID.
Request
curl "https://api.infranest.io/api/organizations/42/integrations/1" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/integrations/1" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/integrations/1', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/integrations/1",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/integrations/1', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/integrations/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
{
"provider": {
"key": "hetzner",
"label": "Hetzner",
"logo": "hetzner",
"capabilities": [
"cloud",
"dns"
],
"categories": [
"cloud",
"dns"
],
"dns_scope": "any",
"features": [
"zone_discovery",
"record_ids"
],
"environments": [],
"oauth": false,
"one_click": false,
"needs_allowlist": false,
"featured": true,
"premium": false,
"min_plan": null,
"max_connections": null,
"credentials": [
{
"key": "api_token",
"label": "integrations.providers.hetzner.apiToken.label",
"secret": true,
"multiline": false,
"help": "integrations.providers.hetzner.apiToken.help",
"help_params": {
"aws_account_id": "InfraNest's AWS account (set AWS_INFRANEST_ACCOUNT_ID)"
},
"placeholder": "LRK9mXv2QpT8sYw4…",
"prefill": null,
"type": "text",
"options": null,
"depends_on": null,
"show_when": null,
"default": null
}
],
"kind": "provider",
"content": null
},
"connections": [
{
"id": 1,
"kind": "provider",
"provider": "hetzner",
"integration_key": "hetzner",
"name": "Hetzner — Production",
"categories": [
"cloud",
"dns"
],
"capabilities": [
"cloud",
"dns"
],
"counts": {
"servers": 6,
"zones": 2,
"domains": 0,
"certs": 1
},
"suspended_capabilities": [],
"incident": null,
"auth_kind": "api_token",
"enabled": true,
"status": "connected",
"locked": false,
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 97,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
},
"rate_limited": null,
"last_activity_at": "2026-01-15T12:00:00Z"
}
],
"gate": {
"locked": false,
"reason": null,
"premium": false,
"min_plan": null,
"min_plan_name": null,
"current_plan": "pro",
"current_plan_name": "Pro",
"max_connections": null,
"used": 1,
"grandfathered": false,
"included": false
}
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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 an integration account
One connected account of an integration, whatever kind it is, with its status and health. Returns 404 when the account does not exist or does not belong to this integration and organization.
/organizations/{organization}/integrations/{provider}/accounts/{id}cloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
providerintegerrequiredThe provider's ID.
idintegerrequiredThe id's ID.
Request
curl "https://api.infranest.io/api/organizations/42/integrations/1/accounts/1" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/integrations/1/accounts/1" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/integrations/1/accounts/1', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/integrations/1/accounts/1",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/integrations/1/accounts/1', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/integrations/1/accounts/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
{
"id": 1,
"provider": "hetzner",
"label": "Hetzner — Production",
"enabled": true,
"removing": false,
"is_oauth": false,
"auth_kind": "api_token",
"oauth": null,
"error_email_enabled": true,
"alerts_muted_until": null,
"incident": null,
"notices": [],
"spending": null,
"capabilities": [
"cloud",
"dns"
],
"supported_capabilities": [
"cloud",
"dns"
],
"cloud_capabilities": {
"native_delete_protection": true,
"server_destroy": true,
"server_destroy_is_cancellation": false,
"server_create": true,
"server_rename": true,
"console": true,
"snapshots": true,
"backups": true,
"isos": true,
"rescue": true,
"placement_groups": true,
"public_network_toggle": true,
"scheduled_backups": true,
"private_networks": true,
"private_network_attach": true,
"network_join_on_create": false,
"network_attach_ip_choice": true,
"private_network_unfiltered": true,
"floating_ips": true,
"networks_creatable": true,
"network_cidr": true,
"network_subnets": true,
"network_routes": true,
"network_rename": true,
"network_ip_range_extendable": true,
"firewalls_creatable": true,
"firewall_multi_server": true,
"firewall_renamable": true,
"firewall_outbound": true,
"firewall_ipv6": true,
"firewall_dynamic_ip": true,
"server_firewall": false,
"load_balancers_creatable": true,
"load_balancer_rename": true,
"load_balancer_algorithm": true,
"load_balancer_services": true,
"load_balancer_targets": true,
"volumes_creatable": true,
"volume_resize": true,
"volume_rename": true,
"volume_native_delete_protection": true,
"network_native_delete_protection": true,
"user_data": true,
"install_flavour": false,
"images_per_plan": false,
"metrics": true,
"metrics_disk_throughput": true,
"rdns_subnet": true,
"rdns_address_list": false,
"reverse_dns": true,
"snapshot_description": true,
"snapshot_protection": true
},
"dns_capabilities": {
"record_writes": true,
"bulk_replace": false,
"zone_create": true,
"zone_delete": true,
"record_proxying": false,
"signing": false
},
"dns_scope": "any",
"cloud_firewall_protocols": [
"tcp",
"udp"
],
"enabled_capabilities": null,
"suspended_capabilities": [],
"resource_counts": {
"dns": 2,
"certificates": 1,
"cloud": 6
},
"verified_at": "2025-10-15T12:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"fields": [
"api_token"
],
"environment": null,
"field_values": {
"api_token": {
"set": true,
"secret": true,
"display": "••••oken"
}
},
"context": [],
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 97,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
},
"registrar_operations": null,
"scope_check": null,
"scope_checked_at": null,
"disabled_operations": [],
"api_base": "/organizations/1/provider-credentials/1"
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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 integration activity
The calls made to and received from this integration, newest first, paginated with per_page (5 to 100, default 20). Filter with status (success or error), capability, direction, credential_id and search; meta lists the accounts and filter values available.
/organizations/{organization}/integrations/{provider}/activitycloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
providerintegerrequiredThe provider's ID.
Request
curl "https://api.infranest.io/api/organizations/42/integrations/1/activity" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/integrations/1/activity" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/integrations/1/activity', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/integrations/1/activity",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/integrations/1/activity', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/integrations/1/activity", 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
{
"data": [
{
"id": 9,
"credential_id": 1,
"capability": "cloud",
"direction": "outbound",
"method": "GET",
"endpoint": "/v1/servers",
"action": "listServers",
"success": true,
"http_status": 200,
"duration_ms": 60,
"error_type": null,
"error_message": null,
"created_at": "2026-01-15T12:00:00.000000Z"
},
{
"id": 10,
"credential_id": 1,
"capability": "cloud",
"direction": "outbound",
"method": "GET",
"endpoint": "/v1/volumes",
"action": "listVolumes",
"success": true,
"http_status": 200,
"duration_ms": 112,
"error_type": null,
"error_message": null,
"created_at": "2026-01-15T11:57:00.000000Z"
}
],
"total": 672,
"last_page": 34,
"meta": {
"accounts": [
{
"id": 1,
"label": "Hetzner — Production",
"context": []
}
],
"capabilities": [
"cloud"
],
"directions": [
"outbound"
],
"rate_limit": null
}
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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
Export integration activity as CSV
Downloads every call logged for this integration as a CSV file, newest first. Takes the same status, capability, direction, credential_id and search filters as the activity list.
/organizations/{organization}/integrations/{provider}/activity/exportcloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
providerintegerrequiredThe provider's ID.
Request
curl "https://api.infranest.io/api/organizations/42/integrations/1/activity/export" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/integrations/1/activity/export" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/integrations/1/activity/export', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/integrations/1/activity/export",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/integrations/1/activity/export', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/integrations/1/activity/export", 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
The integration's activity log as CSV.
Content-Type: text/csv{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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
Provider credentials
List provider accounts
Every connected cloud, DNS, registrar and certificate account, with its health and how many zones, domains, certificates and servers it holds.
/organizations/{organization}/provider-credentialscloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
Request
curl "https://api.infranest.io/api/organizations/42/provider-credentials" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/provider-credentials" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/provider-credentials', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/provider-credentials",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/provider-credentials', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/provider-credentials", 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
[
{
"id": 1,
"provider": "hetzner",
"label": "Hetzner — Production",
"enabled": true,
"removing": false,
"is_oauth": false,
"auth_kind": "api_token",
"oauth": null,
"error_email_enabled": true,
"alerts_muted_until": null,
"incident": null,
"notices": [],
"spending": null,
"capabilities": [
"cloud",
"dns"
],
"supported_capabilities": [
"cloud",
"dns"
],
"cloud_capabilities": {
"native_delete_protection": true,
"server_destroy": true,
"server_destroy_is_cancellation": false,
"server_create": true,
"server_rename": true,
"console": true,
"snapshots": true,
"backups": true,
"isos": true,
"rescue": true,
"placement_groups": true,
"public_network_toggle": true,
"scheduled_backups": true,
"private_networks": true,
"private_network_attach": true,
"network_join_on_create": false,
"network_attach_ip_choice": true,
"private_network_unfiltered": true,
"floating_ips": true,
"networks_creatable": true,
"network_cidr": true,
"network_subnets": true,
"network_routes": true,
"network_rename": true,
"network_ip_range_extendable": true,
"firewalls_creatable": true,
"firewall_multi_server": true,
"firewall_renamable": true,
"firewall_outbound": true,
"firewall_ipv6": true,
"firewall_dynamic_ip": true,
"server_firewall": false,
"load_balancers_creatable": true,
"load_balancer_rename": true,
"load_balancer_algorithm": true,
"load_balancer_services": true,
"load_balancer_targets": true,
"volumes_creatable": true,
"volume_resize": true,
"volume_rename": true,
"volume_native_delete_protection": true,
"network_native_delete_protection": true,
"user_data": true,
"install_flavour": false,
"images_per_plan": false,
"metrics": true,
"metrics_disk_throughput": true,
"rdns_subnet": true,
"rdns_address_list": false,
"reverse_dns": true,
"snapshot_description": true,
"snapshot_protection": true
},
"dns_capabilities": {
"record_writes": true,
"bulk_replace": false,
"zone_create": true,
"zone_delete": true,
"record_proxying": false,
"signing": false
},
"dns_scope": "any",
"cloud_firewall_protocols": [
"tcp",
"udp"
],
"enabled_capabilities": null,
"suspended_capabilities": [],
"resource_counts": {
"dns": 2,
"certificates": 1,
"cloud": 6
},
"verified_at": "2025-10-15T12:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"fields": [
"api_token"
],
"environment": null,
"field_values": {
"api_token": {
"set": true,
"secret": true,
"display": "••••oken"
}
},
"context": [],
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 97,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
}
},
{
"id": 2,
"provider": "cloudflare",
"label": "Cloudflare DNS",
"enabled": true,
"removing": false,
"is_oauth": false,
"auth_kind": "api_token",
"oauth": null,
"error_email_enabled": true,
"alerts_muted_until": null,
"incident": null,
"notices": [],
"spending": null,
"capabilities": [
"dns",
"registrar"
],
"supported_capabilities": [
"dns",
"registrar"
],
"cloud_capabilities": [],
"dns_capabilities": {
"record_writes": true,
"bulk_replace": false,
"zone_create": true,
"zone_delete": true,
"record_proxying": true,
"signing": true
},
"dns_scope": "any",
"cloud_firewall_protocols": [],
"enabled_capabilities": null,
"suspended_capabilities": [],
"resource_counts": {
"dns": 5,
"registrar": 0,
"certificates": 1
},
"verified_at": "2025-10-15T12:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"fields": [
"api_token",
"account_id"
],
"environment": null,
"field_values": {
"api_token": {
"set": true,
"secret": true,
"display": "••••oken"
},
"account_id": {
"set": true,
"secret": false,
"display": "demoaccount0000000000000000cf01"
}
},
"context": [],
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 49,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
}
}
]{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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 provider account
One connected provider account with its health, how many zones, domains, certificates and servers it holds, the registrar operations it supports and the result of its last permission check. Secrets are never returned.
/organizations/{organization}/provider-credentials/{providerCredential}cloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
providerCredentialintegerrequiredThe provider credential's ID.
Request
curl "https://api.infranest.io/api/organizations/42/provider-credentials/1" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/provider-credentials/1" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/provider-credentials/1', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/provider-credentials/1",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/provider-credentials/1', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/provider-credentials/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
{
"id": 1,
"provider": "hetzner",
"label": "Hetzner — Production",
"enabled": true,
"removing": false,
"is_oauth": false,
"auth_kind": "api_token",
"oauth": null,
"error_email_enabled": true,
"alerts_muted_until": null,
"incident": null,
"notices": [],
"spending": null,
"capabilities": [
"cloud",
"dns"
],
"supported_capabilities": [
"cloud",
"dns"
],
"cloud_capabilities": {
"native_delete_protection": true,
"server_destroy": true,
"server_destroy_is_cancellation": false,
"server_create": true,
"server_rename": true,
"console": true,
"snapshots": true,
"backups": true,
"isos": true,
"rescue": true,
"placement_groups": true,
"public_network_toggle": true,
"scheduled_backups": true,
"private_networks": true,
"private_network_attach": true,
"network_join_on_create": false,
"network_attach_ip_choice": true,
"private_network_unfiltered": true,
"floating_ips": true,
"networks_creatable": true,
"network_cidr": true,
"network_subnets": true,
"network_routes": true,
"network_rename": true,
"network_ip_range_extendable": true,
"firewalls_creatable": true,
"firewall_multi_server": true,
"firewall_renamable": true,
"firewall_outbound": true,
"firewall_ipv6": true,
"firewall_dynamic_ip": true,
"server_firewall": false,
"load_balancers_creatable": true,
"load_balancer_rename": true,
"load_balancer_algorithm": true,
"load_balancer_services": true,
"load_balancer_targets": true,
"volumes_creatable": true,
"volume_resize": true,
"volume_rename": true,
"volume_native_delete_protection": true,
"network_native_delete_protection": true,
"user_data": true,
"install_flavour": false,
"images_per_plan": false,
"metrics": true,
"metrics_disk_throughput": true,
"rdns_subnet": true,
"rdns_address_list": false,
"reverse_dns": true,
"snapshot_description": true,
"snapshot_protection": true
},
"dns_capabilities": {
"record_writes": true,
"bulk_replace": false,
"zone_create": true,
"zone_delete": true,
"record_proxying": false,
"signing": false
},
"dns_scope": "any",
"cloud_firewall_protocols": [
"tcp",
"udp"
],
"enabled_capabilities": null,
"suspended_capabilities": [],
"resource_counts": {
"dns": 2,
"certificates": 1,
"cloud": 6
},
"verified_at": "2025-10-15T12:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"fields": [
"api_token"
],
"environment": null,
"field_values": {
"api_token": {
"set": true,
"secret": true,
"display": "••••oken"
}
},
"context": [],
"health": {
"status": "ok",
"success_rate": 100,
"total_calls": 97,
"last_error_at": null,
"last_success_at": "2026-01-15T12:00:00Z"
},
"registrar_operations": null,
"scope_check": null,
"scope_checked_at": null,
"disabled_operations": []
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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 provider account’s call log
The most recent 200 calls InfraNest made with this account, newest first. Filter with status (success or failure) and the dates from and to.
/organizations/{organization}/provider-credentials/{providerCredential}/logscloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
providerCredentialintegerrequiredThe provider credential's ID.
Request
curl "https://api.infranest.io/api/organizations/42/provider-credentials/1/logs" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/provider-credentials/1/logs" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/provider-credentials/1/logs', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/provider-credentials/1/logs",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/provider-credentials/1/logs', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/provider-credentials/1/logs", 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
[
{
"id": 9,
"provider": "hetzner",
"capability": "cloud",
"method": "GET",
"endpoint": "/v1/servers",
"success": true,
"http_status": 200,
"duration_ms": 60,
"error_type": null,
"error_message": null,
"provider_request_id": null,
"request_summary": null,
"response_summary": null,
"created_at": "2026-01-15T12:00:00.000000Z"
},
{
"id": 10,
"provider": "hetzner",
"capability": "cloud",
"method": "GET",
"endpoint": "/v1/volumes",
"success": true,
"http_status": 200,
"duration_ms": 112,
"error_type": null,
"error_message": null,
"provider_request_id": null,
"request_summary": null,
"response_summary": null,
"created_at": "2026-01-15T11:57:00.000000Z"
}
]{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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 provider account health
How many enabled provider accounts there are (total) and how many are currently degraded or down (unhealthy).
/organizations/{organization}/provider-credentials/healthcloud.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
Request
curl "https://api.infranest.io/api/organizations/42/provider-credentials/health" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/provider-credentials/health" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/provider-credentials/health', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/provider-credentials/health",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/provider-credentials/health', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/provider-credentials/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
{
"unhealthy": 2,
"total": 10
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the cloud.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": "cloud.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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
Webhook endpoints
Get the outbound webhook JSON Schema
The JSON Schema of the payload InfraNest sends to your webhook endpoints, for tools that type a payload from a schema. Narrow it with events[]; with none, it covers every event. events lists every event you can name.
/organizations/{organization}/webhook-endpoints/schemamonitoring.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
Query parameters
eventsarrayoptionalRequest
curl "https://api.infranest.io/api/organizations/42/webhook-endpoints/schema" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/webhook-endpoints/schema" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/webhook-endpoints/schema', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/webhook-endpoints/schema",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/webhook-endpoints/schema', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/webhook-endpoints/schema", 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
{
"schema": {
"type": "object",
"properties": {
"event": {
"title": "Event",
"type": "string"
},
"created_at": {
"title": "Created at",
"type": "string",
"format": "date-time"
},
"data": {
"type": "object",
"properties": {
"acknowledged_by": {
"title": "Acknowledged by",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"action": {
"title": "Action",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"actor": {
"title": "Actor",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"agent": {
"title": "Agent",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"asn_org": {
"title": "ASN org",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"assignee": {
"title": "Assignee",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"assignees": {
"title": "Assignees",
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"auction": {
"title": "Auction",
"anyOf": [
{
"type": "object"
},
{
"type": "null"
}
]
},
"author": {
"title": "Author",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"base_branch": {
"title": "Base branch",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"branch": {
"title": "Branch",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"change": {
"title": "Change",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"changed_fields": {
"title": "Changed fields",
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"check_name": {
"title": "Check name",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"comment": {
"title": "Comment",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"commits": {
"title": "Commits",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"conclusion": {
"title": "Conclusion",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"context": {
"title": "Context",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"country_code": {
"title": "Country code",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"created": {
"title": "Created",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"creator": {
"title": "Creator",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"current_ipv4": {
"title": "Current IPv4",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"current_ipv6": {
"title": "Current IPv6",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"custom_fields": {
"title": "Custom fields",
"anyOf": [
{
"type": "object"
},
{
"type": "null"
}
]
},
"days_left": {
"title": "Days left",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"deleted": {
"title": "Deleted",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"deleted_in": {
"title": "Deleted in",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"deployment_id": {
"title": "Deployment ID",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"description": {
"title": "Description",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"domain": {
"title": "Domain",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"draft": {
"title": "Draft",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"drop_eta": {
"title": "Drop ETA",
"anyOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "null"
}
]
},
"duration_minutes": {
"title": "Duration minutes",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"email": {
"title": "Email",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"endpoint": {
"title": "Endpoint",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"environment": {
"title": "Environment",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"environment_url": {
"title": "Environment URL",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"escalation_policy": {
"title": "Escalation policy",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"expires_at": {
"title": "Expires at",
"anyOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "null"
}
]
},
"expiry_may_be_stale": {
"title": "Expiry may be stale",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"forced": {
"title": "Forced",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"head_branch": {
"title": "Head branch",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"head_sha": {
"title": "Head SHA",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"host": {
"title": "Host",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"identifier": {
"title": "Identifier",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"incident_title": {
"title": "Incident title",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"incident_type": {
"title": "Incident type",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"incident_url": {
"title": "Incident URL",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"ip": {
"title": "IP",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"ip_version": {
"title": "IP version",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"is_hosting": {
"title": "Is hosting",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"is_pull_request": {
"title": "Is pull request",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"issue_type": {
"title": "Issue type",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"issuer": {
"title": "Issuer",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"issues": {
"title": "Issues",
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"label": {
"title": "Label",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"labels": {
"title": "Labels",
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"log_url": {
"title": "Log URL",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"merged": {
"title": "Merged",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"message": {
"title": "Message",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"monitor_type": {
"title": "Monitor type",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"name": {
"title": "Name",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"new_nameservers": {
"title": "New nameservers",
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"note": {
"title": "Note",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"note_trimmed": {
"title": "Note trimmed",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"number": {
"title": "Number",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"old_nameservers": {
"title": "Old nameservers",
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"owner": {
"title": "Owner",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"owner_email": {
"title": "Owner email",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"owner_name": {
"title": "Owner name",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"pd_connection_id": {
"title": "PagerDuty connection ID",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"pd_incident_id": {
"title": "PagerDuty incident ID",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"prerelease": {
"title": "Prerelease",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"previous_state": {
"title": "Previous state",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"priority": {
"title": "Priority"
},
"production_environment": {
"title": "Production environment",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"project": {
"title": "Project",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"provider": {
"title": "Provider",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"pusher": {
"title": "Pusher",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"record_action": {
"title": "Record action",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"record_name": {
"title": "Record name",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"record_type": {
"title": "Record type",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"records": {
"title": "Records",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"ref": {
"title": "Ref",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"ref_type": {
"title": "Ref type",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"registrar": {
"title": "Registrar",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"repo": {
"title": "Repo",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"responder": {
"title": "Responder",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"responder_message": {
"title": "Responder message",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"responder_state": {
"title": "Responder state",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"reviewer": {
"title": "Reviewer",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"run_attempt": {
"title": "Run attempt",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"run_id": {
"title": "Run ID",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"run_number": {
"title": "Run number",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"server_name": {
"title": "Server name",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"service": {
"title": "Service",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"sha": {
"title": "SHA",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"size_gb": {
"title": "Size GB",
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"state": {
"title": "State",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"status": {
"title": "Status",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"status_page": {
"title": "Status page",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"subject": {
"title": "Subject",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"tag": {
"title": "Tag",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"task": {
"title": "Task",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"team": {
"title": "Team",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"title": {
"title": "Title",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"tld": {
"title": "TLD",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"transient_environment": {
"title": "Transient environment",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"trigger_event": {
"title": "Triggering event",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"triggering_actor": {
"title": "Triggering actor",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"type": {
"title": "Type",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"unused": {
"title": "Unused",
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"update_status": {
"title": "Update status",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"urgency": {
"title": "Urgency",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"title": "URL",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"via": {
"title": "Via",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"workflow": {
"title": "Workflow",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"zone": {
"title": "Zone",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
}
}
},
"required": [
"event",
"created_at"
]
},
"events": [
"domain.registered",
"domain.expiring"
]
}{
"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"
}{
"code": "scope_missing",
"message": "This API token does not have the monitoring.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": "monitoring.read",
"reference": "k3j9x0b2qa"
}{
"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"
}{
"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