[{"data":1,"prerenderedAt":1657},["ShallowReactive",2],{"search":3,"content-api\u002Fwebhook-payloads":442,"surround-\u002Fapi\u002Fwebhook-payloads":1652},[4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,304,308,312,316,320,323,327,331,335,339,343,347,351,355,359,363,367,371,375,379,383,387,391,395,399,403,407,411,415,419,423,426,430,434,438],{"path":5,"title":6,"description":7},"\u002Fguide","Guide","Product guides for Owlat — a modular, self-hosted email platform. Learn how to send campaigns, run a personal mailbox, manage a team inbox, and more.",{"path":9,"title":10,"description":11},"\u002Fguide\u002Fgetting-started","Welcome to Owlat","Set up your Owlat workspace and send your first email — from deploying the stack to verifying a domain, building your audience, and launching a campaign.",{"path":13,"title":14,"description":15},"\u002Fguide\u002Fcontact-properties","Contact Properties","Custom fields that extend built-in contact data with your own values for segmentation.",{"path":17,"title":18,"description":19},"\u002Fguide\u002Ftopics","Topics","Topics are explicit audience groups you manage by hand — ideal for opt-in subscribers, imported cohorts, and organized contact buckets you target with campaigns.",{"path":21,"title":22,"description":23},"\u002Fguide\u002Fsegments","Segments","Build dynamic, rule-based contact groups from properties, email activity, and topic membership, re-evaluated from current data each time they're used.",{"path":25,"title":26,"description":27},"\u002Fguide\u002Fforms","Forms","Form Endpoints collect new contacts from your website or landing pages by exposing a public endpoint that accepts submissions and feeds them into a topic.",{"path":29,"title":30,"description":31},"\u002Fguide\u002Fcampaigns","Campaigns & Reporting","Build and send marketing campaigns to a topic or segment with the five-step wizard, optional A\u002FB testing, and full delivery reporting.",{"path":33,"title":34,"description":35},"\u002Fguide\u002Fab-testing","A\u002FB Testing","Compare two variants of a campaign on a test group, then automatically or manually send the winning version to the rest of your audience.",{"path":37,"title":38,"description":39},"\u002Fguide\u002Fautomations","Automations","Send emails automatically based on triggers, delays, and conditions — build welcome series, trial flows, and follow-ups once and let Owlat run them.",{"path":41,"title":42,"description":43},"\u002Fguide\u002Ftransactional","Transactional Emails","One-to-one emails your application triggers in response to a user action — password resets, order confirmations, welcome emails, and similar notifications.",{"path":45,"title":46,"description":47},"\u002Fguide\u002Fcreate-campaign","Create a Campaign","Walk through Owlat's five-step campaign wizard: Basics, Audience, Content, A\u002FB Test, and Review & Send.",{"path":49,"title":50,"description":51},"\u002Fguide\u002Fsend-campaign","Send & Monitor a Campaign","How to send your campaign and track its performance with real-time metrics.",{"path":53,"title":54,"description":55},"\u002Fguide\u002Fquick-start","Quick Start","The fastest path from a blank Owlat workspace to a live email campaign, from your first template through sending and reviewing results.",{"path":57,"title":58,"description":59},"\u002Fguide\u002Ftransactional-setup","Transactional Email Setup","Set up and send transactional emails like password resets and order confirmations via the Owlat API and SDKs.",{"path":61,"title":62,"description":63},"\u002Fguide\u002Fdeliverability","Deliverability","Verify sending domains, manage your blocklist, monitor sending reputation, and stay compliant so your emails reach the inbox.",{"path":65,"title":66,"description":67},"\u002Fguide\u002Fapi-keys-webhooks","API Keys & Webhooks","Create API keys for programmatic access and set up outbound webhooks to receive real-time notifications for email and contact events.",{"path":69,"title":70,"description":71},"\u002Fguide\u002Ffeature-flags","Feature flags","Owlat is modular — every feature listed in this guide can be turned on or off. This page is the user-facing overview of how to do it.",{"path":73,"title":74,"description":75},"\u002Fguide\u002Fteam-permissions","Team & Permissions","Use role-based access to control what each member of your organization can do, with Owner, Admin, and Editor roles.",{"path":77,"title":78,"description":79},"\u002Fguide\u002Faudit-logs","Audit Logs","A chronological record of significant actions in your Owlat organization, so you can see who did what and when.",{"path":81,"title":82,"description":83},"\u002Fguide\u002Fshare-links","Share Links","Create temporary preview links to share email designs with stakeholders who don't have dashboard access.",{"path":85,"title":86,"description":87},"\u002Fguide\u002Fpostbox","Postbox — Personal Email","Per-user mailboxes with a webmail interface and native IMAP\u002FSMTP support. Run your own Gmail-equivalent personal mailbox on your Owlat instance.",{"path":89,"title":90,"description":91},"\u002Fguide\u002Fmigrate-from-google","Migrate from Google","Import your full Gmail history into Owlat over IMAP, and let your AI assistant learn from every imported conversation.",{"path":93,"title":94,"description":95},"\u002Fguide\u002Fteam-inbox","Team Inbox","Triage inbound email as a team: read AI-classified threads, approve, edit or reject agent drafts, work the review queue, and manage quarantine.",{"path":97,"title":98,"description":99},"\u002Fguide\u002Femail-editor","Email Editor","A block-based visual editor for building responsive emails that render consistently across desktop, mobile, Outlook, Gmail, and Apple Mail.",{"path":101,"title":102,"description":103},"\u002Fguide\u002Fai-agent","AI Agent & Autonomy","Configure the AI agent that classifies and drafts replies to inbound mail: auto-reply settings, the health dashboard, circuit breakers, autonomy rules, and the knowledge backfill.",{"path":105,"title":106,"description":107},"\u002Fguide\u002Fknowledge-graph","Knowledge Graph","Browse, search, and manage Owlat's typed organizational knowledge — the 7 entry types, source attribution, confidence decay, relations, and how entries are extracted from mail.",{"path":109,"title":110,"description":111},"\u002Fguide\u002Ffiles","Files","Upload, browse, search, tag, and version documents in the file library.",{"path":113,"title":114,"description":115},"\u002Fguide\u002Fchat","Team Chat","Use Owlat's built-in team chat: public and private channels, direct messages, mentions, attachments, and channels linked to an inbox conversation.",{"path":117,"title":118,"description":119},"\u002Fguide\u002Fcode-tasks","Code Tasks","Queue coding-agent tasks, watch them move from queued through review, and run the code-worker sidecar that opens the pull requests.",{"path":121,"title":122,"description":123},"\u002Fguide\u002Faudience-data","Audience Data: Identities, Relationships & Timeline","Unify a contact across email, phone, and messaging channels, merge duplicates, map relationships, and read the cross-channel interaction timeline.",{"path":125,"title":126,"description":127},"\u002Fguide\u002Fimporting-contacts","Importing & Exporting Contacts","Bring contacts into Owlat from a CSV or from Mailchimp and Stripe, export them back out, and run bulk operations on your audience.",{"path":129,"title":130,"description":131},"\u002Fguide\u002Faccount","Your Account & Data","Export your data as JSON or CSV, request account deletion with a 30-day grace period, and use the onboarding checklist and the public preference center.",{"path":133,"title":134,"description":135},"\u002Fguide\u002Fchannels","Communication Channels","Configure SMS, WhatsApp, and generic-webhook channels, monitor channel health, and understand which channels are fully live today.",{"path":137,"title":138,"description":139},"\u002Fguide\u002Fdesktop-app","Desktop App","Install the Owlat desktop app, connect one or more workspaces, switch between them, and use native notifications, tray badges, shortcuts, and deep links.",{"path":141,"title":142,"description":143},"\u002Fguide\u002Femail-templates","Email Templates","Reusable email designs that define the structure, content, and personalization of every campaign and transactional message you send in Owlat.",{"path":145,"title":146,"description":147},"\u002Fguide\u002Fai-assistant","AI Assistant","Owlat's multi-turn, streaming, tool-calling AI assistant — a private chat surface that can search your workspace and draft copy, plus @assistant replies inside team chat.",{"path":149,"title":150,"description":151},"\u002Fguide\u002Fsecurity-scanning","Sending Security & Scanning","Owlat's security scanning: a content check for spam and phishing, an attachment scan for malware, and a Google Safe Browsing URL check. Suspicious content goes to a review queue.",{"path":153,"title":154,"description":155},"\u002Fguide\u002Fsystem-updates","System & Updates","The owner-only System & Updates screen: your current Owlat version, container health, LLM spend, and the in-app one-click updater with history.",{"path":157,"title":158,"description":159},"\u002Fguide\u002Foperating-modes","Operating Modes","The different ways to run Owlat at a company — read external mailboxes over IMAP, send transactional or marketing email through a delivery provider, host your own mail server, or run a team inbox with AI — and the rules that keep each combination coherent.",{"path":161,"title":162,"description":163},"\u002Fguide\u002Fsaved-blocks","Saved Blocks","Create reusable, linked content blocks you can drop into any email — edit one and every email that uses it updates automatically.",{"path":165,"title":166,"description":167},"\u002Fguide\u002Fmedia-library","Media Library","Manage, organize, search, and reuse images and files across your emails from one centralized hub.",{"path":169,"title":170,"description":171},"\u002Fguide\u002Femail-theme","Email Theme","Set your organization's default colors, font, and email width so every new template starts from a consistent baseline.",{"path":173,"title":174,"description":175},"\u002Fguide\u002Ftranslations","Translations","Send one email in multiple languages: add per-language translations to a single template and Owlat picks the right version for each recipient.",{"path":177,"title":178,"description":179},"\u002Fguide\u002Fcontacts","Contacts","How to add, view, organize, and manage contacts in Owlat, including sources, the contact detail tabs, and subscription compliance.",{"path":181,"title":182,"description":183},"\u002Fapi","API Overview","Owlat exposes authenticated API endpoints under your Convex site URL.",{"path":185,"title":186,"description":187},"\u002Fapi\u002Fwebhooks","Webhooks","Owlat supports both outbound customer webhooks and inbound provider webhooks.",{"path":189,"title":190,"description":191},"\u002Fapi\u002Fpublic-endpoints","Public Endpoints","These routes are public-facing and usually accessed from email links or embedded forms.",{"path":193,"title":194,"description":195},"\u002Fapi\u002Fwebhook-payloads","Webhook Payloads","The authoritative wire contract for outbound webhooks: envelope, signature headers, per-event data shapes, and payload versioning.",{"path":197,"title":198,"description":199},"\u002Fapi\u002Finbound-channels","Inbound Channel Webhooks","Provider webhook reference for inbound SMS, WhatsApp, and generic-channel messages, plus the MTA mailbox and credential callbacks.",{"path":201,"title":202,"description":203},"\u002Fapi\u002Fauthentication","Authentication","Secure API access with organization-scoped API keys.",{"path":205,"title":206,"description":207},"\u002Fapi\u002Fsdk","TypeScript SDK","Typed client for the Owlat API, usable from Node.js, Bun, Deno, or any server-side JavaScript runtime.",{"path":209,"title":210,"description":211},"\u002Fapi\u002Fsdk-java","Java SDK","The official `owlat-sdk` package provides a typed client for interacting with the Owlat API from any JVM application. Requires Java 11+.",{"path":213,"title":214,"description":215},"\u002Fapi\u002Fcontacts","Contacts API","Manage contacts for your organization.",{"path":217,"title":218,"description":219},"\u002Fapi\u002Ftopics","Topics API","Manage topic membership through authenticated endpoints.",{"path":221,"title":222,"description":223},"\u002Fapi\u002Fevents","Events API","Send contact events to drive segmentation and automation triggers.",{"path":225,"title":226,"description":227},"\u002Fapi\u002Ftransactional","Transactional API","Send published transactional templates to a recipient.",{"path":229,"title":230,"description":231},"\u002Fapi\u002Fforms","Forms API","Capture subscribers through public form endpoints.",{"path":233,"title":234,"description":235},"\u002Fdeveloper","Developer Guide","Technical architecture, feature-flag model, and provider abstractions used by Owlat.",{"path":237,"title":238,"description":239},"\u002Fdeveloper\u002Fmta-system","MTA System","Owlat's custom Mail Transfer Agent for direct SMTP delivery with intelligent rate limiting, bounce processing, and IP warming.",{"path":241,"title":242,"description":243},"\u002Fdeveloper\u002Ffeature-flags","Feature flags — developer reference","How the Owlat feature flag system works: single source of truth, dependency resolution, docker profile mapping, and how to add a new flag.",{"path":245,"title":246,"description":247},"\u002Fdeveloper\u002Fhow-email-works","How Email Works","A technical deep-dive into how email actually works — from SMTP and DNS to authentication, deliverability, and the differences between marketing and private email.",{"path":249,"title":250,"description":251},"\u002Fdeveloper\u002Femail-security","Email Security","Content scanning, attachment validation, URL reputation checking, and malware detection for outbound emails.",{"path":253,"title":254,"description":255},"\u002Fdeveloper\u002Fpostbox-architecture","Postbox Architecture","How the Postbox personal-mail feature is wired — schema, IMAP server, app-password auth, outbound relay, inbound delivery, and external mailboxes.",{"path":257,"title":258,"description":259},"\u002Fdeveloper\u002Fproviders","Providers","Pluggable provider abstractions for LLM, email sending, notifications, vector stores, and analytics, selected per-deployment so self-hosters can swap implementations without code changes.",{"path":261,"title":262,"description":263},"\u002Fdeveloper\u002Fcampaign-internals","Campaign Internals","How the campaign backend works: two status machines, send pre-flight, the send orchestrator, emailSends records, and the priority workpools.",{"path":265,"title":266,"description":267},"\u002Fdeveloper\u002Faudience-internals","Audience Internals","Backend reference for contact resolution, the double opt-in lifecycle, topic subscription, the conditions registry, and segment evaluation.",{"path":269,"title":270,"description":271},"\u002Fdeveloper\u002Fautomation-internals","Automation Internals","How the automation run engine works: the step walker, the lifecycle state machine, trigger fanout, the three step types, and the resilience cron.",{"path":273,"title":274,"description":275},"\u002Fdeveloper\u002Fdeliverability-infrastructure","Deliverability Infrastructure","The Convex-side deliverability backend: provider routing, health-aware failover, sending reputation with auto-enforcement, IP warming cache, the blocklist, and the content-scan gate.",{"path":277,"title":278,"description":279},"\u002Fdeveloper\u002Farchitecture","Architecture Overview","Owlat follows a modern serverless architecture with real-time capabilities.",{"path":281,"title":282,"description":283},"\u002Fdeveloper\u002Fplatform-operations","Platform Operations","Operator reference for abuse status and the sending gate, the platform-admin roster, content review, org deletion, in-app self-update, dev endpoints, crons, and migrations.",{"path":285,"title":286,"description":287},"\u002Fdeveloper\u002Fscopes","Scopes","What each app and package in the Owlat monorepo is responsible for.",{"path":289,"title":290,"description":291},"\u002Fdeveloper\u002Fself-hosting","Self-Hosting","Deploy Owlat on your own infrastructure with Docker Compose. Complete guide from first boot to production.",{"path":293,"title":294,"description":295},"\u002Fdeveloper\u002Fself-hosting-config","Self-Hosting Configuration","Complete reference for Docker environment variables, Convex backend variables, service topology, and volume persistence.",{"path":297,"title":298,"description":299},"\u002Fdeveloper\u002Fself-hosting-dns-email","DNS & Email Setup","Configure DNS records, DKIM signing, SPF, DMARC, and bounce handling for reliable email delivery.",{"path":301,"title":302,"description":303},"\u002Fdeveloper\u002Fself-hosting-production","Production Deployment","Secure your self-hosted Owlat instance with TLS, firewall rules, backups, and monitoring.",{"path":305,"title":306,"description":307},"\u002Fdeveloper\u002Fself-hosting-maintenance","Maintenance & Updates","Keep your self-hosted Owlat instance up to date, manage backups, scale performance, and troubleshoot common issues.",{"path":309,"title":310,"description":311},"\u002Fdeveloper\u002Fself-hosting-desktop","Desktop Installer","Install Owlat on a bare Linux VPS straight from the desktop app over SSH — no terminal — with a live, animated provisioning timeline.",{"path":313,"title":314,"description":315},"\u002Fdeveloper\u002Fsetup-cli","Setup CLI & Installer","Operator reference for the Owlat self-host tooling: the install.sh one-liner, the owlat-setup CLI, the convex-deploy flow, and admin bootstrap.",{"path":317,"title":318,"description":319},"\u002Fdeveloper\u002Fconvex","Convex Backend","Owlat uses Convex as its serverless backend, providing real-time subscriptions, ACID transactions, and TypeScript-first development.",{"path":321,"title":202,"description":322},"\u002Fdeveloper\u002Fauthentication","Owlat uses BetterAuth with the Convex adapter for authentication and organization (team) management.",{"path":324,"title":325,"description":326},"\u002Fdeveloper\u002Femail-system","Email System","Owlat's email system consists of a visual editor, template management, and multi-provider sending infrastructure.",{"path":328,"title":329,"description":330},"\u002Fdeveloper\u002Femail-renderer","Email Renderer","The @owlat\u002Femail-renderer package converts editor JSON blocks into production-ready HTML emails with cross-client compatibility, CSS inlining, dark mode, and Outlook VML fallbacks.",{"path":332,"title":333,"description":334},"\u002Fdeveloper\u002Fenvironment-variables","Environment Variables","Reference for every environment variable Owlat reads across the Convex backend, web app, MTA, IMAP server, and mail-sync worker.",{"path":336,"title":337,"description":338},"\u002Fdeveloper\u002Fcomponents","Component Library","Reference for the reusable, auto-imported Vue UI components shipped in the packages\u002Fui layer.",{"path":340,"title":341,"description":342},"\u002Fdeveloper\u002Fdecisions","Architectural Decision Records","The architectural decision records for the Owlat project, each capturing the context, the decision, and the trade-offs involved.",{"path":344,"title":345,"description":346},"\u002Fdeveloper\u002Fdecisions\u002F009-model-routing","ADR-009: Task-Based Model Routing","Why Owlat supports per-task LLM model selection instead of using a single model for all pipeline steps.",{"path":348,"title":349,"description":350},"\u002Fdeveloper\u002Fdecisions\u002F010-listing-engine","ADR-010: Listing Engine","Why Owlat replaced four incompatible list-query contracts with one generic listing engine driven by per-entity descriptors.",{"path":352,"title":353,"description":354},"\u002Fdeveloper\u002Fdecisions\u002F001-custom-email-renderer","ADR-001: Custom Email Renderer Over MJML","Why Owlat built a custom table-based HTML email renderer instead of using MJML, gaining full control over VML, dark mode, and per-client rendering.",{"path":356,"title":357,"description":358},"\u002Fdeveloper\u002Fdecisions\u002F002-convex-backend","ADR-002: Convex as Backend","Why Owlat chose Convex over PostgreSQL and Firebase for real-time reactivity, co-located TypeScript logic, and zero-config scaling.",{"path":360,"title":361,"description":362},"\u002Fdeveloper\u002Fdecisions\u002F003-notion-like-builder","ADR-003: Notion-like Email Builder","Why Owlat replaced the traditional 3-panel email editor with a Notion-like single-column canvas for inline WYSIWYG editing.",{"path":364,"title":365,"description":366},"\u002Fdeveloper\u002Fdecisions\u002F004-monorepo-bun-workspaces","ADR-004: Monorepo with Bun Workspaces","Why Owlat uses a monorepo with Bun workspaces and Turborepo for fast installs, atomic cross-package changes, and cached CI.",{"path":368,"title":369,"description":370},"\u002Fdeveloper\u002Fdecisions\u002F005-custom-mta","ADR-005: Custom MTA","Why Owlat built a custom Mail Transfer Agent instead of relying solely on third-party email providers.",{"path":372,"title":373,"description":374},"\u002Fdeveloper\u002Fdecisions\u002F006-self-hosted-convex","ADR-006: Self-Hosted Convex","Why Owlat uses the open-source Convex backend for self-hosting instead of migrating to a different database.",{"path":376,"title":377,"description":378},"\u002Fdeveloper\u002Fdecisions\u002F007-pluggable-llm","ADR-007: Pluggable LLM Provider","Why Owlat uses the Vercel AI SDK with a provider abstraction layer instead of hardcoding a single LLM vendor.",{"path":380,"title":381,"description":382},"\u002Fdeveloper\u002Fdecisions\u002F008-process-architecture","ADR-008: Agent Process Architecture","Why Owlat processes inbound messages with a self-scheduling step walker plus a lifecycle coordinator instead of one sequential function.",{"path":384,"title":385,"description":386},"\u002Fexamples","Examples","Copy-pasteable integration patterns for common Owlat use cases.",{"path":388,"title":389,"description":390},"\u002Fexamples\u002Fwelcome-email","Welcome Email","Send a personalized welcome email when a new user signs up.",{"path":392,"title":393,"description":394},"\u002Fexamples\u002Fbilling-email","Billing Email","Send a billing receipt with an invoice PDF attached after a successful payment.",{"path":396,"title":397,"description":398},"\u002Fexamples\u002Fevent-automation","Event Automation","Trigger automations with custom events for trial lifecycle, feature adoption, and more.",{"path":400,"title":401,"description":402},"\u002Fexamples\u002Fcontact-sync","Contact Sync","Sync contacts from your database to Owlat using upsert patterns and bulk operations.",{"path":404,"title":405,"description":406},"\u002Fexamples\u002Fwebhook-handler","Webhook Handler","Handle Owlat delivery webhooks with signature verification and event routing.",{"path":408,"title":409,"description":410},"\u002Fexamples\u002Fmultilingual-email","Multilingual Email","Send emails in the recipient's preferred language using template translations.",{"path":412,"title":413,"description":414},"\u002Fvision","Vision","Where Owlat is heading — from email platform to unified communication intelligence powered by AI agents.",{"path":416,"title":417,"description":418},"\u002Fvision\u002Fself-hosting","Self-Hosting Architecture","How Owlat runs as a fully self-hosted stack using Docker Compose — open-source Convex backend, custom MTA, and a pluggable LLM provider.",{"path":420,"title":421,"description":422},"\u002Fvision\u002Fagent-pipeline","Agent Pipeline","Technical architecture for the inbound email agent pipeline — step modules, the walker, security scanning, threading, and human review.",{"path":424,"title":106,"description":425},"\u002Fvision\u002Fknowledge-graph","Technical architecture for Owlat's typed knowledge storage — how organizational knowledge is stored, searched, decayed, and maintained.",{"path":427,"title":428,"description":429},"\u002Fvision\u002Fmulti-channel","Multi-Channel & CRM","Technical architecture for channel adapters, unified messaging, contact identity unification, and the CRM hub.",{"path":431,"title":432,"description":433},"\u002Fvision\u002Ffile-system","Semantic File System","Technical architecture for Owlat's semantic file storage — version tracking with provenance today, plus the planned embedding-based retrieval and auto-tagging layer.",{"path":435,"title":436,"description":437},"\u002Fvision\u002Fdesktop-app","Desktop App & Advanced Agents","Architecture of the Owlat desktop shell, visualization agent, adaptive dashboard, agent health, graduated autonomy, and coding agents.",{"path":439,"title":440,"description":441},"\u002Fvision\u002Froadmap","Roadmap","What's planned next for Owlat — the documented-but-unbuilt pieces still being wired, and the enhancements on our radar.",{"id":443,"title":194,"body":444,"description":195,"extension":1646,"meta":1647,"navigation":1648,"path":193,"seo":1649,"stem":1650,"__hash__":1651},"content\u002F2.api\u002F12.webhook-payloads.md",{"type":445,"value":446,"toc":1617},"minimark",[447,460,478,483,486,556,586,591,594,668,679,688,694,722,726,729,735,748,807,812,815,846,852,855,885,891,894,937,943,954,1009,1015,1018,1048,1052,1058,1065,1121,1188,1192,1198,1204,1300,1327,1389,1394,1397,1443,1447,1453,1484,1490,1494,1501,1532,1539,1592,1599,1603,1607,1610,1613],[448,449,450,451,455,456,459],"p",{},"This is the authoritative wire contract for the outbound webhooks Owlat sends to ",[452,453,454],"em",{},"your"," endpoints. To configure subscriptions, verify signatures, and understand retry behavior at a higher level, start with the ",[457,458,186],"a",{"href":185}," reference; this page documents the exact JSON shape of every event.",[461,462,465],"callout",{"title":463,"type":464},"Payload version 1 — frozen","info",[448,466,467,468,472,473,477],{},"Every payload below is frozen as of ",[469,470,471],"code",{},"payloadVersion"," 1. Renaming a field, changing a type, dropping a field, or adding a required field is a breaking change for receivers and requires bumping the payload version. Adding a brand-new event type is ",[474,475,476],"strong",{},"not"," breaking, as long as your handler ignores unknown events.",[479,480,482],"h2",{"id":481},"envelope","Envelope",[448,484,485],{},"Every delivery is the JSON-stringified form of this envelope:",[487,488,493],"pre",{"className":489,"code":490,"language":491,"meta":492,"style":492},"language-json shiki shiki-themes github-light github-dark-dimmed","{\n  \"event\": \"\u003Cevent-name>\",\n  \"timestamp\": \"\u003CISO-8601 UTC>\",\n  \"data\": { \u002F* event-specific, see below *\u002F }\n}\n","json","",[469,494,495,504,521,534,550],{"__ignoreMap":492},[496,497,500],"span",{"class":498,"line":499},"line",1,[496,501,503],{"class":502},"sYgZi","{\n",[496,505,507,511,514,518],{"class":498,"line":506},2,[496,508,510],{"class":509},"snmFh","  \"event\"",[496,512,513],{"class":502},": ",[496,515,517],{"class":516},"s-HuK","\"\u003Cevent-name>\"",[496,519,520],{"class":502},",\n",[496,522,524,527,529,532],{"class":498,"line":523},3,[496,525,526],{"class":509},"  \"timestamp\"",[496,528,513],{"class":502},[496,530,531],{"class":516},"\"\u003CISO-8601 UTC>\"",[496,533,520],{"class":502},[496,535,537,540,543,547],{"class":498,"line":536},4,[496,538,539],{"class":509},"  \"data\"",[496,541,542],{"class":502},": { ",[496,544,546],{"class":545},"sDN9O","\u002F* event-specific, see below *\u002F",[496,548,549],{"class":502}," }\n",[496,551,553],{"class":498,"line":552},5,[496,554,555],{"class":502},"}\n",[557,558,559,570,576],"ul",{},[560,561,562,565,566,569],"li",{},[469,563,564],{},"event"," — the event literal, e.g. ",[469,567,568],{},"email.delivered",".",[560,571,572,575],{},[469,573,574],{},"timestamp"," — when the envelope was built, as an ISO-8601 UTC string.",[560,577,578,581,582,585],{},[469,579,580],{},"data"," — the event-specific payload. The HTTP request body is the exact string ",[469,583,584],{},"JSON.stringify({ event, timestamp, data })",", and the HMAC signature is computed over that exact string.",[587,588,590],"h3",{"id":589},"signature-headers","Signature headers",[448,592,593],{},"Every delivery carries these headers:",[595,596,597,610],"table",{},[598,599,600],"thead",{},[601,602,603,607],"tr",{},[604,605,606],"th",{},"Header",[604,608,609],{},"Value",[611,612,613,624,634,644,656],"tbody",{},[601,614,615,621],{},[616,617,618],"td",{},[469,619,620],{},"X-Signature",[616,622,623],{},"HMAC-SHA256 of the request body, hex-encoded, keyed with your webhook secret",[601,625,626,631],{},[616,627,628],{},[469,629,630],{},"X-Timestamp",[616,632,633],{},"Unix seconds when the delivery was attempted",[601,635,636,641],{},[616,637,638],{},[469,639,640],{},"X-Webhook-Id",[616,642,643],{},"Convex ID of the webhook subscription",[601,645,646,651],{},[616,647,648],{},[469,649,650],{},"User-Agent",[616,652,653],{},[469,654,655],{},"Owlat-Webhooks\u002F1.0",[601,657,658,663],{},[616,659,660],{},[469,661,662],{},"Content-Type",[616,664,665],{},[469,666,667],{},"application\u002Fjson",[448,669,670,671,674,675,569],{},"Webhook secrets use the ",[469,672,673],{},"whsec_..."," format and are generated when the webhook is created. Verify the signature by recomputing the HMAC over the raw body and comparing in constant time — see the ",[457,676,678],{"href":677},"\u002Fapi\u002Fwebhooks#signature-verification","verification example in the Webhooks reference",[461,680,683],{"title":681,"type":682},"Sign over the raw body, not a re-serialized object","warning",[448,684,685,687],{},[469,686,620],{}," is computed over the literal request bytes. If your framework parses and re-serializes the JSON before you hash it, key ordering or whitespace can change and the signature will not match. Read the raw body string first, verify, then parse.",[587,689,691,693],{"id":690},"data-shape-constraints",[469,692,580],{}," shape constraints",[448,695,696,697,699,700,513,703,706,707,706,710,713,714,717,718,721],{},"In payload version 1, ",[469,698,580],{}," is a ",[474,701,702],{},"flat map of primitives",[469,704,705],{},"string",", ",[469,708,709],{},"number",[469,711,712],{},"boolean",", or ",[469,715,716],{},"null",". There are no nested objects or arrays. Anything structured is JSON-encoded into a string field — see ",[469,719,720],{},"topic.unsubscribed.listsRemoved"," below. A future payload version may relax this.",[479,723,725],{"id":724},"email-events","Email events",[448,727,728],{},"These fire as a campaign or transactional email moves through sending, delivery, and engagement.",[587,730,732],{"id":731},"emailsent",[469,733,734],{},"email.sent",[448,736,737,738,741,742,745,746,569],{},"Fired when a campaign or transactional email is handed to the sending provider. Exactly one of ",[469,739,740],{},"campaignId"," \u002F ",[469,743,744],{},"transactionalEmailId"," is set; the other is ",[469,747,716],{},[487,749,751],{"className":489,"code":750,"language":491,"meta":492,"style":492},"{\n  \"email\": \"recipient@example.com\",\n  \"campaignId\": \"\u003CId\u003C'campaigns'> | null>\",\n  \"transactionalEmailId\": \"\u003CId\u003C'transactionalEmails'> | null>\",\n  \"timestamp\": \"\u003CISO-8601>\"\n}\n",[469,752,753,757,769,781,793,802],{"__ignoreMap":492},[496,754,755],{"class":498,"line":499},[496,756,503],{"class":502},[496,758,759,762,764,767],{"class":498,"line":506},[496,760,761],{"class":509},"  \"email\"",[496,763,513],{"class":502},[496,765,766],{"class":516},"\"recipient@example.com\"",[496,768,520],{"class":502},[496,770,771,774,776,779],{"class":498,"line":523},[496,772,773],{"class":509},"  \"campaignId\"",[496,775,513],{"class":502},[496,777,778],{"class":516},"\"\u003CId\u003C'campaigns'> | null>\"",[496,780,520],{"class":502},[496,782,783,786,788,791],{"class":498,"line":536},[496,784,785],{"class":509},"  \"transactionalEmailId\"",[496,787,513],{"class":502},[496,789,790],{"class":516},"\"\u003CId\u003C'transactionalEmails'> | null>\"",[496,792,520],{"class":502},[496,794,795,797,799],{"class":498,"line":552},[496,796,526],{"class":509},[496,798,513],{"class":502},[496,800,801],{"class":516},"\"\u003CISO-8601>\"\n",[496,803,805],{"class":498,"line":804},6,[496,806,555],{"class":502},[587,808,810],{"id":809},"emaildelivered",[469,811,568],{},[448,813,814],{},"Fired when the receiving mail server accepts delivery.",[487,816,818],{"className":489,"code":817,"language":491,"meta":492,"style":492},"{\n  \"email\": \"recipient@example.com\",\n  \"timestamp\": \"\u003CISO-8601>\"\n}\n",[469,819,820,824,834,842],{"__ignoreMap":492},[496,821,822],{"class":498,"line":499},[496,823,503],{"class":502},[496,825,826,828,830,832],{"class":498,"line":506},[496,827,761],{"class":509},[496,829,513],{"class":502},[496,831,766],{"class":516},[496,833,520],{"class":502},[496,835,836,838,840],{"class":498,"line":523},[496,837,526],{"class":509},[496,839,513],{"class":502},[496,841,801],{"class":516},[496,843,844],{"class":498,"line":536},[496,845,555],{"class":502},[587,847,849],{"id":848},"emailopened",[469,850,851],{},"email.opened",[448,853,854],{},"Fired on first open, tracked via a 1×1 pixel beacon.",[487,856,857],{"className":489,"code":817,"language":491,"meta":492,"style":492},[469,858,859,863,873,881],{"__ignoreMap":492},[496,860,861],{"class":498,"line":499},[496,862,503],{"class":502},[496,864,865,867,869,871],{"class":498,"line":506},[496,866,761],{"class":509},[496,868,513],{"class":502},[496,870,766],{"class":516},[496,872,520],{"class":502},[496,874,875,877,879],{"class":498,"line":523},[496,876,526],{"class":509},[496,878,513],{"class":502},[496,880,801],{"class":516},[496,882,883],{"class":498,"line":536},[496,884,555],{"class":502},[587,886,888],{"id":887},"emailclicked",[469,889,890],{},"email.clicked",[448,892,893],{},"Fired on each link click, via the tracked-URL redirect.",[487,895,897],{"className":489,"code":896,"language":491,"meta":492,"style":492},"{\n  \"email\": \"recipient@example.com\",\n  \"url\": \"https:\u002F\u002Fwww.example.com\u002Flanding\",\n  \"timestamp\": \"\u003CISO-8601>\"\n}\n",[469,898,899,903,913,925,933],{"__ignoreMap":492},[496,900,901],{"class":498,"line":499},[496,902,503],{"class":502},[496,904,905,907,909,911],{"class":498,"line":506},[496,906,761],{"class":509},[496,908,513],{"class":502},[496,910,766],{"class":516},[496,912,520],{"class":502},[496,914,915,918,920,923],{"class":498,"line":523},[496,916,917],{"class":509},"  \"url\"",[496,919,513],{"class":502},[496,921,922],{"class":516},"\"https:\u002F\u002Fwww.example.com\u002Flanding\"",[496,924,520],{"class":502},[496,926,927,929,931],{"class":498,"line":536},[496,928,526],{"class":509},[496,930,513],{"class":502},[496,932,801],{"class":516},[496,934,935],{"class":498,"line":552},[496,936,555],{"class":502},[587,938,940],{"id":939},"emailbounced",[469,941,942],{},"email.bounced",[448,944,945,946,949,950,953],{},"Fired on a hard or soft bounce reported by the provider. ",[469,947,948],{},"message"," is the provider-supplied reason, or an empty string ",[469,951,952],{},"\"\""," when none was given.",[487,955,957],{"className":489,"code":956,"language":491,"meta":492,"style":492},"{\n  \"email\": \"recipient@example.com\",\n  \"bounceType\": \"hard | soft\",\n  \"message\": \"\u003Cprovider reason or ''>\",\n  \"timestamp\": \"\u003CISO-8601>\"\n}\n",[469,958,959,963,973,985,997,1005],{"__ignoreMap":492},[496,960,961],{"class":498,"line":499},[496,962,503],{"class":502},[496,964,965,967,969,971],{"class":498,"line":506},[496,966,761],{"class":509},[496,968,513],{"class":502},[496,970,766],{"class":516},[496,972,520],{"class":502},[496,974,975,978,980,983],{"class":498,"line":523},[496,976,977],{"class":509},"  \"bounceType\"",[496,979,513],{"class":502},[496,981,982],{"class":516},"\"hard | soft\"",[496,984,520],{"class":502},[496,986,987,990,992,995],{"class":498,"line":536},[496,988,989],{"class":509},"  \"message\"",[496,991,513],{"class":502},[496,993,994],{"class":516},"\"\u003Cprovider reason or ''>\"",[496,996,520],{"class":502},[496,998,999,1001,1003],{"class":498,"line":552},[496,1000,526],{"class":509},[496,1002,513],{"class":502},[496,1004,801],{"class":516},[496,1006,1007],{"class":498,"line":804},[496,1008,555],{"class":502},[587,1010,1012],{"id":1011},"emailcomplained",[469,1013,1014],{},"email.complained",[448,1016,1017],{},"Fired when the recipient marks the email as spam (the provider's feedback loop).",[487,1019,1020],{"className":489,"code":817,"language":491,"meta":492,"style":492},[469,1021,1022,1026,1036,1044],{"__ignoreMap":492},[496,1023,1024],{"class":498,"line":499},[496,1025,503],{"class":502},[496,1027,1028,1030,1032,1034],{"class":498,"line":506},[496,1029,761],{"class":509},[496,1031,513],{"class":502},[496,1033,766],{"class":516},[496,1035,520],{"class":502},[496,1037,1038,1040,1042],{"class":498,"line":523},[496,1039,526],{"class":509},[496,1041,513],{"class":502},[496,1043,801],{"class":516},[496,1045,1046],{"class":498,"line":536},[496,1047,555],{"class":502},[479,1049,1051],{"id":1050},"contact-events","Contact events",[587,1053,1055],{"id":1054},"contactcreated",[469,1056,1057],{},"contact.created",[448,1059,1060,1061,1064],{},"Fired when a new contact is added. ",[469,1062,1063],{},"source"," records how the contact entered the system.",[487,1066,1068],{"className":489,"code":1067,"language":491,"meta":492,"style":492},"{\n  \"contactId\": \"\u003CId\u003C'contacts'>>\",\n  \"email\": \"person@example.com\",\n  \"source\": \"api | import | form | transactional | inbound\",\n  \"timestamp\": \"\u003CISO-8601>\"\n}\n",[469,1069,1070,1074,1086,1097,1109,1117],{"__ignoreMap":492},[496,1071,1072],{"class":498,"line":499},[496,1073,503],{"class":502},[496,1075,1076,1079,1081,1084],{"class":498,"line":506},[496,1077,1078],{"class":509},"  \"contactId\"",[496,1080,513],{"class":502},[496,1082,1083],{"class":516},"\"\u003CId\u003C'contacts'>>\"",[496,1085,520],{"class":502},[496,1087,1088,1090,1092,1095],{"class":498,"line":523},[496,1089,761],{"class":509},[496,1091,513],{"class":502},[496,1093,1094],{"class":516},"\"person@example.com\"",[496,1096,520],{"class":502},[496,1098,1099,1102,1104,1107],{"class":498,"line":536},[496,1100,1101],{"class":509},"  \"source\"",[496,1103,513],{"class":502},[496,1105,1106],{"class":516},"\"api | import | form | transactional | inbound\"",[496,1108,520],{"class":502},[496,1110,1111,1113,1115],{"class":498,"line":552},[496,1112,526],{"class":509},[496,1114,513],{"class":502},[496,1116,801],{"class":516},[496,1118,1119],{"class":498,"line":804},[496,1120,555],{"class":502},[595,1122,1123,1134],{},[598,1124,1125],{},[601,1126,1127,1131],{},[604,1128,1129],{},[469,1130,1063],{},[604,1132,1133],{},"Meaning",[611,1135,1136,1148,1158,1168,1178],{},[601,1137,1138,1143],{},[616,1139,1140],{},[469,1141,1142],{},"api",[616,1144,1145,1146],{},"Created via the ",[457,1147,214],{"href":213},[601,1149,1150,1155],{},[616,1151,1152],{},[469,1153,1154],{},"import",[616,1156,1157],{},"Added through a CSV import",[601,1159,1160,1165],{},[616,1161,1162],{},[469,1163,1164],{},"form",[616,1166,1167],{},"Submitted a hosted form",[601,1169,1170,1175],{},[616,1171,1172],{},[469,1173,1174],{},"transactional",[616,1176,1177],{},"Auto-created while sending a transactional email",[601,1179,1180,1185],{},[616,1181,1182],{},[469,1183,1184],{},"inbound",[616,1186,1187],{},"Created from an inbound message",[479,1189,1191],{"id":1190},"topic-events","Topic events",[587,1193,1195],{"id":1194},"topicunsubscribed",[469,1196,1197],{},"topic.unsubscribed",[448,1199,1200,1201,569],{},"Fired when a contact unsubscribes from one or more ",[457,1202,1203],{"href":17},"topics",[487,1205,1207],{"className":489,"code":1206,"language":491,"meta":492,"style":492},"{\n  \"contactId\": \"\u003CId\u003C'contacts'>>\",\n  \"email\": \"person@example.com\",\n  \"unsubscribedAt\": 1710505200000,\n  \"listsRemoved\": \"[{\\\"topicId\\\":\\\"...\\\",\\\"topicName\\\":\\\"...\\\"}]\"\n}\n",[469,1208,1209,1213,1223,1233,1246,1296],{"__ignoreMap":492},[496,1210,1211],{"class":498,"line":499},[496,1212,503],{"class":502},[496,1214,1215,1217,1219,1221],{"class":498,"line":506},[496,1216,1078],{"class":509},[496,1218,513],{"class":502},[496,1220,1083],{"class":516},[496,1222,520],{"class":502},[496,1224,1225,1227,1229,1231],{"class":498,"line":523},[496,1226,761],{"class":509},[496,1228,513],{"class":502},[496,1230,1094],{"class":516},[496,1232,520],{"class":502},[496,1234,1235,1238,1240,1244],{"class":498,"line":536},[496,1236,1237],{"class":509},"  \"unsubscribedAt\"",[496,1239,513],{"class":502},[496,1241,1243],{"class":1242},"sviXB","1710505200000",[496,1245,520],{"class":502},[496,1247,1248,1251,1253,1256,1260,1263,1265,1268,1270,1273,1275,1278,1280,1283,1285,1287,1289,1291,1293],{"class":498,"line":552},[496,1249,1250],{"class":509},"  \"listsRemoved\"",[496,1252,513],{"class":502},[496,1254,1255],{"class":516},"\"[{",[496,1257,1259],{"class":1258},"s74oq","\\\"",[496,1261,1262],{"class":516},"topicId",[496,1264,1259],{"class":1258},[496,1266,1267],{"class":516},":",[496,1269,1259],{"class":1258},[496,1271,1272],{"class":516},"...",[496,1274,1259],{"class":1258},[496,1276,1277],{"class":516},",",[496,1279,1259],{"class":1258},[496,1281,1282],{"class":516},"topicName",[496,1284,1259],{"class":1258},[496,1286,1267],{"class":516},[496,1288,1259],{"class":1258},[496,1290,1272],{"class":516},[496,1292,1259],{"class":1258},[496,1294,1295],{"class":516},"}]\"\n",[496,1297,1298],{"class":498,"line":804},[496,1299,555],{"class":502},[461,1301,1303],{"title":1302,"type":682},"listsRemoved is a JSON-encoded string",[448,1304,1305,1306,699,1309,1311,1312,1315,1316,1319,1320,1323,1324,1326],{},"Because payload version 1 only allows flat primitives, ",[469,1307,1308],{},"listsRemoved",[474,1310,705],{}," containing JSON, not an array. You must ",[469,1313,1314],{},"JSON.parse"," it to read the entries. Each entry is ",[469,1317,1318],{},"{ topicId, topicName }",". Note also that ",[469,1321,1322],{},"unsubscribedAt"," is epoch milliseconds (a number), unlike the ISO-8601 ",[469,1325,574],{}," on the email events.",[487,1328,1332],{"className":1329,"code":1330,"language":1331,"meta":492,"style":492},"language-typescript shiki shiki-themes github-light github-dark-dimmed","const removed: Array\u003C{ topicId: string; topicName: string }> =\n  JSON.parse(data.listsRemoved)\n","typescript",[469,1333,1334,1375],{"__ignoreMap":492},[496,1335,1336,1340,1343,1345,1349,1352,1355,1357,1360,1363,1365,1367,1369,1372],{"class":498,"line":499},[496,1337,1339],{"class":1338},"s7YZ4","const",[496,1341,1342],{"class":1242}," removed",[496,1344,1267],{"class":1338},[496,1346,1348],{"class":1347},"sOLd2"," Array",[496,1350,1351],{"class":502},"\u003C{ ",[496,1353,1262],{"class":1354},"stnAF",[496,1356,1267],{"class":1338},[496,1358,1359],{"class":1242}," string",[496,1361,1362],{"class":502},"; ",[496,1364,1282],{"class":1354},[496,1366,1267],{"class":1338},[496,1368,1359],{"class":1242},[496,1370,1371],{"class":502}," }> ",[496,1373,1374],{"class":1338},"=\n",[496,1376,1377,1380,1382,1386],{"class":498,"line":506},[496,1378,1379],{"class":1242},"  JSON",[496,1381,569],{"class":502},[496,1383,1385],{"class":1384},"sPO5f","parse",[496,1387,1388],{"class":502},"(data.listsRemoved)\n",[479,1390,1392],{"id":1391},"test",[469,1393,1391],{},[448,1395,1396],{},"Not subscribable — sent only when you use the test-fire button in the webhook dashboard to validate a receiver endpoint. Use it to confirm your endpoint reachability and signature verification before relying on live events.",[487,1398,1400],{"className":489,"code":1399,"language":491,"meta":492,"style":492},"{\n  \"message\": \"This is a test webhook from Owlat\",\n  \"webhookId\": \"\u003CId\u003C'webhooks'>>\",\n  \"webhookName\": \"\u003Cyour label>\"\n}\n",[469,1401,1402,1406,1417,1429,1439],{"__ignoreMap":492},[496,1403,1404],{"class":498,"line":499},[496,1405,503],{"class":502},[496,1407,1408,1410,1412,1415],{"class":498,"line":506},[496,1409,989],{"class":509},[496,1411,513],{"class":502},[496,1413,1414],{"class":516},"\"This is a test webhook from Owlat\"",[496,1416,520],{"class":502},[496,1418,1419,1422,1424,1427],{"class":498,"line":523},[496,1420,1421],{"class":509},"  \"webhookId\"",[496,1423,513],{"class":502},[496,1425,1426],{"class":516},"\"\u003CId\u003C'webhooks'>>\"",[496,1428,520],{"class":502},[496,1430,1431,1434,1436],{"class":498,"line":536},[496,1432,1433],{"class":509},"  \"webhookName\"",[496,1435,513],{"class":502},[496,1437,1438],{"class":516},"\"\u003Cyour label>\"\n",[496,1440,1441],{"class":498,"line":552},[496,1442,555],{"class":502},[479,1444,1446],{"id":1445},"payload-version-and-forward-compatibility","Payload version and forward-compatibility",[448,1448,1449,1450,1452],{},"The envelope carries no version field on the wire, but every delivery log row stores the ",[469,1451,471],{}," it was built with. Write your receiver defensively:",[557,1454,1455,1464,1470],{},[560,1456,1457,1460,1461,1463],{},[474,1458,1459],{},"Ignore unknown events."," New event literals may be added without a version bump; handlers that strictly reject unknown ",[469,1462,564],{}," values will break on upgrade.",[560,1465,1466,1469],{},[474,1467,1468],{},"Ignore unknown fields."," Additive fields within a shape are possible; do not fail on extras.",[560,1471,1472,1475,1476,1478,1479,1481,1482,569],{},[474,1473,1474],{},"Branch on type, not position."," Remember ",[469,1477,574],{}," is ISO-8601 on email\u002Fcontact events but ",[469,1480,1322],{}," is epoch milliseconds on ",[469,1483,1197],{},[448,1485,1486,1487,1489],{},"A future version 2 may relax the flat-primitive constraint and allow nested arrays\u002Fobjects (retiring the JSON-string encoding on ",[469,1488,1308],{},"). When that happens, the version will be bumped and both shapes documented.",[479,1491,1493],{"id":1492},"retry-behavior-and-delivery-logs","Retry behavior and delivery logs",[448,1495,1496,1497,1500],{},"Owlat treats any non-2xx response — or a network error, timeout, or a URL that resolves to a private\u002Flocal network — as a failed delivery and retries up to ",[474,1498,1499],{},"3 attempts"," total with backoff:",[1502,1503,1504,1508,1511,1515,1522,1526],"steps",{},[587,1505,1507],{"id":1506},"attempt-1","Attempt 1",[448,1509,1510],{},"Delivered immediately when the event fires.",[587,1512,1514],{"id":1513},"attempt-2","Attempt 2",[448,1516,1517,1518,1521],{},"Retried after ",[474,1519,1520],{},"1 minute"," if attempt 1 failed.",[587,1523,1525],{"id":1524},"attempt-3","Attempt 3",[448,1527,1517,1528,1531],{},[474,1529,1530],{},"5 minutes"," if attempt 2 failed. After this final attempt, the delivery is marked failed and not retried again.",[448,1533,1534,1535,1538],{},"Each request has a ",[474,1536,1537],{},"30-second timeout"," and follows no redirects. Every attempt is recorded in a delivery log with one of these statuses:",[595,1540,1541,1550],{},[598,1542,1543],{},[601,1544,1545,1548],{},[604,1546,1547],{},"Status",[604,1549,1133],{},[611,1551,1552,1562,1572,1582],{},[601,1553,1554,1559],{},[616,1555,1556],{},[469,1557,1558],{},"pending",[616,1560,1561],{},"Logged, scheduled, not yet attempted",[601,1563,1564,1569],{},[616,1565,1566],{},[469,1567,1568],{},"retrying",[616,1570,1571],{},"An attempt failed and another is scheduled",[601,1573,1574,1579],{},[616,1575,1576],{},[469,1577,1578],{},"success",[616,1580,1581],{},"Endpoint returned a 2xx response",[601,1583,1584,1589],{},[616,1585,1586],{},[469,1587,1588],{},"failed",[616,1590,1591],{},"All attempts exhausted, or the webhook was disabled\u002Fnot found",[448,1593,1594,1595,1598],{},"Logs capture the HTTP status code, a truncated response body (first 1000 characters), an error message on failure, and the per-attempt duration. Because Owlat retries on any non-2xx, your endpoint should ",[474,1596,1597],{},"acknowledge with a 2xx as soon as it has durably received the event"," and process asynchronously — and it should be idempotent, since a slow or flaky 2xx can still result in a duplicate delivery.",[479,1600,1602],{"id":1601},"related","Related",[1604,1605],"link-card",{"description":1606,"title":186,"to":185},"Configure outbound subscriptions, verify signatures, and review inbound provider routes.",[1604,1608],{"description":1609,"title":214,"to":213},"Create and manage the contacts that drive contact.created events.",[1604,1611],{"description":1612,"title":18,"to":17},"Subscription topics behind the topic.unsubscribed event.",[1614,1615,1616],"style",{},"html pre.shiki code .sYgZi, html code.shiki .sYgZi{--shiki-default:#24292E;--shiki-dark:#ADBAC7}html pre.shiki code .snmFh, html code.shiki .snmFh{--shiki-default:#005CC5;--shiki-dark:#8DDB8C}html pre.shiki code .s-HuK, html code.shiki .s-HuK{--shiki-default:#032F62;--shiki-dark:#96D0FF}html pre.shiki code .sDN9O, html code.shiki .sDN9O{--shiki-default:#6A737D;--shiki-dark:#768390}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sviXB, html code.shiki .sviXB{--shiki-default:#005CC5;--shiki-dark:#6CB6FF}html pre.shiki code .s74oq, html code.shiki .s74oq{--shiki-default:#005CC5;--shiki-dark:#F47067}html pre.shiki code .s7YZ4, html code.shiki .s7YZ4{--shiki-default:#D73A49;--shiki-dark:#F47067}html pre.shiki code .sOLd2, html code.shiki .sOLd2{--shiki-default:#6F42C1;--shiki-dark:#F69D50}html pre.shiki code .stnAF, html code.shiki .stnAF{--shiki-default:#E36209;--shiki-dark:#F69D50}html pre.shiki code .sPO5f, html code.shiki .sPO5f{--shiki-default:#6F42C1;--shiki-dark:#DCBDFB}",{"title":492,"searchDepth":506,"depth":506,"links":1618},[1619,1624,1632,1635,1638,1639,1640,1645],{"id":481,"depth":506,"text":482,"children":1620},[1621,1622],{"id":589,"depth":523,"text":590},{"id":690,"depth":523,"text":1623},"data shape constraints",{"id":724,"depth":506,"text":725,"children":1625},[1626,1627,1628,1629,1630,1631],{"id":731,"depth":523,"text":734},{"id":809,"depth":523,"text":568},{"id":848,"depth":523,"text":851},{"id":887,"depth":523,"text":890},{"id":939,"depth":523,"text":942},{"id":1011,"depth":523,"text":1014},{"id":1050,"depth":506,"text":1051,"children":1633},[1634],{"id":1054,"depth":523,"text":1057},{"id":1190,"depth":506,"text":1191,"children":1636},[1637],{"id":1194,"depth":523,"text":1197},{"id":1391,"depth":506,"text":1391},{"id":1445,"depth":506,"text":1446},{"id":1492,"depth":506,"text":1493,"children":1641},[1642,1643,1644],{"id":1506,"depth":523,"text":1507},{"id":1513,"depth":523,"text":1514},{"id":1524,"depth":523,"text":1525},{"id":1601,"depth":506,"text":1602},"md",{},true,{"title":194,"description":195},"2.api\u002F12.webhook-payloads","a8caebvTjUkhab35Xkbi4phaQqpGcBZgpHBfgHx1DNM",[1653,1655],{"title":190,"path":189,"stem":1654,"children":-1},"2.api\u002F11.public-endpoints",{"title":198,"path":197,"stem":1656,"children":-1},"2.api\u002F13.inbound-channels",1782846427013]