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

# Webhooks

Subscribe to payroll updates and get notified instantly.

## Overview

Webhooks provide real-time notifications to your system when events take place, or new data is added, updated, or deleted.

#### Example scenarios:

* A new payroll connection is attempted.
* Data retrieval from a recently connected account has completed.
* New data is available for a connected account.

<Note>
  **Webhooks are not specific to individual users or accounts.**

  <Note>
    For example, if you are subscribed to the `identities.added` webhook, new identity information added to *any account* of *any user* will cause the webhook to be delivered.
  </Note>

  #### Additional resources:
</Note>

[Webhooks Reference](/api-reference/users-webhooks/fully-synced) — Complete list of available webhooks and their descriptions.

[Console Webhooks](/console/management/webhooks) — Learn more about subscribing to and managing webhooks via Console.

<Note>
  Webhooks are not designed to be a primary source of analytics information. For detailed metrics on step-by-step conversion success rates, visit the **Conversion** area of [Console's Dashboard](https://console.argyle.com/dashboard) or contact your customer success manager.
</Note>

## Subscribing to webhooks

Send a **POST** request to the `/v2/webhooks` API endpoint. In the request body, include a JSON object in the format:

```json theme={}
{
    "events": ["webhook.1", "webhook.2", "..."],
    "name": "name-for-the-webhook-subscription",
    "url": "https://your-webhook-backend.com",
    "secret": "optional-secret",            // Optional.
    "config": { "include_resource": true }  // Optional. Can only be applied to certain webhooks.
}
```

* `events` — List all webhooks to include in the subscription.

  <Note>
    To subscribe to all webhooks at once, use `"*"`.

    * This method will not subscribe you to any [Items webhooks](/api-reference/items-webhooks/updated).
    * This method does not allow you to specify the number of days synced for the [`paystubs.partially_synced`](/api-reference/paystubs-webhooks/partially-synced) and [`gigs.partially_synced`](/api-reference/gigs-webhooks/partially-synced) webhooks.
    * For webhooks that have an optional `config` parameter (used to return an account object in the webhook's payload), you must subscribe to these webhooks individually to receive this optional account object.
  </Note>
* `name` — Your name for the set of webhooks in the subscription.
* `url` — Where you want to receive webhook delivery. This can be either a backend URL that you manage, or a URL provided by a webhook management service.

  <Warning>
    Argyle handles URL encoding for webhook URLs. Send the URL in its normal, unencoded form.
  </Warning>

  Argyle delivers webhooks from four static IP addresses:

  <Note>
    * `34.27.251.226`
    * `34.122.50.253`
    * `35.188.163.115`
    * `35.226.53.251`
  </Note>
* `secret` — (Optional) A secret word or phrase that can be used to authenticate webhooks you receive. See below for more information on verifying webhooks.
* `config` — (Optional) Some webhooks will return a payload when `include_resource` is set to `true`.

## Verifying webhooks

When you receive webhooks that were subscribed to using an optional `secret`, an Argyle signature will be included in the header. The `secret` can be any string of characters.

### Steps

To verify the authenticity of a webhook:

1. Use `HMAC-SHA512` to directly encode the received payload body **without any added adjustments**. Use the webhook's `secret` as the secret key for encoding.
2. The webhook is genuine if the encoded payload matches the Argyle signature in the header.

### Example signature

If your `secret` was `my little secret`

...the following webhook body:

```json theme={}
{
    "event": "accounts.added",
    "name": "name-for-the-webhook-subscription",
    "data": {
        "account": "0187c66e-e7e5-811c-b006-2232f00f426a",
        "user": "018051aa-f7a9-a0db-2f38-6cfa325e9d69"
    }
}
```

...would have the following signature:

```json theme={}
"X-Argyle-Signature": "1b158d292b0514f437481f0f1fbb4193ced2ab45b47a6c1255c66e1b8e614d482fd437f23590e8b1d0dd363228ba1ea3261ee0727db132dc0e8d9873fb09c880"
```

### Example validation

#### using Node:

```js theme={}
const http = require('http');
const crypto = require('crypto');
const serverPort = 80
const requestListener = function (req, res) {
    const client_secret = 'my little secret';
    var requestBody = '';
    req.on('readable', () => {
        var read = req.read()
        if(read != null) {
        requestBody += read;
        }
    });
    req.on('end', () => {
        // Make sure to use the raw requestBody when validating the signature.
        signature = crypto.createHmac('sha512',client_secret).update(requestBody).digest('hex');
        console.log('Signature:' + signature);
        res.writeHead(200);
        res.end(signature);
    })
}
const server = http.createServer(requestListener);
server.listen(serverPort);
```

## Webhook management

<div className="argyle-divider" />

### List all webhooks

Send a GET request to the `/v2/webhooks` API endpoint.

<Accordion title="Optional query parameters:">
  * `from_created_at` — Filter for webhooks created on or after this timestamp [(ISO 8601)](https://en.wikipedia.org/wiki/ISO_8601).
  * `to_created_at` — Filter for webhooks created on or before this timestamp [(ISO 8601)](https://en.wikipedia.org/wiki/ISO_8601).
  * `ordering` — Use `id` to order the list results by webhook ID. Use `created_at` to order the list results by when the webhooks were created.
  * `limit` — Limit the number of results returned [per page](/api-guide/overview#pagination). Default: 10. Maximum: 200.
</Accordion>

<Note>
  When you list all webhooks, the last time a particular webhook was sent by Argyle is returned in a `last_sent_at` field. This field can be used for troubleshooting purposes to determine if a webhook was either not sent by Argyle, or sent by Argyle but not received by your webhook system.
</Note>

```json theme={}
{
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "205c027e-8a4d-4248-b395-d4f345dfd49f",
            "name": "name-for-the-webhook-subscription",
            "events": [
                "accounts.added"
            ],
            "config": {
                "include_resource": true
            },
            "secret": "optional-secret",
            "url": "https://your-webhook-backend.com",
            "created_at": "2024-08-30T13:58:53.683338Z",
            "updated_at": "2024-10-07T15:20:49.926525Z",
            "last_sent_at": "2024-10-07T15:19:49.412642Z"
        }
    ]
}
```

### Retrieve a webhook

Send a GET request to the `/v2/webhooks/{id}` API endpoint, and replace the `{id}` with the webhook's ID.

### Delete a webhook

Send a DELETE request to the `/v2/webhooks/{id}` API endpoint, and replace the `{id}` with the webhook's ID.

<Note>
  Webhook ID's are returned in the API response when subscribing to webhooks, or can be found by listing webhooks.
</Note>

## Webhook retry policy

Webhooks have a 10 second timeout. If successful receipt of a webhook (200 response code) does not occur within the timeout window, webhooks will be resent once after 30 seconds for the following response codes: 429, 500, 502, 503, 504. Argyle does not log the body of sent webhooks.

[API Reference](/api-reference/users#object)
