Create a subscription
curl --request POST \
--url https://api.example.com/exo-api/webhooks \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"resource": "<string>",
"events": [
{}
]
}
'import requests
url = "https://api.example.com/exo-api/webhooks"
payload = {
"url": "<string>",
"resource": "<string>",
"events": [{}]
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>', resource: '<string>', events: [{}]})
};
fetch('https://api.example.com/exo-api/webhooks', 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.example.com/exo-api/webhooks",
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([
'url' => '<string>',
'resource' => '<string>',
'events' => [
[
]
]
]),
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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/exo-api/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"resource\": \"<string>\",\n \"events\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/exo-api/webhooks")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"resource\": \"<string>\",\n \"events\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/exo-api/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"resource\": \"<string>\",\n \"events\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_bodyWebhooks
Create a subscription
Creates a new webhook subscription.
POST
/
exo-api
/
webhooks
Create a subscription
curl --request POST \
--url https://api.example.com/exo-api/webhooks \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"resource": "<string>",
"events": [
{}
]
}
'import requests
url = "https://api.example.com/exo-api/webhooks"
payload = {
"url": "<string>",
"resource": "<string>",
"events": [{}]
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>', resource: '<string>', events: [{}]})
};
fetch('https://api.example.com/exo-api/webhooks', 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.example.com/exo-api/webhooks",
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([
'url' => '<string>',
'resource' => '<string>',
'events' => [
[
]
]
]),
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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/exo-api/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"resource\": \"<string>\",\n \"events\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/exo-api/webhooks")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"resource\": \"<string>\",\n \"events\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/exo-api/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"resource\": \"<string>\",\n \"events\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_bodyCreates a webhook subscription that delivers events to the specified URL. The full secret is only returned in this response.
Request body
string
required
The URL to receive webhook POST requests. Must be a valid URL (max 2048 characters).
string
required
The resource name to subscribe to. Must match a registered resource.
array
required
Array of trigger events to listen for. Must be a subset of the resource’s supported triggers:
on_create, on_update, on_delete.Request
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhook-receiver",
"resource": "order",
"events": ["on_create", "on_update"]
}' \
https://your-app.com/exo-api/webhooks
Response
Returns the created subscription with a201 Created status. The secret field contains the full webhook secret.
Example response:
{
"id": 1,
"user_id": 1,
"url": "https://example.com/webhook-receiver",
"resource": "order",
"events": ["on_create", "on_update"],
"secret": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2",
"is_active": true,
"created_at": "2026-03-28T14:30:00.000000Z",
"updated_at": "2026-03-28T14:30:00.000000Z"
}
The
secret is only returned in full in this response. Store it securely — you need it to verify webhook signatures. Subsequent requests show only a masked version.Errors
| Status | Description |
|---|---|
422 | Validation failed — invalid URL, unknown resource, or unsupported events |
⌘I