Skip to content
Listener.comDevelopers

Set up an endpoint

Register a webhook URL, choose its events, store the secret and send a test.

2 min read

You can manage endpoints in Settings → Developers → Webhooks in either app, or through the API with the webhooks:write scope. Both use the same endpoints, so anything you create in one shows up in the other.

1. Build a receiver#

Your endpoint must:

  • Accept POST requests with a JSON body over HTTPS.
  • Read the raw body (before JSON parsing) so you can verify the signature.
  • Return a 2xx status within 10 seconds. Redirects are not followed and count as failures.

Do the slow work after responding: put the event on a queue and return 200 straight away.

2. Register it#

curl https://api.listener.com/v1/webhook-endpoints \
  -H "Authorization: Bearer $LISTENER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/listener",
    "enabled_events": ["campaign.created", "campaign.updated", "campaign.status_changed"],
    "description": "Campaign sync"
  }'
  • enabled_events is a list of event types, or ["*"] for every type, including types added later.
  • The response includes the signing secret (whsec_…). Store it in your secrets manager. Lists and reads show only its last four characters; GET /v1/webhook-endpoints/{id}/secret reveals it again and needs webhooks:write, because the secret lets its holder forge deliveries.
  • A workspace can have up to 16 endpoints, disabled ones included.

URL rules#

URLs must use https://, carry no credentials or fragment, and must not resolve to private, loopback, link-local or other internal addresses. The check runs when you save the endpoint and again before every delivery. To receive webhooks on your laptop, expose your local server through a tunnel such as ngrok or cloudflared and register the tunnel’s HTTPS URL.

3. Send a test event#

curl
curl -X POST https://api.listener.com/v1/webhook-endpoints/we_5Rk2LqP9xT1m/test \
  -H "Authorization: Bearer $LISTENER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event_type": "campaign.created"}'

Listener sends a test event right away and returns the delivery, including your endpoint’s response status. Without event_type it sends webhook_endpoint.test; with one, it sends that type’s catalog example with data.test: true. Test deliveries are signed like real ones but are not retried and never count against the endpoint’s health. Use them to check signature verification end to end without changing any data.

Managing endpoints#

ActionRequest
List endpointsGET /v1/webhook-endpoints
Change URL, events or descriptionPATCH /v1/webhook-endpoints/{id}
Pause or resumePATCH /v1/webhook-endpoints/{id} with {"disabled": true} or false
Reveal the secretGET /v1/webhook-endpoints/{id}/secret
Rotate the secretPOST /v1/webhook-endpoints/{id}/roll-secret
See recent deliveriesGET /v1/webhook-endpoints/{id}/deliveries
Redeliver one nowPOST /v1/webhook-deliveries/{id}/retry
DeleteDELETE /v1/webhook-endpoints/{id}

The Webhooks tab in the app shows the same delivery log with the request and response of each attempt.

Rotating the secret#

roll-secret returns a new secret. The previous secret keeps signing for 24 hours by default (expire_previous_in_hours, 0 to 168; the response says when in expires_previous_at), and during that time every delivery carries two v1 signatures, one per secret. Deploy the new secret, and verification keeps passing throughout. See Verify signatures.