10xDotIn Developer Docs

Webhook Delivery and Failure Handling

Understand webhook delivery guarantees, retry behavior, terminal failures, and debugging steps.

Webhook Delivery and Failure Handling

Use this guide when you need to answer a practical webhook question quickly:

  • Was the webhook only accepted for dispatch, or actually delivered?
  • Which failures are retried automatically?
  • Which responses are treated as terminal failures?
  • What evidence should you collect before escalating to support?

Delivery model

  • 10x sends webhooks as HTTPS POST requests to your configured endpoint.
  • Webhook dispatch is asynchronous. Creating a subscription or triggering a test accepts work for delivery; it does not wait for your endpoint to finish processing.
  • Deliveries are at-least-once, not exactly-once. Your receiver must handle duplicate deliveries safely.
  • If ordering matters to your system, compare id, occurredAt, and your own idempotency state instead of assuming strict in-order arrival.

What a webhook test does and does not prove

POST /v2/handles/{handle}/webhooks/{subscriptionId}/test queues a webhook.test delivery and returns 202 with an eventId.

What it proves:

  • the subscription exists
  • 10x accepted the dispatch request
  • your endpoint can be exercised at that moment

What it does not prove:

  • that future live deliveries will succeed
  • that your production endpoint will stay healthy
  • that your live event filters are broad enough for the business events you care about

Delivery request format

Each delivery includes these headers:

  • x-arjun-signature: HMAC-SHA256 signature in the format sha256=<hex>
  • x-arjun-event-type: event type such as link.clicked
  • x-arjun-attempt: delivery attempt number

Typical payload shape:

{
  "id": "evt_...",
  "type": "link.clicked",
  "handle": "acme",
  "occurredAt": "2026-02-25T12:00:00Z",
  "payload": {}
}

Retry and terminal-failure policy

10x currently performs up to 5 total delivery attempts. Retryable failures are retried after 5s, 10s, 20s, and 40s.

Receiver outcome10x behaviorWhat you should do
timeout / connection failure / no HTTP responseRetry automaticallyKeep the endpoint reachable and return a response quickly
5xxRetry automaticallyTreat as receiver instability and restore service
408, 409, 425, 429Retry automaticallyStabilize the receiver, then let retries succeed
most other 4xx such as 400, 401, 403, 404, 410, 422Classify as terminal immediatelyFix route, auth, secret validation, or payload expectations
repeated retryable failure through attempt 5Classify as terminal on the final attemptInvestigate receiver stability before replaying

What happens on terminal failure

When a delivery is classified as terminal:

  • the failed delivery is written to the webhook DLQ for operator triage
  • a webhook.delivery.terminal_failure event can be emitted for downstream notification flows
  • handle-owner alerting paths may notify operators or owners about the failed subscription

Current operational note: 10x does not automatically disable your subscription for you. If your endpoint is invalid or no longer wanted, you should update or remove it.

Troubleshooting by status code

SymptomTypical causeNext step
401 or 403Secret/auth verification mismatchRe-check signature verification, auth middleware, and any IP or header gating
404Wrong path, inactive route, or deleted workflowConfirm the exact production URL and make sure the route is deployed
410Endpoint intentionally retiredUpdate the subscription to a live endpoint
422Payload rejected by business validationRelax the receiver schema or update the integration contract
429Receiver is throttlingQueue internally on your side or raise receiver capacity
5xxReceiver outage or unhandled exceptionFix the receiver and inspect application logs before replay
no request seenDNS, TLS, firewall, egress, or host mismatchVerify hostname, certificate, network rules, and request logs

Evidence to capture before escalating

If you need help from support, capture:

  • handle
  • subscriptionId
  • eventId
  • receiver URL hostname and path
  • approximate failure timestamp in UTC
  • receiver logs showing the returned status code
  • whether the failure happened on webhook.test, live traffic, or both
  • any recent deployment or config change on the receiver

Integration best practices

  • Return a 2xx quickly, then process asynchronously in your own worker if needed.
  • Verify the HMAC signature before trusting the payload.
  • Make your receiver idempotent so duplicate deliveries are safe.
  • Keep production webhook URLs stable; avoid temporary tunnels for long-lived subscriptions.
  • Use separate test and production endpoints if your downstream system has different validation rules.
  • Subscribe only to the event types you actually need.

Triggering Context Store refreshes

Webhooks are outbound delivery events, not direct Context Store ingestion. Use a receiver or automation worker as the bridge:

  1. Receive and verify the 10x webhook, or receive and verify a provider webhook in your own system.
  2. Decide which Context Store sourceId needs refresh.
  3. Call the Context Store MCP sync route using a PAT with mcp.connect and context_store.manage.
  4. Let the async worker refresh the source; use context_store_status to confirm readiness.
curl -sS -X POST "https://ai.10x.in/v2/mcp/{handle}/context-store/sources/{sourceId}/sync" \
  -H "authorization: Bearer patv1_<tokenId>.<secret>" \
  -H "content-type: application/json" \
  -d '{}'

Do not store provider webhook secrets in Context Store source config. Keep provider verification in your receiver and Context Store as the replicated search layer.

Updated Jun 19, 2026