# prospect_response webhook event

Sent to a campaign's webhooks when a prospect replies.

Victoria AI sends this event as an HTTP `POST` with a JSON body when a prospect replies to a campaign. It goes to every enabled webhook on that campaign at the same time. Register one with [Create a webhook](https://docs.versionseven.ai/api-reference/campaigns/create-webhook).

## Delivery

- Your endpoint has 75 seconds to respond. An error status or a timeout counts as a failure.
- If every webhook on the campaign fails, the delivery is retried every 15 minutes, up to 5 attempts within 48 hours.
- A reply is normally delivered once per lead. If a later reply from the same lead is positive after an earlier one wasn't, it's delivered again with a new `idempotency_key`, because the message is part of the key.
- Retries of the same delivery carry the same `idempotency_key`. Record the keys you've processed and skip repeats.

## Signatures

When the webhook has a signing secret, each delivery carries `X-Signature-256: sha256=<hex>`: an HMAC-SHA256 of the raw request body, keyed with the secret. Recompute it over the exact bytes you received, before parsing the JSON. Set or rotate the secret with [Set or rotate a webhook secret](https://docs.versionseven.ai/api-reference/campaigns/rotate-webhook-secret).

## Request headers

| Header | Description |
| --- | --- |
| `Content-Type` | `application/json` |
| `X-Signature-256` | `sha256=` followed by the hex HMAC-SHA256 of the raw body, keyed with the webhook's secret. Only sent when the webhook has a secret. |

## Payload

- `event` (string, required, example `"prospect_response"`): Event type
- `idempotency_key` (string, required, exactly 64 characters, example `"f3a1c9d2b8e7460a91d0a25f3e7b4c1d6f8a92e0b4c1d6f8a92e0b4c1d6f8a92"`): SHA-256 hex digest (64 characters) of the sequence lead, campaign, channel and prospect message. Identical on every redelivery of the same reply; a different reply from the same prospect gets a new key
- `sequence_lead_id` (string · uuid, required, example `"550e8400-e29b-41d4-a716-446655440000"`): ID of the sequence lead this response relates to
- `timestamp` (string, required, example `"2025-01-14T19:30:00.123456+00:00"`): When the delivery was built: ISO 8601, UTC, with a `+00:00` offset and microseconds
- `channel` (string, required, example `"email"`): Communication channel: 'email' or 'linkedin'
- `sender` (object, required): The accounts assigned to send to this lead, keyed by channel. A channel is left out when no account is assigned, and the object is empty when the accounts can't be looked up.
  - `email` (object or null, optional): Present when the lead has an email account assigned
    - `account_id` (string, required, example `"xyz789-id"`): ID of the connected email account that sent the outreach.
    - `platform_username` (string, required, example `"jane@yourcompany.com"`): Account username (typically the address)
    - `email` (string, required, example `"jane@yourcompany.com"`): Sender email address
  - `linkedin` (object or null, optional): Present when the lead has a LinkedIn account assigned
    - `account_id` (string, required, example `"abc123-id"`): ID of the connected LinkedIn account that sent the outreach.
    - `platform_username` (string, required, example `"jane-smith-sdr"`): LinkedIn username/handle
- `lead` (object, required): The lead's details. A field the lead has no value for is `null`.
  - `annual_revenue` (integer or null, optional, example `5000000`)
  - `company` (string or null, optional, example `"Example Corp"`)
  - `custom_fields` (object, optional)
  - `email` (string or null, optional, example `"john.doe@example.com"`)
  - `employee_count` (integer or null, optional, example `50`)
  - `first_name` (string or null, optional, example `"John"`)
  - `industry` (string or null, optional, example `"Technology"`)
  - `last_name` (string or null, optional, example `"Doe"`)
  - `linkedin_profile` (string or null, optional, example `"https://linkedin.com/in/johndoe"`): The lead's LinkedIn profile URL
  - `title` (string or null, optional, example `"VP of Sales"`)
  - `website` (string or null, optional, example `"https://example.com"`): The lead's company website
- `ai_response` (object, required): The AI Appointment Setter's analysis of the reply. When the reply wasn't analyzed, every field except `goal` is `null`, and `goal` gives the reason.
  - `agent_action` (string or null, optional, example `"reply"`): What the agent did with the reply: 'reply', 'wait', 'nudge', 'escalate', 'close' or 'skip'
  - `agent_version` (integer or null, optional, example `2`): Present (as 2) when the Appointment Setter agent handled the reply; absent on legacy payloads. Feature-detect on this field
  - `asset_delivered` (boolean or null, optional, example `true`): Asset-first campaigns only: whether the page went out
  - `asset_url` (string or null, optional, example `"https://pages.example.com/p/abc123"`): Asset-first campaigns only: the personalised page that was sent
  - `complete` (boolean or null, optional, example `false`): `true` when the conversation has ended or should end, whether or not its goal was reached. When `agent_version` is `2`, it's `true` exactly when `conversation_status` is one of the `closed_` values.
  - `conversation_status` (string or null, optional, example `"awaiting_prospect"`): The conversation's state after this reply. `awaiting_prospect`: waiting for the prospect. `needs_human`: the AI Appointment Setter handed the conversation to your team. `human_owned`: someone on your team has taken it over. `closed_won`, `closed_lost`, `closed_no_response` or `closed_escalated`: the conversation has ended. A lead still on the older follow-up flow can show `awaiting_followup`. Handle values you don't recognize without failing.
  - `escalation_reason` (string or null, optional): Why the agent handed the conversation to a human, when it did
  - `first_message_mode` (string or null, optional, example `"asset"`): Asset-first campaigns only: how the first message was sent
  - `goal` (string or null, optional, example `"Schedule a demo"`): The campaign goal the responder is working toward, or the skip reason
  - `goal_status` (string or null, optional, example `"link_sent"`): Progress toward the meeting goal: 'not\_sent', 'link\_sent', 'soft\_commit', 'confirmed' or 'declined'
  - `out_of_office` (boolean or null, optional, example `false`)
  - `responder_message` (string or null, optional, example `"Thank you for your interest! I'd be happy to schedule a demo for you."`): The reply the responder sent, or null when nothing was sent
  - `sdr_brief` (string or null, optional, example `"Prospect expressed interest, recommend scheduling demo within 24 hours."`)
  - `sentiment` (string or null, optional, example `"positive"`): 'positive', 'neutral' or 'negative'
- `campaign` (string or null, optional, example `"Q1 2024 Outbound Campaign"`): The campaign's name. The payload doesn't include the campaign's ID.
- `conversation_owner` (string or null, optional, example `"victoria"`): Present only when the conversation has an owner: 'victoria' when Victoria's responder is handling replies, 'lp\_responder' when an external responder is. Receivers that reply to prospects themselves should stay out of conversations Victoria owns
- `prospect_message` (string or null, optional, example `"Hi, I'm interested in learning more about your product."`): The prospect's reply, as received
- `variation` (string or null, optional, example `"a"`): A/B arm the lead is in: 'a', 'b', or null when the lead has none

## Examples

### Email reply

```json
{
  "event": "prospect_response",
  "idempotency_key": "f3a1c9d2b8e7460a91d0a25f3e7b4c1d6f8a92e0b4c1d6f8a92e0b4c1d6f8a92",
  "sequence_lead_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2025-01-14T19:30:00.482913+00:00",
  "campaign": "Q1 2024 Outbound Campaign",
  "variation": "a",
  "channel": "email",
  "sender": {
    "email": {
      "account_id": "email-abc123",
      "platform_username": "jane@yourcompany.com",
      "email": "jane@yourcompany.com"
    }
  },
  "lead": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@example.com",
    "company": "Example Corp",
    "title": "VP of Sales",
    "linkedin_profile": "https://linkedin.com/in/johndoe",
    "annual_revenue": 5000000,
    "employee_count": 50,
    "industry": "Technology",
    "website": "https://example.com",
    "custom_fields": {
      "region": "North America",
      "product_interest": "Enterprise Plan"
    }
  },
  "prospect_message": "Hi, I'm interested in learning more about your product.",
  "ai_response": {
    "sentiment": "positive",
    "out_of_office": false,
    "complete": false,
    "goal": "Schedule a demo",
    "responder_message": "Thank you for your interest! I'd be happy to schedule a demo for you.",
    "sdr_brief": "Prospect expressed interest, recommend scheduling demo within 24 hours."
  }
}
```

### LinkedIn reply

```json
{
  "event": "prospect_response",
  "idempotency_key": "a7b2e5f9c1d4068b3e7f2a5c8d1e4b7a0c3f6e9b2d5a8c1f4e7b0d3a6c9f2e5b",
  "sequence_lead_id": "660f9511-f3a0-42e5-b827-557766551111",
  "timestamp": "2025-01-15T10:15:00.117204+00:00",
  "campaign": "Enterprise Tech Outreach",
  "variation": "b",
  "channel": "linkedin",
  "sender": {
    "linkedin": {
      "account_id": "li-def456",
      "platform_username": "alex-sdr-yourcompany"
    }
  },
  "lead": {
    "first_name": "Sarah",
    "last_name": "Chen",
    "email": "sarah.chen@techstartup.io",
    "company": "TechStartup Inc",
    "title": "CTO",
    "linkedin_profile": "https://linkedin.com/in/sarahchen",
    "annual_revenue": 12000000,
    "employee_count": 85,
    "industry": "Software",
    "website": "https://techstartup.io",
    "custom_fields": {
      "region": "West Coast",
      "product_interest": "API Integration"
    }
  },
  "prospect_message": "This looks interesting. Can you send me some case studies?",
  "ai_response": {
    "sentiment": "positive",
    "out_of_office": false,
    "complete": false,
    "goal": "Share case studies",
    "responder_message": "Absolutely! I'll send over a few case studies from similar companies in your industry.",
    "sdr_brief": "Prospect requesting more information, warm lead showing buying signals."
  },
  "conversation_owner": "victoria"
}
```

### Out of office

```json
{
  "event": "prospect_response",
  "idempotency_key": "b8c3f6e0d2e5179c4f8a3b6d9e2f5a8c1b4d7e0a3c6f9b2e5d8a1c4f7b0d3e6a",
  "sequence_lead_id": "770a0622-04b1-43f6-8938-668877662222",
  "timestamp": "2025-01-16T14:45:00.903316+00:00",
  "campaign": "SMB Growth Initiative",
  "variation": "a",
  "channel": "email",
  "sender": {
    "linkedin": {
      "account_id": "li-ghi789",
      "platform_username": "morgan-sdr-yourcompany"
    },
    "email": {
      "account_id": "email-jkl012",
      "platform_username": "morgan@yourcompany.com",
      "email": "morgan@yourcompany.com"
    }
  },
  "lead": {
    "first_name": "Michael",
    "last_name": "Roberts",
    "email": "m.roberts@retailco.com",
    "company": "RetailCo",
    "title": "Director of Operations",
    "linkedin_profile": "https://linkedin.com/in/michaelroberts",
    "annual_revenue": 25000000,
    "employee_count": 200,
    "industry": "Retail",
    "website": "https://retailco.com",
    "custom_fields": {
      "region": "Midwest",
      "product_interest": "Automation Tools"
    }
  },
  "prospect_message": "I'll be out of office until January 20th. Please reach out then.",
  "ai_response": {
    "sentiment": "neutral",
    "out_of_office": true,
    "complete": false,
    "goal": "Follow up after OOO",
    "responder_message": null,
    "sdr_brief": "Prospect is OOO until Jan 20. Schedule follow-up for that date.",
    "agent_version": 2,
    "agent_action": "wait",
    "conversation_status": "awaiting_followup",
    "goal_status": "not_sent",
    "escalation_reason": null
  }
}
```
