Webhooks

Create an event webhook (10 per app at most)

Operation ID: createWebhook

POST
/webhooks

Adds an HTTPS endpoint. The URL must be https, on a public host and a standard port (400 invalid_request otherwise). The response includes the signing secret; this and rotateWebhookSecret are the only calls that return it, so store it now. 409 conflict when the app already has 10 endpoints. See Webhook events for what is sent and how to verify it.

Needs an API key with the manage scope.

Authorization

apiKey
headerAuthorizationBearer <oq_ followed by 43 letters and digits>

An Outqube API key, made in the app's settings. It belongs to one app and has the scope read, trigger or manage; a higher scope includes the lower ones. A revoked or expired key is a 401.

Request Body

application/json
  1. body
url*string

An https:// URL on a public host, standard port.

Length1 <= length <= 2048
events?array<never>|array<>

Event types to send, or ["*"] for all of them.

description?string

Your note on what the endpoint is for, up to 200 characters.

Lengthlength <= 200
Default""
enabled?boolean

Start sending straight away; default true.

Defaulttrue

Response Body

Created

application/json
  1. response

An endpoint with its signing secret, returned only on create and on rotate.

id*string

The endpoint's id.

Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
app_id*string

The app the endpoint belongs to.

Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
url*string

Where Outqube sends the events.

Formaturi
events*array<string>

Event types sent, or ["*"] for all of them.

description*string

Your note on what the endpoint is for; empty when not set.

enabled*boolean

Whether Outqube sends events to the endpoint.

disabled_reason*|

manual: switched off by a person. failures: 5 messages in a row ran out of retries. Null while enabled.

disabled_at*|

When it was switched off, or null.

consecutive_failures*integer

Messages in a row that ran out of retries; any delivery resets it.

Range-9007199254740991 <= value <= 9007199254740991
secret_hint*string

The last 4 characters of the signing secret.

previous_secret_expires_at*|

After a rotation, when the previous secret stops signing; else null.

created_at*string

When the endpoint was created.

Match^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
Formatdate-time
updated_at*string

When the endpoint last changed.

Match^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
Formatdate-time
secret*string

The signing secret, whsec_ + base64. Shown here and in settings.

Example Request
curl -X POST 'https://app.outqube.com/api/v1/webhooks' \  -H 'Content-Type: application/json' \  -d '{  "url": "https://ci.acme.test/hooks/outqube",  "events": [    "run.completed",    "run.cancelled"  ],  "description": "Post results to CI"}'
Example Response
{  "id": "d8f0b2a4-6c1e-4d73-9a5b-1c3e5a7b9d46",  "app_id": "9b1d2f4e-7a3c-4c58-9e0b-6f3a1d2c4b5a",  "url": "https://ci.acme.test/hooks/outqube",  "events": [    "run.completed",    "run.cancelled"  ],  "description": "Post results to CI",  "enabled": true,  "disabled_reason": null,  "disabled_at": null,  "consecutive_failures": 0,  "secret_hint": "k3Fz",  "previous_secret_expires_at": null,  "created_at": "2026-10-25T10:00:00.000Z",  "updated_at": "2026-10-25T10:00:00.000Z",  "secret": "whsec_c2FtcGxlLXdlYmhvb2sta2V5LW5vdC1hLXNlY3JldCE="}