Webhooks
View as Markdown

Receiving webhooks

Register a webhook on a campaign to hear when a prospect replies, and handle deliveries, retries and duplicates.

Last updated

Instead of polling for replies, register a webhook on a campaign. When a prospect replies, Victoria AI sends a prospect_response event to your URL, with the reply, the lead, the campaign, and the AI Appointment Setter's read of the reply.

1. Build an endpoint

Your endpoint must:

  • Accept POST requests with a JSON body over HTTPS, at an address reachable from the public internet.
  • Respond with a 2xx status within 75 seconds. Acknowledge the delivery first, then do slow work such as CRM updates.
  • Check the X-Signature-256 header before trusting the body. See Verifying signatures.

To build and test it before a live campaign sends anything, use the sample deliveries from GET /v1/webhooks/examples.

2. Register the webhook

Register your URL on a campaign with POST /v1/campaigns/{campaign_id}/webhooks. Send a secret of at least 16 characters to sign deliveries with a value you already hold, or leave it out and one is generated:

curl -X POST https://api.versionseven.ai/v1/campaigns/550e8400-e29b-41d4-a716-446655440000/webhooks \
  -H "Authorization: Bearer $VICTORIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"webhook_url": "https://example.com/victoria/webhooks"}'

The response includes the webhook_id, and the secret when one was generated.

A generated secret is returned only in this response. Store it before you discard the response. If you lose it, set a new one with POST /v1/campaigns/{campaign_id}/webhooks/{webhook_id}/secret.

ResponseWhen
201The webhook was created.
200A disabled webhook for the same URL was enabled again.
409 DUPLICATE_WEBHOOKThe URL is already active on this campaign.
400 INVALID_WEBHOOK_URLThe URL isn't HTTPS, or doesn't resolve to a public address.

A campaign can have several webhooks, and each delivery goes to all of them at the same time.

A lead's reply is normally delivered once per campaign, not once per message. The exception is described under Retries and duplicates.

3. Handle deliveries

Each delivery is a POST with Content-Type: application/json. A shortened example:

{
  "event": "prospect_response",
  "idempotency_key": "f3a1c9d2b8e7460a91d0a25f3e7b4c1d6f8a92e0b4c1d6f8a92e0b4c1d6f8a92",
  "sequence_lead_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2025-01-14T19:30:00+00:00",
  "campaign": "Q1 2024 Outbound Campaign",
  "channel": "email",
  "prospect_message": "Hi, I'm interested in learning more about your product.",
  "ai_response": {
    "sentiment": "positive",
    "out_of_office": false,
    "sdr_brief": "Prospect expressed interest, recommend scheduling demo within 24 hours."
  }
}

The event reference documents every field, including the lead, the sending account and the rest of ai_response.

Retries and duplicates

  • A delivery fails when your endpoint answers with an error status or doesn't respond within 75 seconds.
  • If every webhook on the campaign fails, the delivery is retried every 15 minutes, up to 5 attempts within 48 hours.
  • A retry carries the same idempotency_key as the original delivery. Record the keys you've processed and skip any you've already seen.
  • A later reply from the same lead can arrive as a new event with a new idempotency_key, for example when a prospect who first asked a question then says yes.

Managing webhooks

Deleting a webhook disables it rather than destroying it. Registering the same URL again re-enables it, along with its existing signing secret.