curl --request POST \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/automations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Nightly dependency audit",
"instructions": "Audit dependencies for known CVEs and open a PR if any need patching.",
"repo": "acme/widget",
"provider": "github"
}
'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/automations"
payload = {
"name": "Nightly dependency audit",
"instructions": "Audit dependencies for known CVEs and open a PR if any need patching.",
"repo": "acme/widget",
"provider": "github"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Nightly dependency audit',
instructions: 'Audit dependencies for known CVEs and open a PR if any need patching.',
repo: 'acme/widget',
provider: 'github'
})
};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/automations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.reasonmachines.com/v3/organizations/{orgId}/automations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Nightly dependency audit',
'instructions' => 'Audit dependencies for known CVEs and open a PR if any need patching.',
'repo' => 'acme/widget',
'provider' => 'github'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.reasonmachines.com/v3/organizations/{orgId}/automations"
payload := strings.NewReader("{\n \"name\": \"Nightly dependency audit\",\n \"instructions\": \"Audit dependencies for known CVEs and open a PR if any need patching.\",\n \"repo\": \"acme/widget\",\n \"provider\": \"github\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.reasonmachines.com/v3/organizations/{orgId}/automations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Nightly dependency audit\",\n \"instructions\": \"Audit dependencies for known CVEs and open a PR if any need patching.\",\n \"repo\": \"acme/widget\",\n \"provider\": \"github\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/automations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Nightly dependency audit\",\n \"instructions\": \"Audit dependencies for known CVEs and open a PR if any need patching.\",\n \"repo\": \"acme/widget\",\n \"provider\": \"github\"\n}"
response = http.request(request)
puts response.read_body{
"id": "automation_example",
"org_id": "org_example",
"name": "Daily repository review",
"instructions": "Review open issues.",
"model": null,
"enabled": true,
"tools": {
"mcp_servers": null,
"app_tools": []
},
"environment": {
"repo": "example/project",
"provider": "github"
},
"triggers": [
{
"id": "trigger_example",
"kind": "schedule",
"enabled": true,
"schedule": {
"kind": "cron",
"expression": "0 9 * * *",
"every_seconds": null,
"next_run_at": "2026-09-24T09:00:00Z"
},
"github": null,
"webhook": null,
"run_kind": null,
"last_fired_at": null,
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}
],
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}{
"error": "prompt_required"
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Create an automation
Creates the automation’s configuration (instructions + environment binding). Add a trigger with POST /automations/{automationId}/triggers to make it fire. The repo must already be connected. Name and instructions are trimmed and may not be blank; tools must name MCP servers the workspace has and known app tools (see the field descriptions for each 400 code). A known app tool that is not connected yet is accepted with an app_tool_not_connected entry in warnings.
automations:writecurl --request POST \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/automations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Nightly dependency audit",
"instructions": "Audit dependencies for known CVEs and open a PR if any need patching.",
"repo": "acme/widget",
"provider": "github"
}
'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/automations"
payload = {
"name": "Nightly dependency audit",
"instructions": "Audit dependencies for known CVEs and open a PR if any need patching.",
"repo": "acme/widget",
"provider": "github"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Nightly dependency audit',
instructions: 'Audit dependencies for known CVEs and open a PR if any need patching.',
repo: 'acme/widget',
provider: 'github'
})
};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/automations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.reasonmachines.com/v3/organizations/{orgId}/automations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Nightly dependency audit',
'instructions' => 'Audit dependencies for known CVEs and open a PR if any need patching.',
'repo' => 'acme/widget',
'provider' => 'github'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.reasonmachines.com/v3/organizations/{orgId}/automations"
payload := strings.NewReader("{\n \"name\": \"Nightly dependency audit\",\n \"instructions\": \"Audit dependencies for known CVEs and open a PR if any need patching.\",\n \"repo\": \"acme/widget\",\n \"provider\": \"github\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.reasonmachines.com/v3/organizations/{orgId}/automations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Nightly dependency audit\",\n \"instructions\": \"Audit dependencies for known CVEs and open a PR if any need patching.\",\n \"repo\": \"acme/widget\",\n \"provider\": \"github\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/automations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Nightly dependency audit\",\n \"instructions\": \"Audit dependencies for known CVEs and open a PR if any need patching.\",\n \"repo\": \"acme/widget\",\n \"provider\": \"github\"\n}"
response = http.request(request)
puts response.read_body{
"id": "automation_example",
"org_id": "org_example",
"name": "Daily repository review",
"instructions": "Review open issues.",
"model": null,
"enabled": true,
"tools": {
"mcp_servers": null,
"app_tools": []
},
"environment": {
"repo": "example/project",
"provider": "github"
},
"triggers": [
{
"id": "trigger_example",
"kind": "schedule",
"enabled": true,
"schedule": {
"kind": "cron",
"expression": "0 9 * * *",
"every_seconds": null,
"next_run_at": "2026-09-24T09:00:00Z"
},
"github": null,
"webhook": null,
"run_kind": null,
"last_fired_at": null,
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}
],
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}{
"error": "prompt_required"
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Authorizations
Your Reason API key from Settings > API. New keys use reason_; legacy ara_ keys remain accepted. Keys are capability-scoped: run, mcp:read, mcp:write, secrets:read, secrets:write, sessions:read, sessions:debug, knowledge:read, memory:read, memory:write, skills:read, skills:write, repos:read, repos:write, reviews:read, reviews:write, deployment:read, analytics:read, org:read, org:write, attachments:read, attachments:write, guardrails:read, guardrails:write, automations:read, automations:write, agent_auth:read. mcp:write manages MCP server configuration only; it does not authorize remote MCP-tool execution. sessions:read reads sessions, including the assistant, reasoning and tool activity in their events. sessions:debug is privileged: only for organization owners/admins, it expands session events to the full diagnostic projection (diagnostic event kinds, status text and raw event metadata).
Path Parameters
Organization id or slug. Resolve it with GET /v3/self.
Body
Creates the automation's configuration. It has no triggers until you add one via POST /automations/{automationId}/triggers, so it will not fire on its own yet.
The system instructions the automation runs with, trimmed, at most 100,000 characters. Blank instructions return 400 instructions_required; longer ones return 400 instructions_too_long.
Connected GitHub repository path in owner/name form.
Display name, trimmed, at most 200 characters. Defaults to the start of instructions when omitted. A blank name returns 400 name_required; a longer one returns 400 name_too_long.
Source-control provider for the connected repository. GitHub is the only supported provider.
github Model override. null uses the workspace default. New runs accept only the currently available Reason model catalog.
Show child attributes
Show child attributes
Response
Created.
An automation: its instructions, tools, environment binding, and triggers.
The system instructions the automation runs with.
A paused (false) automation's triggers never fire.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Every condition that fires this automation. Empty until you add one.
Show child attributes
Show child attributes
Present only when the request was accepted but something is not as sent or not usable yet. Codes: schedule_interval_raised, app_tool_not_connected.
Show child attributes
Show child attributes

