Automations
Automations and the connections they use. Read only.
Common tasks
Only in the app: Creating and changing automations.
How it works in the app: help article.
Scopes: Read with 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.
Automation connections
List automation connections
The accounts automations can act through, such as GitHub, Jira or PagerDuty, with each one’s status, whether it is paused and whether its triggers can fire.
/organizations/{organization}/automation-connectionsmonitoring.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/automation-connections" \
-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/automation-connections" -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/automation-connections', [
'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/automation-connections",
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/automation-connections', {
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/automation-connections", 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": "pagerduty",
"kind": "oauth",
"label": "Northwind on-call",
"meta": {
"service_name": "Platform — production",
"account": "northwind",
"auth": "oauth",
"region": "us",
"authorized_by": {
"name": "Alex Rivera",
"email": "demo@example.com"
},
"webhook_subscription_id": "PD3WHS1"
},
"status": "active",
"paused": false,
"triggers_on": false,
"created_at": "2026-01-15T12:00:00+00:00"
},
{
"id": 2,
"provider": "github",
"kind": "github_app",
"label": "northwind-cloud",
"meta": {
"installation_id": "20000001",
"account": "northwind-cloud"
},
"status": "active",
"paused": false,
"triggers_on": false,
"created_at": "2026-01-15T12:00:00+00:00"
}
]{
"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
Automations
List automations
Every automation, newest first, with its tags and run statistics: runs in the last 30 and 7 days, success rate, average duration and the last run’s status. Test runs are not counted.
/organizations/{organization}/automationsmonitoring.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/automations" \
-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/automations" -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/automations', [
'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/automations",
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/automations', {
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/automations", 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,
"organization_id": 1,
"name": "Release published → announce on status page",
"trigger_event": "github.release",
"conditions": [
{
"op": "eq",
"field": "action",
"value": "published"
},
{
"op": "eq",
"field": "prerelease",
"value": "false"
}
],
"actions": [
{
"action": "create_status_announcement",
"config": {
"body": "{{name}}.",
"title": "Released: {{tag}}",
"status_page_id": 1
}
}
],
"enabled": true,
"cooldown_seconds": 0,
"consecutive_failures": 0,
"disabled_reason": null,
"last_triggered_at": null,
"created_by": 1,
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"condition_match": "all",
"run_as": "owner",
"trigger_kind": "event",
"schedule": null,
"trigger_events": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"disabled_detail": null,
"template_key": null,
"tags": [],
"runs_30d": 0,
"runs_7d": 0,
"success_rate": null,
"avg_duration_ms": null,
"last_status": null,
"last_run_at": null,
"spark": [
{
"total": 0,
"failed": 0
},
{
"total": 0,
"failed": 0
}
]
},
{
"id": 2,
"organization_id": 1,
"name": "PR merged to main → run deploy workflow",
"trigger_event": "github.pull_request",
"conditions": [
{
"op": "eq",
"field": "merged",
"value": "true"
},
{
"op": "eq",
"field": "base_branch",
"value": "main"
}
],
"actions": [
{
"action": "require_approval",
"config": {
"note": "Production deploy"
}
},
{
"action": "github_trigger_workflow",
"config": {
"ref": "main",
"repo": "northwind-cloud/app",
"workflow": "deploy.yml",
"connection_id": 2
}
}
],
"enabled": true,
"cooldown_seconds": 0,
"consecutive_failures": 0,
"disabled_reason": null,
"last_triggered_at": null,
"created_by": 1,
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"condition_match": "all",
"run_as": "owner",
"trigger_kind": "event",
"schedule": null,
"trigger_events": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"disabled_detail": null,
"template_key": null,
"tags": [],
"runs_30d": 5,
"runs_7d": 5,
"success_rate": 40,
"avg_duration_ms": 3000,
"last_status": "awaiting_approval",
"last_run_at": "2026-01-15T09:00:00.000000Z",
"spark": [
{
"total": 1,
"failed": 1
},
{
"total": 0,
"failed": 0
}
]
}
]{
"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
Get an automation
One automation with its trigger, conditions, actions and tags, plus its 20 most recent runs and their steps.
/organizations/{organization}/automations/{automationRule}monitoring.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.
automationRuleintegerrequiredThe automation rule's ID.
Request
curl "https://api.infranest.io/api/organizations/42/automations/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/automations/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/automations/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/automations/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/automations/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/automations/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,
"organization_id": 1,
"name": "Release published → announce on status page",
"trigger_event": "github.release",
"conditions": [
{
"op": "eq",
"field": "action",
"value": "published"
},
{
"op": "eq",
"field": "prerelease",
"value": "false"
}
],
"actions": [
{
"action": "create_status_announcement",
"config": {
"body": "{{name}}.",
"title": "Released: {{tag}}",
"status_page_id": 1
}
}
],
"enabled": true,
"cooldown_seconds": 0,
"consecutive_failures": 0,
"disabled_reason": null,
"last_triggered_at": null,
"created_by": 1,
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"condition_match": "all",
"run_as": "owner",
"trigger_kind": "event",
"schedule": null,
"trigger_events": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"disabled_detail": null,
"template_key": null,
"tags": [],
"runs": []
}{
"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
List an automation’s runs
The automation’s run history with each run’s steps, newest first, 25 per page. Filter with status and the dates from and to. Unless you may edit automations, what triggered each run is left out and details_hidden is true.
/organizations/{organization}/automations/{automationRule}/runsmonitoring.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.
automationRuleintegerrequiredThe automation rule's ID.
Request
curl "https://api.infranest.io/api/organizations/42/automations/1/runs" \
-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/automations/1/runs" -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/automations/1/runs', [
'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/automations/1/runs",
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/automations/1/runs', {
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/automations/1/runs", 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
{
"details_hidden": false,
"current_page": 1,
"data": [],
"first_page_url": "http://localhost/api/organizations/1/automations/1/runs?page=1",
"from": null,
"last_page": 1,
"last_page_url": "http://localhost/api/organizations/1/automations/1/runs?page=1",
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "http://localhost/api/organizations/1/automations/1/runs?page=1",
"label": "1",
"page": 1,
"active": true
}
],
"next_page_url": null,
"path": "http://localhost/api/organizations/1/automations/1/runs",
"per_page": 25,
"prev_page_url": null,
"to": null,
"total": 0
}{
"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