Create an outbound webhook
using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://api.vendorica.com/v1/webhooks"), Headers = { { "Authorization", "Bearer <token>" }, }, Content = new StringContent("{ \"name\": \"example\", \"triggers\": [ \"example\" ], \"endpoint\": \"https://example.com\", \"customHeaders\": [ { \"name\": \"example\", \"value\": \"example\" } ], \"signingEnabled\": true, \"retryPolicy\": { \"enabled\": true, \"maxAttempts\": 1, \"backoff\": \"exponential\", \"initialDelaySeconds\": 1, \"maxDelaySeconds\": 1, \"retryOn\": [ \"timeout\" ] }, \"failureHandling\": { \"autoDisableAfter\": 1, \"disableOnGone\": true } }") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://api.vendorica.com/v1/webhooks"
payload := strings.NewReader("{ \"name\": \"example\", \"triggers\": [ \"example\" ], \"endpoint\": \"https://example.com\", \"customHeaders\": [ { \"name\": \"example\", \"value\": \"example\" } ], \"signingEnabled\": true, \"retryPolicy\": { \"enabled\": true, \"maxAttempts\": 1, \"backoff\": \"exponential\", \"initialDelaySeconds\": 1, \"maxDelaySeconds\": 1, \"retryOn\": [ \"timeout\" ] }, \"failureHandling\": { \"autoDisableAfter\": 1, \"disableOnGone\": true } }")
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(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{ \"name\": \"example\", \"triggers\": [ \"example\" ], \"endpoint\": \"https://example.com\", \"customHeaders\": [ { \"name\": \"example\", \"value\": \"example\" } ], \"signingEnabled\": true, \"retryPolicy\": { \"enabled\": true, \"maxAttempts\": 1, \"backoff\": \"exponential\", \"initialDelaySeconds\": 1, \"maxDelaySeconds\": 1, \"retryOn\": [ \"timeout\" ] }, \"failureHandling\": { \"autoDisableAfter\": 1, \"disableOnGone\": true } }");Request request = new Request.Builder() .url("https://api.vendorica.com/v1/webhooks") .post(body) .addHeader("Authorization", "Bearer <token>") .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();const url = 'https://api.vendorica.com/v1/webhooks';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"name":"example","triggers":["example"],"endpoint":"https://example.com","customHeaders":[{"name":"example","value":"example"}],"signingEnabled":true,"retryPolicy":{"enabled":true,"maxAttempts":1,"backoff":"exponential","initialDelaySeconds":1,"maxDelaySeconds":1,"retryOn":["timeout"]},"failureHandling":{"autoDisableAfter":1,"disableOnGone":true}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}use serde_json::json;use reqwest;
#[tokio::main]pub async fn main() { let url = "https://api.vendorica.com/v1/webhooks";
let payload = json!({ "name": "example", "triggers": ("example"), "endpoint": "https://example.com", "customHeaders": ( json!({ "name": "example", "value": "example" }) ), "signingEnabled": true, "retryPolicy": json!({ "enabled": true, "maxAttempts": 1, "backoff": "exponential", "initialDelaySeconds": 1, "maxDelaySeconds": 1, "retryOn": ("timeout") }), "failureHandling": json!({ "autoDisableAfter": 1, "disableOnGone": true }) });
let mut headers = reqwest::header::HeaderMap::new(); headers.insert("Authorization", "Bearer <token>".parse().unwrap()); headers.insert("Content-Type", "application/json".parse().unwrap());
let client = reqwest::Client::new(); let response = client.post(url) .headers(headers) .json(&payload) .send() .await;
let results = response.unwrap() .json::<serde_json::Value>() .await .unwrap();
dbg!(results);}curl --request POST \ --url https://api.vendorica.com/v1/webhooks \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "name": "example", "triggers": [ "example" ], "endpoint": "https://example.com", "customHeaders": [ { "name": "example", "value": "example" } ], "signingEnabled": true, "retryPolicy": { "enabled": true, "maxAttempts": 1, "backoff": "exponential", "initialDelaySeconds": 1, "maxDelaySeconds": 1, "retryOn": [ "timeout" ] }, "failureHandling": { "autoDisableAfter": 1, "disableOnGone": true } }'Creates one webhook entry (name + triggers + endpoint + optional custom headers + optional HMAC signing + optional retryPolicy / failureHandling; an omitted policy field takes its default). Every trigger must be available on the org’s plan (see GET /webhooks/triggers); the endpoint must be a public HTTPS URL (private / loopback / metadata addresses are rejected). When signingEnabled is true the response carries signingSecret exactly once. Subject to the plan’s webhook-count cap (409 when exceeded). A trigger name that is not in the catalogue is a 422 VALIDATION_ERROR naming triggers; a trigger that exists but is not on the plan is a 403. Either way the whole request is refused — no subset is created.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”Webhook configuration
object
object
object
object
Responses
Section titled “Responses”Success
object
object
object
object
object
object
object
Example
{ "success": true, "data": { "webhook": { "id": "53cbd165-50da-4525-8e31-fad24eaddee2", "organizationId": "8a0d4fa0-f4f4-4c06-81ac-dbdf5e1e19c1", "name": "string", "triggers": [ "string" ], "endpoint": "https://example.com", "status": "active", "apiVersion": "string", "customHeaders": [ { "name": "string", "valueHint": "string" } ], "signing": { "enabled": true, "secretHint": "string" }, "retryPolicy": { "enabled": true, "maxAttempts": 1, "backoff": "exponential", "initialDelaySeconds": 1, "maxDelaySeconds": 1, "retryOn": [ "timeout" ] }, "failureHandling": { "autoDisableAfter": 1, "disableOnGone": true }, "consecutiveFailures": 1, "lastSuccessAt": "2026-08-19T09:41:12.004Z", "lastFailureAt": "2026-08-19T09:41:12.004Z", "disabledReason": "string", "createdAt": "2026-08-19T09:41:12.004Z", "updatedAt": "2026-08-19T09:41:12.004Z" }, "signingSecret": "string" }, "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H", "message": "string"}Validation error
object
Example
{ "success": false, "error": "Bad request", "code": "BAD_REQUEST", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Unauthorized
object
Example
{ "success": false, "error": "Unauthorized", "code": "UNAUTHORIZED", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Forbidden — missing scope
object
Example
{ "success": false, "error": "Forbidden", "code": "FORBIDDEN", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Not found
object
Example
{ "success": false, "error": "Resource not found", "code": "NOT_FOUND", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Rate limit exceeded
object
Example
{ "success": false, "error": "Too many requests", "code": "TOO_MANY_REQUESTS", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}