curl --request POST \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run', 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}/reasons/{reasonId}/loops/{loopId}/run",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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}/reasons/{reasonId}/loops/{loopId}/run")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"loop": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"prompt": "<string>",
"enabled": true,
"status": "active",
"paused_reason": "<string>",
"schedule": {
"kind": "every",
"expression": "<string>",
"every_seconds": 123,
"timezone": "<string>",
"next_run_at": "2023-11-07T05:31:56Z"
},
"slack": {},
"execution_mode": "session",
"session_id": "<string>",
"latest_session_id": "<string>",
"device_id": "<string>",
"repository": "<string>",
"model": "<string>",
"notification_policy": "important_updates",
"until": "2023-11-07T05:31:56Z",
"max_runs": 123,
"run_count": 123,
"last_run": {
"status": "<string>",
"at": "<string>",
"session_id": "<string>"
},
"created_by_user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"trigger_description": "<string>",
"wakes_on": [
{
"kind": "schedule",
"description": "<string>"
}
],
"event_trigger": {
"kind": "webhook",
"url": "<string>"
},
"viewer_access": {
"edit": true,
"stop": true
}
},
"webhook": {
"url": "<string>",
"key": "<string>"
}
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": "session_not_found"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Run a Loop now
Moves the Loop’s next scheduled wake to now. The scheduler starts it within a minute, with the same Session, billing and deduplication as a scheduled wake. Who sees and changes a Loop follows its Reason: the people who can use the Reason see and change its Loops, except that a teammate’s Loop on a team Reason stays that teammate’s (the Reason’s owner may see and stop it). Workspace owners and admins may pause and delete any Loop.What a Loop runs in (its Session or computer), its Slack channels and what wakes it stay with its creator, since each is checked against their access (403 loop_creator_only_change).
automations:writecurl --request POST \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run', 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}/reasons/{reasonId}/loops/{loopId}/run",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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}/reasons/{reasonId}/loops/{loopId}/run")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/reasons/{reasonId}/loops/{loopId}/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"loop": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"prompt": "<string>",
"enabled": true,
"status": "active",
"paused_reason": "<string>",
"schedule": {
"kind": "every",
"expression": "<string>",
"every_seconds": 123,
"timezone": "<string>",
"next_run_at": "2023-11-07T05:31:56Z"
},
"slack": {},
"execution_mode": "session",
"session_id": "<string>",
"latest_session_id": "<string>",
"device_id": "<string>",
"repository": "<string>",
"model": "<string>",
"notification_policy": "important_updates",
"until": "2023-11-07T05:31:56Z",
"max_runs": 123,
"run_count": 123,
"last_run": {
"status": "<string>",
"at": "<string>",
"session_id": "<string>"
},
"created_by_user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"trigger_description": "<string>",
"wakes_on": [
{
"kind": "schedule",
"description": "<string>"
}
],
"event_trigger": {
"kind": "webhook",
"url": "<string>"
},
"viewer_access": {
"edit": true,
"stop": true
}
},
"webhook": {
"url": "<string>",
"key": "<string>"
}
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": "session_not_found"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Authorizations
Your Reason API key from Settings › API keys. 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, network:read, network:write, automations:read, automations:write, agent_auth:read. network:read and network:write are opt-in, excluded from default keys. network:read reads the saved workspace network policy; network:write replaces custom allowed hosts and requires a current organization owner/admin. Legacy project PATCH requests containing network_allowed_hosts also require network:write plus their existing run scope and project management permission; saved project hosts do not affect current session egress. Only owners/admins can mint or manage keys with network:write; keys cannot grant themselves more authority. See /docs/network-policies for replacement semantics and runtime applicability. 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.
The Reason id, returned as id by listReasons and createReason.
The Loop id, returned as id by listReasonLoops and as loop.id by createReasonLoop.
Response
The Loop, due now.
The Loop as saved, and the webhook it just gave out, when it did.

