- Signed deliveries with Ed25519 signatures — see Verify signatures
- Organization-aware headers including org ID, event type, and timestamps on every delivery
- Automatic retries for failed deliveries
- Dashboard and API management for creating and configuring endpoints
- Policy-based access control through dedicated activity types
Event types
Balance and transaction status webhook endpoints must be managed from the billing organization. Sub-organization attempts to create, update, or delete these endpoints return
PermissionDenied.Only documented event types produce deliveries. Unknown event types should not be used and may be rejected in the future.For further information on balances, including supported chains and assets, see Balances.Create an endpoint
Create webhook endpoints from a server-side client using an API key. The endpoint URL must be HTTPS and must resolve to a public destination. SDK methods accept the intent parameters directly. The SDK adds the activity envelope fields (type, timestampMs, organizationId, and parameters) before signing and submitting the request. Use the raw envelope shape only when calling the HTTP API directly.
For server-side/API-key automation, use
@turnkey/sdk-server@6.1.0+; it includes createWebhookEndpoint.For client-side admin flows, @turnkey/core can also submit webhook endpoint activities through client.httpClient.createWebhookEndpoint(...), provided the authenticated session is authorized to submit signed activities for the organization.Raw HTTP and CLI submission remain supported for direct activity submission. SDK methods accept intent parameters directly; raw HTTP uses the activity envelope shape.Activity updates
Balance updates
For balance webhooks, subscribe toBALANCE_CONFIRMED_UPDATES when enabling balance notifications. Add BALANCE_FINALIZED_UPDATES alongside confirmed updates if you also need finalization signals.
Manage endpoints
Use the webhook endpoint APIs or the Dashboard UI to manage existing endpoints:
Set
isActive to false to pause delivery without deleting the endpoint.
Endpoint validation and reachability
Webhook endpoint URLs are validated when endpoints are created or updated, and delivery also uses dial-time protections. URLs must usehttps, include a valid host, and resolve to a public destination. Turnkey rejects URLs that point to localhost, private IP ranges, link-local addresses, metadata endpoints, or URLs that include user info.
Redirects are not followed. If your endpoint hostname later resolves to a disallowed destination, delivery will fail even if the endpoint was valid when it was created.
Keep your endpoint publicly reachable and return a 2xx response after accepting the webhook. Avoid long-running request handling in the delivery path; enqueue work internally and respond quickly. 3xx, 4xx, and 429 responses are treated as terminal delivery failures, while network errors and 5xx responses may be retried.
Delivery contract
Turnkey sends each webhook as an HTTPSPOST request. The request body is JSON and the Content-Type header is application/json. Your endpoint should return a 2xx status code after accepting the delivery. Only active endpoints and active subscriptions receive deliveries.
Headers
Retry behavior
Turnkey treats2xx responses as successful. Turnkey automatically retries retryable delivery failures. Retry schedules and attempt counts are subject to change.
Signed retries receive a fresh timestamp and signature. X-Turnkey-Event-Id is signed delivery metadata and is stable across retry attempts for the same webhook event. Payload fields such as msg.idempotencyKey are event-specific business identifiers. Either may be useful for deduplication depending on the use case, but they are not the same field.
Payloads
Activity updates
ACTIVITY_UPDATES deliveries contain the full activity object for the triggering event. Use the activity id and/or the webhook X-Turnkey-Event-Id header to process deliveries idempotently.
Balance updates
Each delivery corresponds to a single balance-change event: one address, one operation (deposit or withdraw), and one asset. A single transaction can affect multiple addresses or assets, so it may produce multiple webhook deliveries, each with its own idempotencyKey.
The type field is "balances:confirmed" when a balance change is first seen onchain, or "balances:finalized" when the associated block has reached the finalization threshold.
Balance webhooks fire only for assets in the supported asset list and are not supported for private key addresses.
Transaction status updates
Each delivery fires when a transaction changes state. Thetype is always "transaction:status". Fields present in msg depend on the status:
- BROADCASTING: base fields only, no
txHashorerror - INCLUDED: base fields +
txHash. If the transaction reverted onchain,erroris also present. - FAILED: base fields +
error. NotxHash(the transaction never landed onchain).
For more details on transaction broadcasting, see Broadcasting.