---
title: Webhooks
subtitle: >-
  Configure webhook subscriptions to receive real-time event notifications from
  Close.
slug: /api/resources/webhooks
---

Webhooks allow a subscription URL to be configured that we will POST event data
to as it is added to the [Event Log](/api/resources/events). Each subscription
is configured to trigger when an event matches a set of
[object types and actions](/api/resources/events).

Here is an example of the Webhook data for an opportunity that was won. This
would be sent to the URL you provide using a `POST` request:

```json
{
  "event": {
    "date_created": "2019-01-15T12:48:23.395000",
    "meta": {
      "request_method": "PUT",
      "request_path": "/api/v1/opportunity/oppo_7H4sjNso7FyBFaeR3RXi5PMJbilfo0c6UPCxsJtEhCO/"
    },
    "id": "ev_2sYKRjcrA79yKxi3S4Crd7",
    "action": "updated",
    "date_updated": "2019-01-15T12:48:23.395000",
    "changed_fields": [
      "confidence",
      "date_updated",
      "status_id",
      "status_label",
      "status_type"
    ],
    "previous_data": {
      "status_type": "active",
      "confidence": 70,
      "date_updated": "2019-01-15T12:47:39.873000+00:00",
      "status_id": "stat_3FD9DnGUCJzccBKTh8LiiKoyVPpMJsOkJdcGoA5AYKH",
      "status_label": "Active"
    },
    "organization_id": "orga_XbVPx5fFbKlYTz9PW5Ih1XDhViV10YihIaEgMEb6fVW",
    "data": {
      "contact_name": "Mr. Jones",
      "user_name": "Joe Kemp",
      "value_period": "one_time",
      "updated_by_name": "Joe Kemp",
      "date_created": "2019-01-15T12:41:24.496000+00:00",
      "user_id": "user_N6KhMpzHRCYQHdn4gRNIFNN5JExnsrprKA6ekxM63XA",
      "updated_by": "user_N6KhMpzHRCYQHdn4gRNIFNN5JExnsrprKA6ekxM63XA",
      "value_currency": "USD",
      "organization_id": "orga_XbVPx5fFbKlYTz9PW5Ih1XDhViV10YihIaEgMEb6fVW",
      "status_label": "Won",
      "contact_id": "cont_BwlwYQkIP6AooiXP1CMvc6Zbb5gGh2gPu4dqIDlDrII",
      "status_type": "won",
      "created_by_name": "Joe Kemp",
      "id": "oppo_8H4sjNso7FyBFaeR3RXi5PMJbilfo0c6UPCxsJtEhCO",
      "lead_name": "KLine",
      "date_lost": null,
      "note": "",
      "date_updated": "2019-01-15T12:48:23.392000+00:00",
      "status_id": "stat_wMS9M6HC2O3CSEOzF5g2vEGt6RM5R3RfhIQixdnmjf2",
      "value": 100000,
      "created_by": "user_N6KhMpzHRCYQHdn4gRNIFNN5JExnsrprKA6ekxM63XA",
      "value_formatted": "$1,000",
      "date_won": "2019-01-15",
      "lead_id": "lead_zwqYhEFwzPyfCErS8uQ77is2wFLvr9BgVi6cTfbFM68",
      "confidence": 100
    },
    "request_id": "req_4S2L8JTBAA1OUS74SVmfbN",
    "object_id": "oppo_7H4sjNso7FyBFaeR3RXi5PMJbilfo0c6UPCxsJtEhCO",
    "user_id": "user_N6KhMpzHRCYQHdn4gRNIFNN5JExnsrprKA6ekxM63XA",
    "object_type": "opportunity",
    "lead_id": "lead_zwqYhEFwzPyfCErS8uQ77is2wFLvr9BgVi6cTfbFM68"
  },
  "subscription_id": "whsub_8AmjKCZYT3zI8eZoi4HhFC"
}
```

### Webhook delivery

- Failed deliveries are retried with a retry interval that exponentially backs
  off up to every 20 minutes. They will be retried up to 72 hours before being
  dropped.
- Event ordering is not guaranteed due to
  [event consolidation](/api/resources/events#event-consolidation), delivery
  parallelism/retries and other factors.
- A subscription will automatically be paused and its queue cleared when one of
  following happens:
  - Event queue reaches 100,000 backlogged events. Warning emails will be sent
    to admins when there is more than 80,000 backlogged events.
  - All event delivery fails for 3 days. Warning emails will be sent to admins
    before the subscription is paused.
- Email notifications are sent to admins when a subscription is paused.
- Paused subscriptions must be manually re-activated via the API before we will
  attempt to deliver events again.
- We recommend processing Webhook events asynchronously meaning that you queue
  them locally before trying to process the payload. This will ensure we are
  always able to deliver the event and avoid the possibility of subscriptions
  getting paused because the max queue length is reached.
- If your application needs to reprocess historical events, you can access them
  via the event log API for up to 30 days.
- For `updated` or `deleted` actions the webhook will be called after the
  [consolidation delay](/api/resources/events#event-consolidation).
- Event updates are written immediately to the event log during the
  consolidation period so if you query the event log directly you may see events
  that you haven't received a webhook notification for yet.

### Data management

- Users with the Admin role can manage subscriptions for all users in the
  organization. Non-admin users can only modify subscriptions created by them.
- All data is delivered in the Webhook event even for non-admin users since they
  would have access to the same data via the application at delivery time.
- We recommend using https to protect your data during delivery. SSL certificate
  validation is enabled by default but can be disabled via the `verify_ssl`
  field.

### Webhook signatures

The subscription API's POST response includes a `signature_key` value that will
be used to sign Webhooks for the subscription. The signature and signing
timestamp is available in the following two headers of each POST request to your
endpoint.

```json
close-sig-hash: aa4fea8d4b74a0790e6b0dc2214db9d4d7651cb3e23f53caea499defd71ee431
close-sig-timestamp: 1544271440
```

The signature in the `close-sig-hash` header is the sha256 HMAC of the
`close-sig-timestamp` and payload concatenated. The following Python 3 example
code demonstrates how the signture can be verified.

```python
key = '058bfb6a3d8cfdc4da7c3be5901b16ae11da982b46a25fb2cd7016e97a140a1c'
data = headers['close-sig-timestamp'] + payload
signature = hmac.new(bytearray.fromhex(key), data.encode('utf-8'), hashlib.sha256).hexdigest()
valid = hmac.compare_digest(headers['close-sig-hash'], signature)  # Will be True if sigs match
```

See the [Subscription API](api:GET/webhook/) documentation for
the details of managing Webhook subscriptions.

### Limits

The maximum number of webhook subscriptions per organization is 40. However, we
allow a higher limit of webhook subscriptions to specific automation platforms
(up to a total of 500 subscriptions).

These platforms are:

- [Zapier](https://zapier.com/)
- [Backendless](https://backendless.com/)
- [Integrately](https://integrately.com/)
- [Customer.io Journeys Track API](https://docs.customer.io/api/track/)
