Skip to content

Receive a webhook event

POST
/api/v1/webhooks/{source}
curl --request POST \
--url http://localhost:11044/api/v1/webhooks/example \
--header 'Content-Type: application/json' \
--header 'X-Embabel-Api-Key: <X-Embabel-Api-Key>' \
--data '"example"'

Receives a JSON payload from an external system. If the source has a configured action, the event is processed immediately; otherwise the payload type is inferred and the event is queued until the user configures an action via the UI. Provider URL-validation handshakes (such as an endpoint.url_validation event) are answered synchronously with the scheme-specific response body instead of the processed/queued shape.

source
required
string

Source identifier for the webhook (e.g., ‘github’, ‘stripe’)

The provider’s payload: a single JSON event object, or an array of them for providers that batch. Taken as RAW BYTES rather than a parsed type because the signature is computed over the bytes exactly as sent — reserializing a parsed body would change them and every signature check would fail. An empty body is read as an empty object. Non-object elements of an array are ignored rather than refused.

Media typeapplication/json
string format: byte

Example generated

example

Event processed successfully, or handshake response body

Media type*/*
One of:

A batch of events, counted by outcome. Answers 200 when any ran, 202 when any queued, and 500 only when EVERY event failed

object
count
required

How many events the body carried

integer format: int32
errors
required

How many threw. A partial failure still answers 200 or 202, so a caller must read this rather than the status code

integer format: int32
processed
required

How many were dispatched and ran

integer format: int32
queued
required

How many were queued against an unconfigured source

integer format: int32
status
required

Always batch

string

Event queued (unknown source, awaiting configuration)

Media type*/*
One of:

A batch of events, counted by outcome. Answers 200 when any ran, 202 when any queued, and 500 only when EVERY event failed

object
count
required

How many events the body carried

integer format: int32
errors
required

How many threw. A partial failure still answers 200 or 202, so a caller must read this rather than the status code

integer format: int32
processed
required

How many were dispatched and ran

integer format: int32
queued
required

How many were queued against an unconfigured source

integer format: int32
status
required

Always batch

string

Body is not valid JSON, or not an object or array of objects

Media type*/*

The request was refused: 400 for a body that would not parse, 500 for a dispatch that threw

object
message
required

What went wrong, written to be shown

string
status
required

Always error

string

Signature verification or tenant resolution failed

Media type*/*

The caller was not admitted: signature verification, tenant resolution or source installation failed

object
reason
required

Which check refused it. Deliberately coarse — a precise reason would tell an attacker which half of the credential was wrong

string
status
required

Always unauthorized

string

Every event in the batch threw. A PARTIAL failure answers 200 or 202 with a non-zero errors count instead

Media type*/*
One of:

The request was refused: 400 for a body that would not parse, 500 for a dispatch that threw

object
message
required

What went wrong, written to be shown

string
status
required

Always error

string