name: Walnut Webhooks description: >- Walnut's outbound event surface. Two session-completion events are published with complete field tables and full example payloads: demo_session_finished and playlist_session_finished. Deliveries are HTTP POST with application/json, optionally signed with HMAC-SHA256 in an X-Walnut-Signature header, retried up to three times with exponential backoff, and can arrive out of order. Walnut publishes NO AsyncAPI document, no event catalog endpoint and no subscription API — webhooks are configured by an Admin in the application UI at Settings > Webhooks. This file is the webhook catalog, captured from the provider's own documentation; no AsyncAPI spec has been authored on Walnut's behalf. generated: '2026-08-13' method: searched source: https://help.walnut.io/help/api/webhooks docs: https://help.walnut.io/help/api/webhooks asyncapi_published: false asyncapi_probe: - url: https://help.walnut.io/openapi.yaml status: 404 - url: https://customer-api.teamwalnut.com/openapi.json status: 403 - url: https://app.teamwalnut.com/openapi.json status: 404 asyncapi_note: >- No AsyncAPI, event-catalog or CloudEvents document is served on any Walnut host. The event surface below is transcribed from Walnut's published payload tables and example bodies. configuration: where: Walnut application, Settings > Webhooks api_managed: false required_role: Admin actions: - Create a webhook (endpoint URL) - Add signature verification (shared signing key) - Send a test event - Test connection - Edit - Reset key - Disable (toggle off) - Delete note: >- There is no API for creating, listing or rotating webhook subscriptions. Every operation is a click in the application UI. delivery: transport: HTTP POST content_type: application/json expected_response: HTTP 200 or 201 timeout_seconds: 30 retries: 3 retry_strategy: exponential backoff ordering_guaranteed: false ordering_note: >- Each event retries independently, so deliveries can arrive out of order. Walnut instructs consumers to build idempotent handlers and deduplicate on session_id + event. latency: >- Demo session events can take up to two hours, because some demo metrics are calculated after the session ends and Walnut only sends once the full payload is available. endpoint_requirements: - Must be publicly accessible. - Must accept application/json POST bodies. security: signature_header: X-Walnut-Signature algorithm: HMAC-SHA256 encoding: lowercase hexadecimal signed_content: the raw request body exactly as received key_management: >- Shared key per webhook, generated by Walnut. "Reset key" issues a new one and immediately invalidates the old one, so the receiving endpoint must be updated at the same moment. optional: true optional_note: >- Signature verification is opt-in. Walnut recommends it because a public endpoint can be reached by anyone, but a webhook created without it accepts unsigned deliveries. replay_protection: false replay_note: No timestamp header, nonce or tolerance window is documented, so signed replays are not prevented. events: - name: demo_session_finished summary: Engagement data for a single completed interactive demo session. envelope: event: demo_session_finished timestamp: ISO 8601 datetime the event was logged and sent data: the demo session object payload_fields: - name: demo.id type: string (UUID) description: Unique identifier for the demo instance. - name: demo.name type: string description: Name of the demo. - name: demo.template_id type: string (UUID) description: ID of the template used to create the demo. - name: demo.template_name type: string description: Name of the source template. - name: demo.url type: string (URL) description: Direct URL to the demo on app.teamwalnut.com/player/. - name: demo_engagement.fab_clicks type: integer description: Floating action button clicks during the session. - name: demo_engagement.guides_completion_rate type: integer (percentage) description: Percentage of guides completed in the session. - name: demo_engagement.last_guide_shown type: string or null description: Last guide shown during the session. - name: demo_engagement.last_section_viewed type: string or null description: Last section or screen viewed. - name: demo_engagement.screen_completion_rate type: integer (percentage) description: Percentage of demo screens completed by the viewer. - name: demo_engagement.session_duration type: integer (seconds) description: Total demo session duration. - name: session_id type: string (UUID) description: Unique identifier for the session. Use with `event` for deduplication. - name: session_started type: datetime (ISO 8601) description: When the session began. - name: user.email type: string (email) description: Viewer email address, when available. - name: user.user_agent type: string description: Browser and device user agent string. field_count: 15 pii: true pii_note: Carries viewer email address and user agent. - name: playlist_session_finished summary: >- Session data for a playlist experience, which may bundle demos, videos, PDFs and other assets. Carries playlist-level information plus an array of the individual items available in the experience. envelope: event: playlist_session_finished timestamp: ISO 8601 datetime the event was logged and sent is_test: boolean, true when sent as a test payload data: the playlist session object payload_fields: - name: playlist.id type: string (UUID) description: Unique identifier for the playlist. - name: playlist.name type: string description: Name of the playlist. - name: playlist.description type: string description: Description of the playlist. - name: playlist.url type: string (URL) description: Direct link to the playlist. - name: items[].id type: string description: Unique identifier for an item inside the playlist. - name: items[].name type: string description: Name of the playlist item. - name: items[].description type: string description: Description of the playlist item. - name: items[].type type: string description: Asset type — video, pdf, demo, and similar. - name: items[].duration_secs type: integer description: Duration of the item in seconds, when applicable. - name: items[].number_of_views type: integer description: Total views recorded for the item. - name: items[].position type: integer description: Order of the item within the playlist. - name: items[].selected type: boolean description: Whether the item was selected in the session context. - name: items[].visited type: boolean description: Whether the item was visited during the session. - name: items[].demo_id type: string or null description: Demo ID for the item, when the item is tied to a demo. - name: items[].file_url type: string (URL) description: Source file URL for the item, when available. - name: items[].screenshot_uri type: string (URL) description: Screenshot or thumbnail URL for the item. - name: session_id type: string (UUID) description: Unique identifier for the playlist session. - name: session_started type: datetime (ISO 8601) description: When the session began. - name: session_ended type: datetime (ISO 8601) description: When the session ended. - name: session_duration_secs type: integer (seconds) description: Total playlist session duration. - name: user.email type: string (email) description: Viewer email address, when available. - name: user.domain type: string description: Viewer's organization domain. - name: user.identification_method type: string description: How Walnut identified the viewer, e.g. email_gate. - name: user.ip type: string description: Viewer IP address. - name: user.type type: string description: Viewer type classification, e.g. external. - name: user.user_agent type: string description: Browser and device user agent string. field_count: 26 pii: true pii_note: Carries viewer email address, organization domain, IP address and user agent. event_count: 2 testing: test_event: true test_event_control: '"Send a test event" button in Settings > Webhooks' test_flag: is_test test_flag_note: >- Documented on the playlist session payload. The demo session example does not show it. gaps: - No AsyncAPI, CloudEvents or JSON Schema document for either payload. - No API to create, list, rotate or delete webhook subscriptions — UI only. - >- No event-type selection is documented. Both events appear to be sent to any configured endpoint; there is no subscribe-to-specific-events control in the published guide. - No delivery-log, replay or redrive facility is documented. - No timestamp/nonce header, so a captured signed delivery can be replayed. - >- The two payload shapes do not agree with each other or with the Customer Data API. Webhooks use nested objects (demo.id, user.email); the REST API uses flat snake_case (demo_id, user_email); the webhook demo payload has no company_id, geography or lead-form fields; the REST session object has no template_id, fab_clicks or guides_completion_rate. A consumer joining the two surfaces must map fields by hand.