# Webhooks

## List webhook event types[​](#list-webhook-event-types "Direct link to List webhook event types")

GET/api/v1/webhooks/event-types

Returns the event types a webhook can subscribe to. `webhook.test` is not listed: it is sent only by the test route and reaches that webhook whatever its events.

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

`object`stringrequired

`data`arrayrequired

Show child attributes

`type`stringrequired

`description`stringrequired

`since`stringrequired

The API version that added the type

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/event-types \

  -X GET \

  -H 'Authorization: Bearer mob_...'
```

Response

200401

The event types

```
{

  "object": "list",

  "data": [

    {

      "type": "allocation.released",

      "description": "string",

      "since": "string"

    }

  ]

}
```

## List webhooks[​](#list-webhooks "Direct link to List webhooks")

GET/api/v1/webhooks

Returns every webhook of the organization, newest first. Not paginated: the plan caps an organization at 10 (Team) or 25 (Enterprise) webhooks. Any member can read.

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

`object`stringrequired

`data`arrayrequired

Show child attributes

`id`string · uuidrequired

`object`stringrequired

`url`string · urirequired

`description`stringrequirednullable

`events`array of stringrequired

\`\*\`, exact event types, or \`resource.\*\` (e.g. \`allocation.\*\`). Sorted, no duplicates.

`status`stringrequired

`disabledReason`stringrequirednullable

Why the webhook is disabled: by a user, automatically after failing for days, or because its organization was deleted.

`secretSuffix`stringrequired

The last characters of the signing secret, to tell secrets apart.

`organization`string · uuidrequired

`createdAt`string · date-timerequired

`updatedAt`string · date-timerequired

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks \

  -X GET \

  -H 'Authorization: Bearer mob_...'
```

Response

200401404

The webhooks

```
{

  "object": "list",

  "data": [

    {

      "id": "string",

      "object": "webhook",

      "url": "string",

      "description": "string",

      "events": [

        "string"

      ],

      "status": "enabled",

      "disabledReason": "user",

      "secretSuffix": "string",

      "organization": "string",

      "createdAt": "2026-01-01T00:00:00Z",

      "updatedAt": "2026-01-01T00:00:00Z"

    }

  ]

}
```

## Create a webhook[​](#create-webhook "Direct link to Create a webhook")

POST/api/v1/webhooks

Creates an enabled webhook and returns its signing secret. The secret is returned here and by rotate-secret only; later reads show its last characters in `secretSuffix`. The URL must be https and resolve to a public address. Admins only.

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Body parameters

`url`string · urirequired

