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
POSTrequests with a JSON body over HTTPS, at an address reachable from the public internet. - Respond with a
2xxstatus within 75 seconds. Acknowledge the delivery first, then do slow work such as CRM updates. - Check the
X-Signature-256header 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.
| Response | When |
|---|---|
201 | The webhook was created. |
200 | A disabled webhook for the same URL was enabled again. |
409 DUPLICATE_WEBHOOK | The URL is already active on this campaign. |
400 INVALID_WEBHOOK_URL | The 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_keyas 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
| Task | Endpoint |
|---|---|
| List a campaign's webhooks | GET /v1/campaigns/{campaign_id}/webhooks |
| Stop deliveries to a webhook | DELETE /v1/campaigns/{campaign_id}/webhooks/{webhook_id} |
| Set or rotate the signing secret | POST /v1/campaigns/{campaign_id}/webhooks/{webhook_id}/secret |
Deleting a webhook disables it rather than destroying it. Registering the same URL again re-enables it, along with its existing signing secret.