PageSourceSearch

https://zyphr.dev/docs/assets/js/6f391906.1d0da491.js

js zyphr.dev collected 2026-10-04 22:57:50 UTC 12,379 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunk_zyphr_docs=globalThis.webpackChunk_zyphr_docs||[]).push([[263],{78056(e,s,t){t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>l,default:()=>a,frontMatter:()=>n,metadata:()=>i,toc:()=>h});const i=JSON.parse('{"id":"features/webhooks-monitoring","title":"Monitoring & Debugging","description":"Delivery logs, endpoint health, test events, and debugging failed webhook deliveries.","source":"@site/docs/features/webhooks-monitoring.md","sourceDirName":"features","slug":"/features/webhooks-monitoring","permalink":"/docs/features/webhooks-monitoring","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"title":"Monitoring & Debugging","description":"Delivery logs, endpoint health, test events, and debugging failed webhook deliveries."},"sidebar":"docsSidebar","previous":{"title":"Security & Signatures","permalink":"/docs/features/webhooks-security"},"next":{"title":"Best Practices","permalink":"/docs/features/webhooks-best-practices"}}');var d=t(31085),r=t(71184);const n={title:"Monitoring & Debugging",description:"Delivery logs, endpoint health, test events, and debugging failed webhook deliveries."},l="Monitoring & Debugging",c={},h=[{value:"Delivery Logs",id:"delivery-logs",level:2},{value:"List Deliveries",id:"list-deliveries",level:3},{value:"Delivery Detail",id:"delivery-detail",level:3},{value:"Endpoint Health",id:"endpoint-health",level:2},{value:"Webhook Statuses",id:"webhook-statuses",level:3},{value:"Test Events",id:"test-events",level:2},{value:"Common Issues",id:"common-issues",level:2}];function o(e){const s={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(s.header,{children:(0,d.jsx)(s.h1,{id:"monitoring--debugging",children:"Monitoring & Debugging"})}),"\n",(0,d.jsx)(s.p,{children:"Zyphr provides full observability into your webhook deliveries \u2014 delivery logs with request/response capture, endpoint health tracking, and test events for integration development."}),"\n",(0,d.jsx)(s.h2,{id:"delivery-logs",children:"Delivery Logs"}),"\n",(0,d.jsx)(s.h3,{id:"list-deliveries",children:"List Deliveries"}),"\n",(0,d.jsx)(s.p,{children:"Retrieve delivery history for a webhook endpoint:"}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-bash",children:'curl "https://api.zyphr.dev/v1/webhooks/YOUR_WEBHOOK_ID/deliveries?limit=20&offset=0" \\\n  -H "Authorization: Bearer YOUR_API_KEY"\n'})}),"\n",(0,d.jsx)(s.p,{children:"Filter by status:"}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-bash",children:'curl "https://api.zyphr.dev/v1/webhooks/YOUR_WEBHOOK_ID/deliveries?status=failed" \\\n  -H "Authorization: Bearer YOUR_API_KEY"\n'})}),"\n",(0,d.jsxs)(s.p,{children:["Valid status filters: ",(0,d.jsx)(s.code,{children:"pending"}),", ",(0,d.jsx)(s.code,{children:"success"}),", ",(0,d.jsx)(s.code,{children:"failed"}),", ",(0,d.jsx)(s.code,{children:"exhausted"}),"."]}),"\n",(0,d.jsx)(s.h3,{id:"delivery-detail",children:"Delivery Detail"}),"\n",(0,d.jsx)(s.p,{children:"Get full details for a specific delivery, including the payload and response body:"}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-bash",children:'curl "https://api.zyphr.dev/v1/webhooks/YOUR_WEBHOOK_ID/deliveries/DELIVERY_ID" \\\n  -H "Authorization: Bearer YOUR_API_KEY"\n'})}),"\n",(0,d.jsx)(s.p,{children:"The detail response includes:"}),"\n",(0,d.jsxs)(s.table,{children:[(0,d.jsx)(s.thead,{children:(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.th,{children:"Field"}),(0,d.jsx)(s.th,{children:"Description"})]})}),(0,d.jsxs)(s.tbody,{children:[(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"id"})}),(0,d.jsx)(s.td,{children:"Delivery record ID"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"msg_id"})}),(0,d.jsx)(s.td,{children:"Stable message ID (for deduplication)"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"event_id"})}),(0,d.jsx)(s.td,{children:"Originating event ID"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"event_type"})}),(0,d.jsxs)(s.td,{children:["Event type (e.g., ",(0,d.jsx)(s.code,{children:"email.delivered"}),")"]})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"payload"})}),(0,d.jsx)(s.td,{children:"Full webhook payload that was sent"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"status"})}),(0,d.jsx)(s.td,{children:"Current delivery status"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"attempts"})}),(0,d.jsx)(s.td,{children:"Number of delivery attempts made"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"max_attempts"})}),(0,d.jsx)(s.td,{children:"Maximum attempts allowed"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"next_attempt_at"})}),(0,d.jsx)(s.td,{children:"When the next retry is scheduled (if applicable)"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_response_status"})}),(0,d.jsx)(s.td,{children:"HTTP status code from your endpoint"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_response_body"})}),(0,d.jsx)(s.td,{children:"Response body from your endpoint (truncated to 1,000 chars)"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_error"})}),(0,d.jsx)(s.td,{children:"Error message if the delivery failed"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"first_attempted_at"})}),(0,d.jsx)(s.td,{children:"Timestamp of the first delivery attempt"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_attempted_at"})}),(0,d.jsx)(s.td,{children:"Timestamp of the most recent attempt"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"completed_at"})}),(0,d.jsx)(s.td,{children:"Timestamp when delivery succeeded or was exhausted"})]})]})]}),"\n",(0,d.jsx)(s.h2,{id:"endpoint-health",children:"Endpoint Health"}),"\n",(0,d.jsx)(s.p,{children:"Each webhook tracks health metrics that help you identify problematic endpoints:"}),"\n",(0,d.jsxs)(s.table,{children:[(0,d.jsx)(s.thead,{children:(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.th,{children:"Field"}),(0,d.jsx)(s.th,{children:"Description"})]})}),(0,d.jsxs)(s.tbody,{children:[(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"status"})}),(0,d.jsxs)(s.td,{children:["Current webhook status: ",(0,d.jsx)(s.code,{children:"active"}),", ",(0,d.jsx)(s.code,{children:"paused"}),", or ",(0,d.jsx)(s.code,{children:"disabled"})]})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"consecutive_failures"})}),(0,d.jsx)(s.td,{children:"Number of consecutive failed deliveries"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_failure_at"})}),(0,d.jsx)(s.td,{children:"Timestamp of the most recent failure"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"disabled_at"})}),(0,d.jsx)(s.td,{children:"Timestamp when the webhook was auto-disabled"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"disabled_reason"})}),(0,d.jsx)(s.td,{children:'Reason for auto-disable (e.g., "10 consecutive failures")'})]})]})]}),"\n",(0,d.jsx)(s.h3,{id:"webhook-statuses",children:"Webhook Statuses"}),"\n",(0,d.jsxs)(s.table,{children:[(0,d.jsx)(s.thead,{children:(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.th,{children:"Status"}),(0,d.jsx)(s.th,{children:"Description"})]})}),(0,d.jsxs)(s.tbody,{children:[(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"active"})}),(0,d.jsx)(s.td,{children:"Endpoint is receiving deliveries normally"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"paused"})}),(0,d.jsx)(s.td,{children:"Endpoint is temporarily paused \u2014 deliveries are held"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"disabled"})}),(0,d.jsx)(s.td,{children:"Endpoint was auto-disabled due to consecutive failures"})]})]})]}),"\n",(0,d.jsxs)(s.p,{children:["Pausing a webhook is useful during maintenance. While paused, new events still create delivery records but deliveries are not attempted until the webhook is set back to ",(0,d.jsx)(s.code,{children:"active"}),"."]}),"\n",(0,d.jsx)(s.h2,{id:"test-events",children:"Test Events"}),"\n",(0,d.jsx)(s.p,{children:"Send a test event to verify your endpoint is configured correctly:"}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-bash",children:'curl -X POST https://api.zyphr.dev/v1/webhooks/YOUR_WEBHOOK_ID/test \\\n  -H "Authorization: Bearer YOUR_API_KEY"\n'})}),"\n",(0,d.jsxs)(s.p,{children:["The default test event uses the ",(0,d.jsx)(s.code,{children:"webhook.test"})," event type. Customize the event type and payload:"]}),"\n",(0,d.jsx)(s.pre,{children:(0,d.jsx)(s.code,{className:"language-bash",children:'curl -X POST https://api.zyphr.dev/v1/webhooks/YOUR_WEBHOOK_ID/test \\\n  -H "Authorization: Bearer YOUR_API_KEY" \\\n  -H "Content-Type: application/json" \\\n  -d \'{\n    "event_type": "email.delivered",\n    "payload": {\n      "message_id": "test-msg-123",\n      "recipient_email": "[email protected]"\n    }\n  }\'\n'})}),"\n",(0,d.jsxs)(s.p,{children:["Test events create a real delivery record with ",(0,d.jsx)(s.code,{children:"max_attempts: 1"})," (no retries) so you can inspect the full delivery lifecycle."]}),"\n",(0,d.jsx)(s.h2,{id:"common-issues",children:"Common Issues"}),"\n",(0,d.jsxs)(s.table,{children:[(0,d.jsx)(s.thead,{children:(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.th,{children:"Symptom"}),(0,d.jsx)(s.th,{children:"Likely Cause"}),(0,d.jsx)(s.th,{children:"Solution"})]})}),(0,d.jsxs)(s.tbody,{children:[(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:'last_error: "Request timed out after 30000ms"'})}),(0,d.jsx)(s.td,{children:"Endpoint is too slow"}),(0,d.jsx)(s.td,{children:"Respond within 30 seconds \u2014 process events asynchronously"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"last_response_status: 401"})," or ",(0,d.jsx)(s.code,{children:"403"})]}),(0,d.jsx)(s.td,{children:"Authentication failure"}),(0,d.jsx)(s.td,{children:"Ensure your endpoint doesn't require auth for webhook POST requests"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_response_status: 404"})}),(0,d.jsx)(s.td,{children:"Wrong URL"}),(0,d.jsx)(s.td,{children:"Verify the webhook URL is correct"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:(0,d.jsx)(s.code,{children:"last_response_status: 500"})}),(0,d.jsx)(s.td,{children:"Server error"}),(0,d.jsx)(s.td,{children:"Check your endpoint's error logs"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"last_error"})," contains DNS error"]}),(0,d.jsx)(s.td,{children:"DNS resolution failed"}),(0,d.jsx)(s.td,{children:"Verify the hostname is correct and DNS is configured"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:[(0,d.jsx)(s.code,{children:"last_error"})," contains SSL/TLS error"]}),(0,d.jsx)(s.td,{children:"Certificate issue"}),(0,d.jsx)(s.td,{children:"Ensure your SSL certificate is valid and not expired"})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsxs)(s.td,{children:["Webhook status is ",(0,d.jsx)(s.code,{children:"disabled"})]}),(0,d.jsx)(s.td,{children:"10 consecutive failures"}),(0,d.jsxs)(s.td,{children:["Fix the underlying issue, then re-enable with ",(0,d.jsx)(s.code,{children:"PUT /v1/webhooks/:id"})]})]}),(0,d.jsxs)(s.tr,{children:[(0,d.jsx)(s.td,{children:"Signature verification fails"}),(0,d.jsx)(s.td,{children:"Wrong secret or algorithm"}),(0,d.jsx)(s.td,{children:"Confirm you're using the correct secret and signature format"})]})]})]})]})}function a(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,d.jsx)(s,{...e,children:(0,d.jsx)(o,{...e})}):o(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.