Features

Automations & Webhooks

Automations let you trigger actions when specific events occur in Spectacle. Define rules like "when a contact enters an audience, send a webhook" to connect Spectacle with your external systems in real-time.

Overview

Automations follow a simple "When... Then..." model. When a trigger event occurs (like a contact entering an audience), Spectacle automatically performs an action (like sending a webhook to your server). This enables you to build custom integrations and workflows without writing polling code.

Trigger Events

Contact Events

  • Entered Audience - Fires when a contact matches your audience criteria
  • Exited Audience - Fires when a contact no longer matches
  • Scored As Not Qualified - Fires when lead scoring marks a contact as not qualified
  • Scored As Somewhat Qualified - Fires when lead scoring marks a contact as somewhat qualified
  • Scored As Highly Qualified - Fires when lead scoring marks a contact as highly qualified

Company Events

  • Entered Audience - Fires when a company matches your audience criteria
  • Exited Audience - Fires when a company no longer matches
  • Unmasked By Lens - Fires when Lens identifies a previously anonymous company
  • Scored As Not Qualified / Somewhat Qualified / Highly Qualified - Fires based on company lead scores

Destinations

Webhooks

Send HTTP POST requests to any URL when events occur. Webhooks include signed payloads for security verification. See Webhook Reference below for payload structure and signature details.

Slack

Post notifications to a Slack channel when events occur. Requires connecting your Slack workspace in integrations.

Setting Up Automations

Step 1: Choose Your Trigger

Navigate to Automations and click "New automation". Select the event that should trigger your automation.

Step 2: Select an Audience

For audience-based events (entered/exited audience), select which audience should trigger the automation.

Step 3: Configure Your Destination

  • For Webhooks - Enter the URL that should receive the POST request
  • For Slack - Select the channel to post notifications to

Step 4: Test and Save

Use the "Send test" button to verify your endpoint receives the payload correctly. Test events include "isTest": true in the payload. Once verified, save your automation.

Webhook Reference

Payload Structure

{
  "event": "Contact Entered Audience",
  "automationId": "atm_abc123",
  "deliveryId": "audl_xyz789",
  "isTest": false,
  "workspaceId": "wsp_workspace123",
  "payload": {
    "userId": "user_123",
    "email": "user@example.com",
    "firstName": "Jane",
    "lastName": "Doe",
    "traits": {}
  },
  "timestamp": "2024-01-09T12:34:56.789Z"
}

For company events, the payload contains companyId, name, domain, and traits instead.

Signature Verification

Spectacle signs all webhook requests with your workspace's signing secret using HMAC-SHA256. Each request includes a Spectacle-Signature header:

Spectacle-Signature: t=1492774577,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

To verify:

  1. Extract the timestamp (t=) and signature (v1=) from the header
  2. Compute HMAC-SHA256(secret, "${timestamp}.${rawJsonBody}")
  3. Compare your computed signature with the provided one using timing-safe comparison
  4. Verify the timestamp is within 5 minutes to prevent replay attacks

Example (TypeScript)

import crypto from 'crypto'
import express, { Request, Response } from 'express'

const app = express()

interface RequestWithRawBody extends Request {
  rawBody?: string
}

// IMPORTANT: Use raw body for signature verification
app.use(
  express.json({
    verify: (req: RequestWithRawBody, res, buf) => {
      req.rawBody = buf.toString('utf8')
    },
  }),
)

const WEBHOOK_SECRET = process.env.SPECTACLE_WEBHOOK_SECRET!

function verifyWebhookSignature(
  rawBody: string,
  signatureHeader: string,
): boolean {
  const parts = signatureHeader.split(',')
  const timestamp = parts[0].replace('t=', '')
  const signature = parts[1].replace('v1=', '')

  // Verify timestamp is recent (5 minutes)
  const currentTime = Math.floor(Date.now() / 1000)
  if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
    return false
  }

  // Compute expected signature
  const signedPayload = `${timestamp}.${rawBody}`
  const computedSignature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(signedPayload)
    .digest('hex')

  // Use timing-safe comparison
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(computedSignature, 'hex'),
  )
}

app.post('/webhook', (req: RequestWithRawBody, res: Response) => {
  const signatureHeader = req.headers['spectacle-signature'] as string

  if (!signatureHeader || !req.rawBody) {
    return res.status(401).send('Unauthorized')
  }

  if (!verifyWebhookSignature(req.rawBody, signatureHeader)) {
    return res.status(401).send('Unauthorized')
  }

  // Process webhook
  console.log('Valid webhook:', req.body.event)
  res.status(200).send('OK')
})

app.listen(3000)

Getting Your Signing Secret

  1. Go to your workspace's developer settings
  2. Navigate to the Developer section
  3. Copy your webhook signing secret (starts with whsec_)

Keep your signing secret secure and never commit it to version control.

Request Timeout

Webhook requests have a 20-second timeout. Ensure your endpoint responds quickly with a 200 status code. For long-running tasks, acknowledge the webhook immediately and process asynchronously.

Retries

If a delivery fails, Spectacle automatically retries with exponential backoff. A delivery is considered failed if:

  • Your endpoint returns a non-2xx status code
  • The request times out (20 seconds)
  • A network error occurs (connection refused, DNS failure, etc.)

Retry schedule:

AttemptDelay after failure
1st2 minutes
2nd5 minutes
3rd1 hour
4th6 hours
5th12 hours

After 5 failed attempts, the delivery is marked as permanently failed. Test deliveries (isTest: true) are not retried.

Debugging Deliveries

The Delivery Debugger shows a history of all delivery attempts for your workspace. Use it to troubleshoot failed webhooks and verify successful deliveries.

For each attempt, you can see:

  • Status - Whether the delivery succeeded or failed
  • Destination - The webhook URL or Slack channel
  • Timestamp - When the attempt was made
  • Attempt number - Which retry attempt (1-5)

Click any row to expand and view detailed information:

  • Error message - For failed deliveries, the specific error (e.g., "HTTP 500", timeout)
  • Request headers - Including the Spectacle-Signature header
  • Request body - The full JSON payload sent
  • Response status - The HTTP status code returned
  • Response body - What your server returned (truncated to 1000 characters)

Delivery Options

  • Instant - Delivered immediately when the event occurs
  • Batched - Aggregated and delivered at intervals (15-minute, hourly, or daily)

Batched delivery is useful for high-volume events where you prefer consolidated updates over real-time notifications.

Check our pricing page for feature availability.

Previous
Lens (anonymous company identification)