curl --request POST \
--url https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key} \
--header 'Content-Type: application/json'import requests
url = "https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}"
headers = {"Content-Type": "application/json"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'Content-Type': 'application/json'}};
fetch('https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}', 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/webhooks/automations/{publicToken}/{key}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}"
req, _ := http.NewRequest("POST", url, nil)
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/webhooks/automations/{publicToken}/{key}")
.header("Content-Type", "application/json")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
response = http.request(request)
puts response.read_body{
"accepted": true,
"duplicate": true,
"event_id": "<string>",
"work_item_id": "<string>"
}Send an event to a Loop (key in the URL)
Delivers an event to the Loop whose webhook this is. A Loop with a webhook wakes on each accepted event: the event opens a Session of its Reason, or continues the Session of earlier events with the same correlation key. The webhook URL and its key come back once, from the createReasonLoop (or updateReasonLoop) call that adds the webhook.
This form carries the key as the URL’s last path segment, for a sender that only takes a URL. Prefer the bearer header or a signature where the sender allows one: a URL is easier to leak.
A retry with the same event id is answered 202 with duplicate: true and is not queued again. A paused or deleted Loop refuses events (409 automation_disabled).
curl --request POST \
--url https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key} \
--header 'Content-Type: application/json'import requests
url = "https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}"
headers = {"Content-Type": "application/json"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {'Content-Type': 'application/json'}};
fetch('https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}', 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/webhooks/automations/{publicToken}/{key}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}"
req, _ := http.NewRequest("POST", url, nil)
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/webhooks/automations/{publicToken}/{key}")
.header("Content-Type", "application/json")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/webhooks/automations/{publicToken}/{key}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
response = http.request(request)
puts response.read_body{
"accepted": true,
"duplicate": true,
"event_id": "<string>",
"work_item_id": "<string>"
}Headers
Events with the same key continue one Session; without it (or a key in the body) each event opens its own.
500The sender's id for the event; a retry with the same id is answered as a duplicate and queued once. Without one (or an id in the body), every POST is a new event.
240Which system sent the event, shown with it.
80For a sender you write: hex HMAC-SHA256 of the exact body bytes, keyed with the Loop's webhook key (or its signing secret), optionally prefixed sha256=. X-Signature is read the same way.
Path Parameters
The webhook's public token: the last segment of the webhook URL createReasonLoop returns. It names the webhook and authenticates nothing.
The Loop's webhook key, for a sender that only takes a URL.
Response
Accepted, or a duplicate of an event already accepted.
True when an event with the same id already arrived: this one is not queued again, and the earlier event's ids are returned.
The stored event.
The unit of work its correlation key groups it into: one Session per work item.