https, no credentials, no fragment, resolving to a public address. A Slack incoming webhook (https\://hooks.slack.com/...) receives each event as a Slack message instead of the event JSON.

`description`string

`events`array of stringrequired

\`\*\`, event types from GET /api/v1/webhooks/event-types, or \`resource.\*\`.

Returns

`id`string · uuidrequired

`object`stringrequired

`url`string · urirequired

`description`stringrequirednullable

`events`array of stringrequired

\`\*\`, exact event types, or \`resource.\*\` (e.g. \`allocation.\*\`). Sorted, no duplicates.

`status`stringrequired

`disabledReason`stringrequirednullable

Why the webhook is disabled: by a user, automatically after failing for days, or because its organization was deleted.

`secretSuffix`stringrequired

The last characters of the signing secret, to tell secrets apart.

`organization`string · uuidrequired

`createdAt`string · date-timerequired

`updatedAt`string · date-timerequired

`secret`stringrequired

The signing secret, \`whsec\_\` and base64. Shown once.

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks \

  -X POST \

  -H 'Authorization: Bearer mob_...' \

  -H 'Content-Type: application/json' \

  -d '{"url":"string","description":"string","events":["string"]}'
```

Response

201400401402403404503

The webhook, with its secret

```
{

  "id": "string",

  "object": "webhook",

  "url": "string",

  "description": "string",

  "events": [

    "string"

  ],

  "status": "enabled",

  "disabledReason": "user",

  "secretSuffix": "string",

  "organization": "string",

  "createdAt": "2026-01-01T00:00:00Z",

  "updatedAt": "2026-01-01T00:00:00Z",

  "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"

}
```

## Get a webhook[​](#get-webhook "Direct link to Get a webhook")

GET/api/v1/webhooks/{webhookId}

Returns one webhook. Another organization's webhook is 404. Any member can read.

Path parameters

`webhookId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

`id`string · uuidrequired

`object`stringrequired

`url`string · urirequired

`description`stringrequirednullable

`events`array of stringrequired

\`\*\`, exact event types, or \`resource.\*\` (e.g. \`allocation.\*\`). Sorted, no duplicates.

`status`stringrequired

`disabledReason`stringrequirednullable

Why the webhook is disabled: by a user, automatically after failing for days, or because its organization was deleted.

`secretSuffix`stringrequired

The last characters of the signing secret, to tell secrets apart.

`organization`string · uuidrequired

`createdAt`string · date-timerequired

`updatedAt`string · date-timerequired

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId} \

  -X GET \

  -H 'Authorization: Bearer mob_...'
```

Response

200401404

The webhook

```
{

  "id": "string",

  "object": "webhook",

  "url": "string",

  "description": "string",

  "events": [

    "string"

  ],

  "status": "enabled",

  "disabledReason": "user",

  "secretSuffix": "string",

  "organization": "string",

  "createdAt": "2026-01-01T00:00:00Z",

  "updatedAt": "2026-01-01T00:00:00Z"

}
```

## Update a webhook[​](#update-webhook "Direct link to Update a webhook")

PATCH/api/v1/webhooks/{webhookId}

Changes the given fields only. `status: enabled` also clears an automatic disable and its failure streak. While webhooks are not in the plan, only `\{"status": "disabled"\}` is accepted. Admins only.

Path parameters

`webhookId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Body parameters

`url`string · uri

`description`string

`events`array of string

`status`string

Returns

`id`string · uuidrequired

`object`stringrequired

`url`string · urirequired

`description`stringrequirednullable

`events`array of stringrequired

\`\*\`, exact event types, or \`resource.\*\` (e.g. \`allocation.\*\`). Sorted, no duplicates.

`status`stringrequired

`disabledReason`stringrequirednullable

Why the webhook is disabled: by a user, automatically after failing for days, or because its organization was deleted.

`secretSuffix`stringrequired

The last characters of the signing secret, to tell secrets apart.

`organization`string · uuidrequired

`createdAt`string · date-timerequired

`updatedAt`string · date-timerequired

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId} \

  -X PATCH \

  -H 'Authorization: Bearer mob_...' \

  -H 'Content-Type: application/json' \

  -d '{"url":"string","description":"string","events":["string"],"status":"enabled"}'
```

Response

200400401402403404

The updated webhook

```
{

  "id": "string",

  "object": "webhook",

  "url": "string",

  "description": "string",

  "events": [

    "string"

  ],

  "status": "enabled",

  "disabledReason": "user",

  "secretSuffix": "string",

  "organization": "string",

  "createdAt": "2026-01-01T00:00:00Z",

  "updatedAt": "2026-01-01T00:00:00Z"

}
```

## Delete a webhook[​](#delete-webhook "Direct link to Delete a webhook")

DELETE/api/v1/webhooks/{webhookId}

Deletes the webhook. Its pending messages are canceled and are not sent; its message history is deleted with it. Allowed while webhooks are not in the plan. Admins only.

Path parameters

`webhookId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId} \

  -X DELETE \

  -H 'Authorization: Bearer mob_...'
```

Response

204401403404

Deleted

```
// No response body
```

## Rotate a webhook's secret[​](#rotate-webhook-secret "Direct link to Rotate a webhook's secret")

POST/api/v1/webhooks/{webhookId}/rotate-secret

Replaces the signing secret and returns the new one. During `expireCurrentIn` seconds (default 86400) each message carries two signatures, new secret first, so receivers can switch without dropping messages. `0` stops the old secret, and any previous one, now. A second rotation while a previous secret is still valid is refused unless `expireCurrentIn` is 0. Admins only.

Path parameters

`webhookId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Body parameters

`expireCurrentIn`integer

Seconds the old secret keeps signing. 0 stops it now.

Returns

`id`string · uuidrequired

`object`stringrequired

`url`string · urirequired

`description`stringrequirednullable

`events`array of stringrequired

\`\*\`, exact event types, or \`resource.\*\` (e.g. \`allocation.\*\`). Sorted, no duplicates.

`status`stringrequired

`disabledReason`stringrequirednullable

Why the webhook is disabled: by a user, automatically after failing for days, or because its organization was deleted.

`secretSuffix`stringrequired

The last characters of the signing secret, to tell secrets apart.

`organization`string · uuidrequired

`createdAt`string · date-timerequired

`updatedAt`string · date-timerequired

`secret`stringrequired

The signing secret, \`whsec\_\` and base64. Shown once.

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId}/rotate-secret \

  -X POST \

  -H 'Authorization: Bearer mob_...' \

  -H 'Content-Type: application/json' \

  -d '{"expireCurrentIn":86400}'
```

Response

200400401402403404409503

The webhook, with its new secret

```
{

  "id": "string",

  "object": "webhook",

  "url": "string",

  "description": "string",

  "events": [

    "string"

  ],

  "status": "enabled",

  "disabledReason": "user",

  "secretSuffix": "string",

  "organization": "string",

  "createdAt": "2026-01-01T00:00:00Z",

  "updatedAt": "2026-01-01T00:00:00Z",

  "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"

}
```

## Send a test event[​](#send-webhook-test "Direct link to Send a test event")

POST/api/v1/webhooks/{webhookId}/test

Sends a `webhook.test` event to this webhook only, even if it is disabled or its events do not match. Returns the queued message; follow it on the messages routes. At most 10 per minute per webhook. Admins only.

Path parameters

`webhookId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

One event's delivery to one webhook. Admins also get attemptCount, lastResponseStatus, nextAttemptAt and event; the single-message GET adds payload and attempts.

`id`string · uuidrequired

Sent as the \`webhook-id\` header; the same on every attempt and resend.

`object`stringrequired

`webhook`string · uuidrequired

`type`stringrequired

The event type

`status`stringrequired

`createdAt`string · date-timerequired

`attemptCount`integer

Admins only

`lastResponseStatus`integernullable

Admins only

`nextAttemptAt`string · date-timenullable

Admins only; null unless pending

`event`string · uuid

Admins only

`payload`object

Admins only, single-message GET: the body as sent

`attempts`array

Admins only, single-message GET, oldest first

Show child attributes

`id`string · uuidrequired

`object`stringrequired

`attemptedAt`string · date-timerequired

`responseStatus`integerrequirednullable

null when no response arrived

`durationMs`integerrequired

`error`stringrequirednullable

Why no response arrived, e.g. a timeout

`responseBody`stringrequirednullable

The first 1 KB of the response body

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId}/test \

  -X POST \

  -H 'Authorization: Bearer mob_...'
```

Response

202401402403404429503

The queued message

```
{

  "id": "string",

  "object": "webhook_message",

  "webhook": "string",

  "type": "string",

  "status": "pending",

  "createdAt": "2026-01-01T00:00:00Z",

  "attemptCount": 0,

  "lastResponseStatus": 0,

  "nextAttemptAt": "2026-01-01T00:00:00Z",

  "event": "string",

  "payload": {},

  "attempts": [

    {

      "id": "string",

      "object": "webhook_attempt",

      "attemptedAt": "2026-01-01T00:00:00Z",

      "responseStatus": 0,

      "durationMs": 0,

      "error": "string",

      "responseBody": "string"

    }

  ]

}
```

## List a webhook's messages[​](#list-webhook-messages "Direct link to List a webhook's messages")

GET/api/v1/webhooks/{webhookId}/messages

Returns the webhook's messages, newest first. Members see id, type, status and time; admins also see the delivery counters and the event id. Messages are kept for 30 days.

Path parameters

`webhookId`string · uuidrequired

Query parameters

`status`string

`type`string

An event type, or \`resource.\*\`

`createdAfter`string · date-time

`createdBefore`string · date-time

`limit`integer

Page size, 1 to 100. Default 25.

`cursor`string

\`nextCursor\` from the previous page. Opaque.

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

`object`stringrequired

`data`arrayrequired

Show child attributes

`id`string · uuidrequired

Sent as the \`webhook-id\` header; the same on every attempt and resend.

`object`stringrequired

`webhook`string · uuidrequired

`type`stringrequired

The event type

`status`stringrequired

`createdAt`string · date-timerequired

`attemptCount`integer

Admins only

`lastResponseStatus`integernullable

Admins only

`nextAttemptAt`string · date-timenullable

Admins only; null unless pending

`event`string · uuid

Admins only

`payload`object

Admins only, single-message GET: the body as sent

`attempts`array

Admins only, single-message GET, oldest first

Show child attributes

`id`string · uuidrequired

`object`stringrequired

`attemptedAt`string · date-timerequired

`responseStatus`integerrequirednullable

null when no response arrived

`durationMs`integerrequired

`error`stringrequirednullable

Why no response arrived, e.g. a timeout

`responseBody`stringrequirednullable

The first 1 KB of the response body

`nextCursor`string

Pass as \`cursor\` for the next page. Absent on the last page.

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId}/messages \

  -X GET \

  -H 'Authorization: Bearer mob_...'
```

Response

200400401404

A page of messages

```
{

  "object": "list",

  "data": [

    {

      "id": "string",

      "object": "webhook_message",

      "webhook": "string",

      "type": "string",

      "status": "pending",

      "createdAt": "2026-01-01T00:00:00Z",

      "attemptCount": 0,

      "lastResponseStatus": 0,

      "nextAttemptAt": "2026-01-01T00:00:00Z",

      "event": "string",

      "payload": {},

      "attempts": [

        {

          "id": "string",

          "object": "webhook_attempt",

          "attemptedAt": "2026-01-01T00:00:00Z",

          "responseStatus": 0,

          "durationMs": 0,

          "error": "string",

          "responseBody": "string"

        }

      ]

    }

  ],

  "nextCursor": "string"

}
```

## Get a webhook message[​](#get-webhook-message "Direct link to Get a webhook message")

GET/api/v1/webhooks/{webhookId}/messages/{messageId}

Returns one message. Admins also get the signed payload and every attempt, oldest first.

Path parameters

`webhookId`string · uuidrequired

`messageId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

One event's delivery to one webhook. Admins also get attemptCount, lastResponseStatus, nextAttemptAt and event; the single-message GET adds payload and attempts.

`id`string · uuidrequired

Sent as the \`webhook-id\` header; the same on every attempt and resend.

`object`stringrequired

`webhook`string · uuidrequired

`type`stringrequired

The event type

`status`stringrequired

`createdAt`string · date-timerequired

`attemptCount`integer

Admins only

`lastResponseStatus`integernullable

Admins only

`nextAttemptAt`string · date-timenullable

Admins only; null unless pending

`event`string · uuid

Admins only

`payload`object

Admins only, single-message GET: the body as sent

`attempts`array

Admins only, single-message GET, oldest first

Show child attributes

`id`string · uuidrequired

`object`stringrequired

`attemptedAt`string · date-timerequired

`responseStatus`integerrequirednullable

null when no response arrived

`durationMs`integerrequired

`error`stringrequirednullable

Why no response arrived, e.g. a timeout

`responseBody`stringrequirednullable

The first 1 KB of the response body

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId}/messages/{messageId} \

  -X GET \

  -H 'Authorization: Bearer mob_...'
```

Response

200401404

The message

```
{

  "id": "string",

  "object": "webhook_message",

  "webhook": "string",

  "type": "string",

  "status": "pending",

  "createdAt": "2026-01-01T00:00:00Z",

  "attemptCount": 0,

  "lastResponseStatus": 0,

  "nextAttemptAt": "2026-01-01T00:00:00Z",

  "event": "string",

  "payload": {},

  "attempts": [

    {

      "id": "string",

      "object": "webhook_attempt",

      "attemptedAt": "2026-01-01T00:00:00Z",

      "responseStatus": 0,

      "durationMs": 0,

      "error": "string",

      "responseBody": "string"

    }

  ]

}
```

## Resend a webhook message[​](#resend-webhook-message "Direct link to Resend a webhook message")

POST/api/v1/webhooks/{webhookId}/messages/{messageId}/resend

Sends the message again with the same id and payload. A succeeded or failed message gets one more attempt; a pending one is attempted now instead of at its next retry. At most 20 resends per message, within 29 days of the event, and 60 per minute per webhook. Admins only.

Path parameters

`webhookId`string · uuidrequired

`messageId`string · uuidrequired

Header parameters

`X-Organization-Id`string

Selects which of the caller's organizations the request acts on. When omitted, the caller's default organization is used.

Returns

One event's delivery to one webhook. Admins also get attemptCount, lastResponseStatus, nextAttemptAt and event; the single-message GET adds payload and attempts.

`id`string · uuidrequired

Sent as the \`webhook-id\` header; the same on every attempt and resend.

`object`stringrequired

`webhook`string · uuidrequired

`type`stringrequired

The event type

`status`stringrequired

`createdAt`string · date-timerequired

`attemptCount`integer

Admins only

`lastResponseStatus`integernullable

Admins only

`nextAttemptAt`string · date-timenullable

Admins only; null unless pending

`event`string · uuid

Admins only

`payload`object

Admins only, single-message GET: the body as sent

`attempts`array

Admins only, single-message GET, oldest first

Show child attributes

`id`string · uuidrequired

`object`stringrequired

`attemptedAt`string · date-timerequired

`responseStatus`integerrequirednullable

null when no response arrived

`durationMs`integerrequired

`error`stringrequirednullable

Why no response arrived, e.g. a timeout

`responseBody`stringrequirednullable

The first 1 KB of the response body

Request

```
curl https://app.mobilenext.ai/api/v1/webhooks/{webhookId}/messages/{messageId}/resend \

  -X POST \

  -H 'Authorization: Bearer mob_...'
```

Response

202401402403404409410429503

The message, pending

```
{

  "id": "string",

  "object": "webhook_message",

  "webhook": "string",

  "type": "string",

  "status": "pending",

  "createdAt": "2026-01-01T00:00:00Z",

  "attemptCount": 0,

  "lastResponseStatus": 0,

  "nextAttemptAt": "2026-01-01T00:00:00Z",

  "event": "string",

  "payload": {},

  "attempts": [

    {

      "id": "string",

      "object": "webhook_attempt",

      "attemptedAt": "2026-01-01T00:00:00Z",

      "responseStatus": 0,

      "durationMs": 0,

      "error": "string",

      "responseBody": "string"

    }

  ]

}
```
