> ## Documentation Index
> Fetch the complete documentation index at: https://help.hoopai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive real-time event notifications from HoopAI when contacts, appointments, messages, and other resources change.

Webhooks let your integration react to events in HoopAI in real time — no polling required. When something happens (a contact is created, an appointment is booked, a payment is received), HoopAI sends an HTTP POST request to your endpoint.

## How webhooks work

```mermaid theme={null}
sequenceDiagram
    participant User as HoopAI User
    participant Platform as HoopAI Platform
    participant App as Your App

    User->>Platform: Creates a contact
    Platform->>App: POST /your-webhook-url
    Note right of App: { "type": "ContactCreate", "locationId": "...", "body": { ... } }
    App->>Platform: 200 OK
```

1. An event occurs in HoopAI (e.g., contact created, appointment booked)
2. HoopAI sends a `POST` request to your registered webhook URL
3. Your app processes the event and responds with a `2xx` status code
4. If your endpoint doesn't respond with `2xx`, HoopAI retries the delivery

## Setting up webhooks

### For marketplace apps

Register webhook subscriptions when your OAuth app is installed. Use the App Marketplace developer portal to configure which events your app listens to.

### For private integrations

<Steps>
  <Step title="Go to webhook settings">
    Navigate to **Settings > Webhooks** in your HoopAI account.
  </Step>

  <Step title="Add a webhook URL">
    Enter your endpoint URL and select the events you want to receive.
  </Step>

  <Step title="Test the webhook">
    Click **Send Test** to verify your endpoint receives the payload correctly.
  </Step>
</Steps>

## Available events

| Event                    | Trigger                                      |
| ------------------------ | -------------------------------------------- |
| `ContactCreate`          | A new contact is created                     |
| `ContactUpdate`          | A contact is updated                         |
| `ContactDelete`          | A contact is deleted                         |
| `ContactTagUpdate`       | Tags are added or removed from a contact     |
| `ContactDndUpdate`       | Do-not-disturb settings change               |
| `AppointmentCreate`      | An appointment is booked                     |
| `AppointmentUpdate`      | An appointment is modified                   |
| `AppointmentDelete`      | An appointment is cancelled                  |
| `OpportunityCreate`      | A new opportunity is created                 |
| `OpportunityUpdate`      | An opportunity is updated                    |
| `OpportunityStageUpdate` | An opportunity moves to a new pipeline stage |
| `InvoiceCreate`          | An invoice is created                        |
| `InvoicePaid`            | An invoice is fully paid                     |
| `InboundMessage`         | A message is received from a contact         |
| `OutboundMessage`        | A message is sent to a contact               |
| `NoteCreate`             | A note is added to a contact                 |
| `TaskCreate`             | A task is created                            |

See the [full webhook events reference](/api-reference/webhooks/overview) for every event type and its payload.

## Webhook payload structure

Every webhook payload follows this structure:

```json theme={null}
{
  "type": "ContactCreate",
  "locationId": "loc_abc123",
  "body": {
    "id": "contact_xyz789",
    "name": "Jane Smith",
    "email": "jane@example.com",
    "phone": "+15551234567",
    "tags": ["lead"],
    "dateAdded": "2025-03-01T14:30:00.000Z"
  }
}
```

| Field        | Description                            |
| ------------ | -------------------------------------- |
| `type`       | The event name (e.g., `ContactCreate`) |
| `locationId` | The account where the event occurred   |
| `body`       | The event payload with resource data   |

## Verifying webhook signatures

Always verify that incoming webhooks are genuinely from HoopAI by checking the signature header.

```javascript theme={null}
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hash = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return hash === signature;
}

// In your webhook handler
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-hook-signature'];
  const isValid = verifyWebhook(JSON.stringify(req.body), signature, YOUR_WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  // Process the event
  console.log('Event:', req.body.type);
  res.status(200).send('OK');
});
```

See the [webhook authentication guide](/api-reference/oauth/webhook-authentication) for details.

## Best practices

<AccordionGroup>
  <Accordion title="Respond quickly">
    Return a `2xx` status code within **5 seconds**. If your processing takes longer, accept the webhook and process it asynchronously (e.g., with a queue).
  </Accordion>

  <Accordion title="Handle duplicates">
    Webhooks may be delivered more than once. Use the event ID or resource ID to deduplicate in your handler.
  </Accordion>

  <Accordion title="Use HTTPS">
    Always use HTTPS endpoints for webhook URLs to ensure payloads are encrypted in transit.
  </Accordion>

  <Accordion title="Monitor failures">
    Track webhook delivery failures and set up alerts. If your endpoint is down, events will be retried but eventually dropped.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Webhook events reference" icon="list" href="/api-reference/webhooks/overview">
    See every event type and its payload
  </Card>

  <Card title="Webhook authentication" icon="shield" href="/api-reference/oauth/webhook-authentication">
    Verify webhook signatures
  </Card>
</CardGroup>
