Webhook Endpoints
The TapTree Webhook Endpoints API gives you full programmatic control over the static webhook endpoints registered to your organization, scoped to the environment bound to the API key you authenticate with. Use these endpoints to provision receivers from your infrastructure-as-code pipeline, rotate signing secrets on a schedule, or surface endpoint state in your own dashboards.
The same surface is available via the TapTree Dashboard under Entwickler → Webhooks — see Static Webhook Endpoints for the signing-secret design and signature-verification recipe. API and dashboard are interchangeable: every endpoint created here shows up in the dashboard immediately and vice versa.
Discover the Webhook Endpoints resource using Postman:
TapTree Postman CollectionEndpoints
Create a webhook endpoint
Register a new static webhook endpoint and receive the one-shot signing-secret reveal.
List webhook endpoints
Retrieve every webhook endpoint configured for the api-key’s environment.
Update a webhook endpoint
Patch mutable fields (name, description, url, event_types, state). Uses OCC via If-Match.
Rotate a webhook endpoint signing secret
Generate a new signing secret with optional grace window and receive the one-shot reveal.
Delete a webhook endpoint
Soft-delete a webhook endpoint. No future events are delivered; audit history is retained.
Authentication
All endpoints use v2 API keys. Required scopes:
- Name
webhooks:read- Type
- scope
- Description
Required for
GET /v1/webhooks(list) andGET /v1/webhooks/:id(retrieve).
- Name
webhooks:write- Type
- scope
- Description
Required for
POST /v1/webhooks(create),PATCH /v1/webhooks/:id(update) andDELETE /v1/webhooks/:id.
- Name
webhooks:rotate_secret- Type
- scope
- Description
Required for
POST /v1/webhooks/:id/rotate-secret. Separate fromwebhooks:writeso an automation key can rotate secrets without being able to also changeurlorevent_types.
Mint a key with the relevant scopes in the dashboard under Entwickler → API-Schlüssel before calling.
Authentication header
Authorization: Bearer tt_live_pri_…
A key bound to the Live environment can only see and mutate live endpoints; a key bound to a Sandbox environment is scoped to that sandbox. There is no env query parameter and no fallback — the environment is server-bound at mint time. If you need both, mint one key per environment.
The webhook endpoint model
The webhook endpoint model describes a static destination registered for your organization plus the operational state we track for it (failure counter, circuit-breaker state, last successful delivery timestamp).
Core attributes
- Name
id- Type
- string
- Description
Unique identifier for the webhook endpoint.
- Name
environment_id- Type
- string
- Description
Identifier for the environment the endpoint is scoped to. Matches the environment bound to the calling API key.
- Name
acceptor_id- Type
- string
- Description
Identifier for the payment acceptor the endpoint is scoped to, or
nullif the endpoint receives events for every acceptor in your organization.
- Name
name- Type
- string
- Description
Operator-supplied label for the endpoint. 1–255 characters.
- Name
description- Type
- string
- Description
Optional longer description of what the endpoint is for. Up to 2000 characters; empty string when unset.
- Name
url- Type
- string
- Description
HTTPS URL the endpoint delivers events to.
http://URLs are rejected at create time outside of explicit dev environments — see URL requirements.
- Name
transport- Type
- string
- Description
Transport channel used to deliver the event. Currently always
http— payloads are sent over HTTPS via a standardPOSTto the endpoint'surl. The field is reserved for future transports (e.g. queue-based fan-out).
- Name
event_types- Type
- array
- Description
Event-type subscriptions for the endpoint. Each entry is either a concrete event-type token (
transactions.payment.paid) or one of the wildcard forms (transactions.payment.*,transactions.*,*) documented in Static Endpoints → Configure step 3. 1–64 entries, each up to 128 characters.
- Name
state- Type
- string
- Description
Current lifecycle state of the endpoint.
Possible values:
activepausedauto_disabledauto_disabledindicates the delivery circuit breaker has tripped after consecutive failures — events are paused untiltripped_untilpasses or the endpoint is re-enabled.pausedis a manual operator action and is the only value that can be set via the API (alongsideactive). Soft-deleted endpoints are filtered out of every response.
- Name
signing_algo- Type
- string
- Description
Algorithm used to sign delivered payloads. Currently always
hmac-sha256-v2. See Webhook Signing Secrets for the verification recipe.
- Name
consecutive_failures- Type
- integer
- Description
Count of consecutive delivery failures since the last successful 2xx. Resets to
0on success.
- Name
last_success_at- Type
- datetime
- Description
Timestamp of the most recent successful (
2xx) delivery, in ISO 8601 format.nulluntil the first successful delivery.
- Name
tripped_until- Type
- datetime
- Description
Timestamp until which the circuit breaker keeps deliveries paused.
nullwhenstateis notauto_disabled.
- Name
row_version- Type
- integer
- Description
Optimistic-concurrency counter incremented on every mutation. Send the current value in the
If-Matchheader onPATCH,DELETEand rotate-secret calls to guarantee you’re modifying the row you think you are.
- Name
created_at- Type
- datetime
- Description
Timestamp of when the endpoint was created, in ISO 8601 format.
- Name
updated_at- Type
- datetime
- Description
Timestamp of the most recent mutation (configuration change, state transition, signing-secret rotation), in ISO 8601 format.
Response object
{
"object": "webhook_endpoint",
"id": "1252416694177497000",
"environment_id": "8419223344005061000",
"acceptor_id": "5028111769322011000",
"name": "Orders production",
"description": "Routes payment + refund events to order-service.",
"url": "https://api.example.com/webhooks/taptree",
"transport": "http",
"event_types": [
"transactions.payment.*",
"transactions.refund.refunded"
],
"state": "active",
"signing_algo": "hmac-sha256-v2",
"consecutive_failures": 0,
"last_success_at": "2026-05-19T09:14:02.118Z",
"tripped_until": null,
"row_version": 3,
"created_at": "2026-04-12T11:02:33.001Z",
"updated_at": "2026-05-04T16:42:11.044Z"
}
Create a webhook endpoint
Register a new webhook endpoint and receive a one-shot reveal of the freshly minted plaintext signing secret. The response is the only place the plaintext ever leaves our infrastructure — capture plaintext_secret and public_secret_id immediately. The secret itself is stored envelope-encrypted at rest and cannot be re-fetched. If you lose it, rotate.
Requires the webhooks:write scope.
Request body
- Name
name- Type
- string
- Description
Display label, 1–255 characters. Shown in the dashboard list view.
- Name
url- Type
- string
- Description
Destination URL. Must be
https://(orhttp://only in explicitly-enabled dev environments). 1–2048 characters.
- Name
event_types- Type
- array
- Description
Non-empty array of event-type tokens or wildcards. 1–64 entries.
- Name
description- Type
- string
- Description
Optional, up to 2000 characters. Omit or pass an empty string when unused.
- Name
acceptor_id- Type
- string
- Description
Optional bigint string. Required only if the calling API key is not bound to a specific acceptor; otherwise the bound acceptor is used and supplying a different value rejects with
400.
- Name
signing_algo- Type
- string
- Description
Optional. Currently must be omitted or
hmac-sha256-v2— kept explicit so future algorithm bumps stay opt-in.
Possible response statuses
- Name
201 Created- Type
- status
- Description
The endpoint was created. Body is the endpoint object plus
plaintext_secretandpublic_secret_idfor the one-shot reveal.
- Name
400 Bad Request- Type
- status
- Description
Body validation failed (missing field, value out of range, malformed URL, etc.). The response
detailfield carries a human-readable reason; tokens, secrets and PII are never echoed.
- Name
401 Unauthorized- Type
- status
- Description
The bearer token is missing, malformed, or not active.
- Name
403 Forbidden- Type
- status
- Description
The key authenticated but does not carry the
webhooks:writescope.
- Name
409 Conflict- Type
- status
- Description
An endpoint with the same
urlalready exists in this environment. Either reuse it, choose a different URL, or delete the conflicting endpoint first.
Request
curl -X POST https://api.taptree.org/v1/webhooks \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Orders production",
"url": "https://api.example.com/webhooks/taptree",
"event_types": ["transactions.payment.*", "transactions.refund.refunded"],
"description": "Routes payment + refund events to order-service."
}'
Example response
{
"object": "webhook_endpoint",
"id": "1252416694177497000",
"environment_id": "8419223344005061000",
"acceptor_id": "5028111769322011000",
"name": "Orders production",
"description": "Routes payment + refund events to order-service.",
"url": "https://api.example.com/webhooks/taptree",
"transport": "http",
"event_types": [
"transactions.payment.*",
"transactions.refund.refunded"
],
"state": "active",
"signing_algo": "hmac-sha256-v2",
"consecutive_failures": 0,
"last_success_at": null,
"tripped_until": null,
"row_version": 1,
"created_at": "2026-05-19T12:02:33.001Z",
"updated_at": "2026-05-19T12:02:33.001Z",
"public_secret_id": "whsec_id_3a8b29",
"plaintext_secret": "whsec_aa11bb22cc33dd44ee55ff66aa77bb88cc99dd00ee11ff2233445566778899"
}
List webhook endpoints
Retrieve every webhook endpoint configured for the environment bound to your API key. There is no pagination today because organizations rarely operate more than a handful of static endpoints; if your operating model changes, contact support.
Requires the webhooks:read scope. Soft-deleted endpoints are filtered out at the server. Results are returned sorted by created_at descending, with id as a stable tie-breaker. An environment with no configured endpoints returns { "object": "list", "data": [] }.
Possible response statuses
- Name
200 OK- Type
- status
- Description
The list was returned successfully.
datais an array (possibly empty) of endpoint objects.
- Name
401 Unauthorized- Type
- status
- Description
Missing or invalid bearer token.
- Name
403 Forbidden- Type
- status
- Description
The key authenticated but does not carry the
webhooks:readscope.
- Name
503 Service Unavailable- Type
- status
- Description
Resolver not yet provisioned (transient during a rolling deploy). Retry with exponential backoff.
Request
curl https://api.taptree.org/v1/webhooks \
-H "Authorization: Bearer {token}"
Example response
{
"object": "list",
"data": [
{
"id": "1252416694177497000",
"environment_id": "8419223344005061000",
"acceptor_id": "5028111769322011000",
"name": "Orders production",
"description": "Routes payment + refund events to order-service.",
"url": "https://api.example.com/webhooks/taptree",
"transport": "http",
"event_types": [
"transactions.payment.*",
"transactions.refund.refunded"
],
"state": "active",
"signing_algo": "hmac-sha256-v2",
"consecutive_failures": 0,
"last_success_at": "2026-05-19T09:14:02.118Z",
"tripped_until": null,
"row_version": 3,
"created_at": "2026-04-12T11:02:33.001Z",
"updated_at": "2026-05-04T16:42:11.044Z"
}
]
}
Retrieve a webhook endpoint
Fetch a single webhook endpoint by its id. Returns the same shape as the list response, plus the current row_version you’ll need to pass back in If-Match for subsequent mutations.
Requires the webhooks:read scope.
Possible response statuses
- Name
200 OK- Type
- status
- Description
The endpoint object.
- Name
401 Unauthorized- Type
- status
- Description
Missing or invalid bearer token.
- Name
403 Forbidden- Type
- status
- Description
Scope missing.
- Name
404 Not Found- Type
- status
- Description
No endpoint with that id exists in the calling key’s environment, or the endpoint was soft-deleted. The 404 also covers "exists-in-another-environment" cases so existence across environment boundaries is not leaked.
Request
curl https://api.taptree.org/v1/webhooks/1252416694177497000 \
-H "Authorization: Bearer {token}"
Example response
{
"object": "webhook_endpoint",
"id": "1252416694177497000",
"environment_id": "8419223344005061000",
"acceptor_id": "5028111769322011000",
"name": "Orders production",
"description": "Routes payment + refund events to order-service.",
"url": "https://api.example.com/webhooks/taptree",
"transport": "http",
"event_types": [
"transactions.payment.*",
"transactions.refund.refunded"
],
"state": "active",
"signing_algo": "hmac-sha256-v2",
"consecutive_failures": 0,
"last_success_at": "2026-05-19T09:14:02.118Z",
"tripped_until": null,
"row_version": 3,
"created_at": "2026-04-12T11:02:33.001Z",
"updated_at": "2026-05-04T16:42:11.044Z"
}
Update a webhook endpoint
Patch mutable fields on an existing endpoint. Send only the fields you want to change. Uses optimistic concurrency: pass the endpoint’s current row_version in If-Match; a stale value rejects with 409.
Requires the webhooks:write scope.
Request headers
- Name
If-Match- Type
- header
- Description
The current
row_versionof the endpoint as a quoted strong ETag, e.g.If-Match: "3". Missing →428 Precondition Required. Stale →409 Conflictwith the current value in the response body so you can refetch + retry.
Mutable fields
- Name
name- Type
- string
- Description
1–255 characters.
- Name
description- Type
- string
- Description
Up to 2000 characters.
- Name
url- Type
- string
- Description
HTTPS URL, 1–2048 characters.
- Name
event_types- Type
- array
- Description
Non-empty array, 1–64 entries, each ≤128 characters.
- Name
state- Type
- string
- Description
activeorpaused. The breaker-drivenauto_disabledstate is server-managed and cannot be set directly.
acceptor_id, signing_algo and identifiers are not patchable — create a new endpoint if you need a different acceptor binding.
Possible response statuses
- Name
200 OK- Type
- status
- Description
The patched endpoint object with the new
row_versionvalue.
- Name
400 Bad Request- Type
- status
- Description
Body validation failed, or no mutable field was supplied.
- Name
401 Unauthorized- Type
- status
- Description
Missing or invalid bearer token.
- Name
403 Forbidden- Type
- status
- Description
Scope missing.
- Name
404 Not Found- Type
- status
- Description
Endpoint id not visible to this key.
- Name
409 Conflict- Type
- status
- Description
row_versionmismatch — somebody else mutated the row between your read and write. Body carriescurrent_row_versionfor the retry.
- Name
428 Precondition Required- Type
- status
- Description
If-Matchheader missing.
Request
curl -X PATCH https://api.taptree.org/v1/webhooks/1252416694177497000 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-H 'If-Match: "3"' \
-d '{"event_types": ["transactions.payment.*"], "state": "paused"}'
Example response
{
"object": "webhook_endpoint",
"id": "1252416694177497000",
"environment_id": "8419223344005061000",
"acceptor_id": "5028111769322011000",
"name": "Orders production",
"description": "Routes payment + refund events to order-service.",
"url": "https://api.example.com/webhooks/taptree",
"transport": "http",
"event_types": ["transactions.payment.*"],
"state": "paused",
"signing_algo": "hmac-sha256-v2",
"consecutive_failures": 0,
"last_success_at": "2026-05-19T09:14:02.118Z",
"tripped_until": null,
"row_version": 4,
"created_at": "2026-04-12T11:02:33.001Z",
"updated_at": "2026-05-19T13:45:08.221Z"
}
Rotate a webhook endpoint signing secret
Mint a fresh signing secret for an endpoint and receive the one-shot reveal. The previous secret stays valid for grace_hours after the rotation so receivers can deploy the new secret without dropped events. After the grace window expires the old secret is permanently invalidated.
Capture plaintext_secret and public_secret_id from the response — they are not retrievable later.
Requires the webhooks:rotate_secret scope (deliberately separate from webhooks:write so an automation key can rotate without being able to also change URLs or event subscriptions).
Request headers
- Name
If-Match- Type
- header
- Description
Current
row_version. Same semantics asPATCH.
Request body
The body is optional; an empty body uses the defaults.
- Name
grace_hours- Type
- integer
- Description
How long (in hours) the previous secret remains valid alongside the new one. Range
0..168(one week). Default24.
- Name
rotation_reason- Type
- string
- Description
Free-form label captured in the audit log. 1–64 characters. Default
manual. Useful values:scheduled,compromise,staff-leaver.
Possible response statuses
- Name
200 OK- Type
- status
- Description
The endpoint object with the new
row_versionplus the one-shot reveal block (plaintext_secret,public_secret_id,rotation.previous_expires_at).
- Name
400 Bad Request- Type
- status
- Description
Body validation failed (out-of-range
grace_hours, etc.).
- Name
401 Unauthorized- Type
- status
- Description
Missing or invalid bearer token.
- Name
403 Forbidden- Type
- status
- Description
Scope missing.
- Name
404 Not Found- Type
- status
- Description
Endpoint id not visible to this key.
- Name
409 Conflict- Type
- status
- Description
Stale
If-Match.
- Name
428 Precondition Required- Type
- status
- Description
If-Matchheader missing.
Request
curl -X POST https://api.taptree.org/v1/webhooks/1252416694177497000/rotate-secret \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-H 'If-Match: "4"' \
-d '{"grace_hours": 48, "rotation_reason": "scheduled"}'
Example response
{
"object": "webhook_endpoint_secret",
"id": "1252416694177497000",
"environment_id": "8419223344005061000",
"acceptor_id": "5028111769322011000",
"name": "Orders production",
"description": "Routes payment + refund events to order-service.",
"url": "https://api.example.com/webhooks/taptree",
"transport": "http",
"event_types": ["transactions.payment.*"],
"state": "paused",
"signing_algo": "hmac-sha256-v2",
"consecutive_failures": 0,
"last_success_at": "2026-05-19T09:14:02.118Z",
"tripped_until": null,
"row_version": 5,
"created_at": "2026-04-12T11:02:33.001Z",
"updated_at": "2026-05-19T14:01:00.000Z",
"rotation": {
"new_version_id": "9981334467728802000",
"previous_version": 1,
"previous_expires_at": "2026-05-21T14:01:00.000Z"
},
"public_secret_id": "whsec_id_8c14a2",
"plaintext_secret": "whsec_ab99ee77dd66cc55bb44aa33ee22dd11cc00bb99aa88..."
}
Delete a webhook endpoint
Soft-delete an endpoint. No future events are delivered and the endpoint disappears from list/retrieve responses, but the audit history is retained for compliance. The endpoint id is permanently retired — you cannot reuse it.
Requires the webhooks:write scope.
Request headers
- Name
If-Match- Type
- header
- Description
Current
row_version. Same semantics asPATCH.
Possible response statuses
- Name
204 No Content- Type
- status
- Description
The endpoint has been soft-deleted. No response body.
- Name
401 Unauthorized- Type
- status
- Description
Missing or invalid bearer token.
- Name
403 Forbidden- Type
- status
- Description
Scope missing.
- Name
404 Not Found- Type
- status
- Description
Endpoint id not visible to this key.
- Name
409 Conflict- Type
- status
- Description
Stale
If-Match.
- Name
428 Precondition Required- Type
- status
- Description
If-Matchheader missing.
Request
curl -X DELETE https://api.taptree.org/v1/webhooks/1252416694177497000 \
-H "Authorization: Bearer {token}" \
-H 'If-Match: "5"'
Example response
HTTP/1.1 204 No Content