Webhook endpoints tools
MCP tools for Webhook endpoints: webhook_endpoints_create, webhook_endpoints_delete, webhook_endpoints_get, webhook_endpoints_list, webhook_endpoints_rotate_secret, webhook_endpoints_test, webhook_endpoints_update.
webhook_endpoints_create: Create a webhook endpointwebhook_endpoints_delete: Delete a webhook endpointwebhook_endpoints_get: Get a webhook endpointwebhook_endpoints_list: List webhook endpointswebhook_endpoints_rotate_secret: Rotate a webhook endpoint's signing secretwebhook_endpoints_test: Send a test event to a webhook endpointwebhook_endpoints_update: Update a webhook endpoint
webhook_endpoints_create
Create a webhook endpoint. Operation webhook_endpoints.create · Brand level · permission webhooks:admin · risk tier security · since M4
Creates an endpoint that receives the brand's events in the request's mode: Ownrecord POSTs each event it
subscribes to as JSON, signed with the Ownrecord-Signature header (see the webhooks concept page).
eventslists event types from the catalogue that are delivered to webhooks, or["*"]for all of them, including types added later.urlmust be a publichttpsURL. In development and test (dev gate open),http://localhostworks too.- The response contains the signing secret in
secret. It is shown only once: it is stored encrypted and can't be read again. Rotate it withwebhook_endpoints.rotate_secretif you lose it.
A brand can have at most 16 endpoints per mode. Send a test event with webhook_endpoints.test.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: false · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
url | string | yes | The https URL Ownrecord POSTs events to, e.g. https://example.com/webhooks/ownrecord. (1–2048 characters) |
events | array of string | yes | Event types to receive (from the event catalogue), or ["*"] for every event of the brand. (1–100 items) |
description | string | no | (at most 500 characters) |
enabled | boolean | no | Start receiving events at once (default) or create it disabled. (default true) |
metadata | object | no | Your own key-value pairs (at most 50 keys). On updates the whole set is replaced. |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: A field is missing or malformed.webhook_url_not_allowed: The URL isn't https, or points at localhost, a private network or another refused address.webhook_event_type_invalid: An event type isn't in the catalogue or isn't delivered to brand webhook endpoints.webhook_endpoint_limit_reached: The brand already has 16 endpoints in this mode.permission_denied: You can't manage this brand's webhooks.livemode_not_allowed: You have no live-mode access, so you can't manage live webhooks.
Examples
An endpoint for order fulfilment
Arguments:
{
"url": "https://example.com/webhooks/ownrecord",
"events": ["customer.created", "checkout.session.completed"],
"description": "Order fulfilment",
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["customer.created", "checkout.session.completed"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-13T12:00:00.000Z",
"secret": "whsec_ExampleOnlyNotARealSigningSecret0000000"
}
Every event of the brand
Arguments:
{
"url": "https://example.com/webhooks/all",
"events": ["*"],
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/all",
"description": null,
"events": ["*"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-13T12:00:00.000Z",
"secret": "whsec_ExampleOnlyNotARealSigningSecret0000000"
}
webhook_endpoints_delete
Delete a webhook endpoint. Operation webhook_endpoints.delete · Brand level · permission webhooks:admin · risk tier security · since M4
Deletes an endpoint and its signing secret for good. Nothing more is sent to it: deliveries waiting for a
retry are canceled instead of sent. Its delivery log stays readable with webhook_deliveries.list. To pause
an endpoint instead, set enabled: false with webhook_endpoints.update.
Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (we_…) | yes | – |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
resource_not_found: No endpoint with this ID is visible to the request.version_conflict: The endpoint changed at the same time; retry.permission_denied: You can't manage this brand's webhooks.
Example
Delete an endpoint
Arguments:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"deleted": true
}
webhook_endpoints_get
Get a webhook endpoint. Operation webhook_endpoints.get · Brand level · permission webhooks:read · risk tier read · since M4
Returns one webhook endpoint of the brand in the request's mode: its URL, event types, whether it is enabled (and why not), and since when its deliveries have been failing. Never its signing secret.
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (we_…) | yes | – |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Read-only: changes nothing;
idempotency_keyis ignored.
Errors
resource_not_found: No endpoint with this ID is visible to the request.permission_denied: You can't see this brand's webhooks.
Example
An endpoint
Arguments:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["customer.created", "checkout.session.completed"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-13T12:00:00.000Z"
}
webhook_endpoints_list
List webhook endpoints. Operation webhook_endpoints.list · Brand level · permission webhooks:read · risk tier read · since M4
Lists the brand's webhook endpoints in the request's mode, newest first. Filter with enabled (true or
false) to find endpoints that were disabled, by you or after failing for 3 days.
Paginate with limit (1–100, default 10) and starting_after (the next_cursor of the previous page).
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
enabled | string | no | Only enabled (true) or disabled (false) endpoints. |
limit | integer | no | (1–100) |
starting_after | ID (we_…) | no | – |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Read-only: changes nothing;
idempotency_keyis ignored.
Errors
validation_failed: A filter or pagination value is malformed.permission_denied: You can't see this brand's webhooks.
Examples
The brand's endpoints
Arguments:
{
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
Result output:
{
"object": "list",
"data": [
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["customer.created", "checkout.session.completed"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-13T12:00:00.000Z"
}
],
"has_more": false,
"next_cursor": null
}
Endpoints that were disabled
Arguments:
{
"enabled": "false",
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
Result output:
{
"object": "list",
"data": [
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z1",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["customer.created", "checkout.session.completed"],
"enabled": false,
"disabledReason": "failing",
"disabledAt": "2026-10-14T09:30:00.000Z",
"failingSince": "2026-10-11T09:30:00.000Z",
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-14T09:30:00.000Z"
}
],
"has_more": false,
"next_cursor": null
}
webhook_endpoints_rotate_secret
Rotate a webhook signing secret. Operation webhook_endpoints.rotate_secret · Brand level · permission webhooks:admin · risk tier security · since M4
Replaces the endpoint's signing secret and returns the new one in secret. It is shown only once.
- Without
overlapSeconds(or with 0) the old secret stops at once: deliveries are signed with the new one only, and receivers still checking the old one fail until they switch (failed deliveries are retried). - With
overlapSeconds(up to 86400) the old secret keeps signing next to the new one untilpreviousSecretExpiresAt: each delivery carries twov1=signatures, and a receiver accepts it when either matches. Deploy the new secret, then let the overlap run out.
Rotating again ends an earlier overlap at once.
Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: false · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (we_…) | yes | – |
overlapSeconds | integer | no | Seconds the old secret keeps signing next to the new one (0–86400, default 0: it stops at once). During the overlap each delivery carries two v1 signatures. (0–86400) (default 0) |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: overlapSeconds isn't a whole number from 0 to 86400.resource_not_found: No endpoint with this ID is visible to the request.version_conflict: The endpoint changed at the same time; retry.permission_denied: You can't manage this brand's webhooks.
Example
Rotate with a one-hour overlap
Arguments:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"overlapSeconds": 3600,
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["customer.created", "checkout.session.completed"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": "2026-10-14T09:30:00.000Z",
"previousSecretExpiresAt": "2026-10-14T10:30:00.000Z",
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-14T09:30:00.000Z",
"secret": "whsec_ExampleOnlyNotARealSigningSecret0000000"
}
webhook_endpoints_test
Send a test webhook. Operation webhook_endpoints.test · Brand level · permission webhooks:write · risk tier write · since M4
Sends a webhook_endpoint.test event to this endpoint only, signed like every delivery, so you can check that
your receiver verifies Ownrecord-Signature and answers 2xx. It works for enabled and disabled endpoints.
The call returns the queued delivery at once; it is attempted right after (one attempt, no retries). Read the
outcome with webhook_deliveries.get: status, responseCode and the start of your response body. The test
event isn't part of the event feed, and endpoints can't subscribe to it.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: false · openWorldHint: true
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (we_…) | yes | – |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
resource_not_found: No endpoint with this ID is visible to the request.permission_denied: You can't send test webhooks for this brand.
Example
Send a test event
Arguments:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "whd_01m4tx5nj8emwbyf7y9vcf47z3",
"object": "webhook_delivery",
"endpointId": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"eventId": "evt_01m4tx5nj8emwbyf7y9vcf47z5",
"eventType": "webhook_endpoint.test",
"trigger": "test",
"redeliveryOf": null,
"status": "pending",
"attempt": 0,
"maxAttempts": 1,
"nextAttemptAt": "2026-10-14T10:30:00.000Z",
"responseCode": null,
"canceledReason": null,
"attempts": [],
"createdAt": "2026-10-14T10:30:00.000Z",
"updatedAt": "2026-10-14T10:30:00.000Z"
}
webhook_endpoints_update
Update a webhook endpoint. Operation webhook_endpoints.update · Brand level · permission webhooks:admin · risk tier security · since M4
Changes an endpoint's URL, event types, description or metadata, or disables or enables it. Send only the
fields to change; metadata replaces the whole set.
enabled: falsestops deliveries: event deliveries waiting for a retry are canceled instead of sent.enabled: trueresumes deliveries of new events, also after Ownrecord disabled the endpoint for failing for 3 days. Events that happened while it was disabled aren't sent again on their own: redeliver them withwebhook_deliveries.redeliver.
The signing secret doesn't change (use webhook_endpoints.rotate_secret).
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (we_…) | yes | – |
url | string | no | The https URL Ownrecord POSTs events to, e.g. https://example.com/webhooks/ownrecord. (1–2048 characters) |
events | array of string | no | Event types to receive (from the event catalogue), or ["*"] for every event of the brand. (1–100 items) |
description | string or null | no | A new description, or null to remove it. |
enabled | boolean | no | false stops deliveries (waiting retries are canceled); true resumes them. |
metadata | object | no | Your own key-value pairs (at most 50 keys). On updates the whole set is replaced. |
entity_id | ID (ent_…) | no | Optional: the brand's legal entity (ent_…); brand_id alone is enough. |
brand_id | ID (brd_…) | no | The brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Brand: pass
brand_idwith an organization or entity key; a brand key acts on its own brand. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: No field to change was sent, or a field is malformed.webhook_url_not_allowed: The new URL isn't allowed.webhook_event_type_invalid: An event type can't be delivered to brand endpoints.resource_not_found: No endpoint with this ID is visible to the request.version_conflict: The endpoint changed at the same time; retry.permission_denied: You can't manage this brand's webhooks.
Examples
Subscribe to more event types
Arguments:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"events": ["customer.created", "checkout.session.completed", "invoice.paid"],
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["checkout.session.completed", "customer.created", "invoice.paid"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-14T09:30:00.000Z"
}
Enable an endpoint again after it was disabled for failing
Arguments:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"enabled": true,
"brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "we_01m4tx5nj8emwbyf7y9vcf47z0",
"object": "webhook_endpoint",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"url": "https://example.com/webhooks/ownrecord",
"description": "Order fulfilment",
"events": ["customer.created", "checkout.session.completed"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failingSince": null,
"secretRotatedAt": null,
"previousSecretExpiresAt": null,
"metadata": {},
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-14T09:30:00.000Z"
}