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

# Webhooks

Asset uses **webhooks** to send notifications regarding specific requests and updates about
the platform.

## **Configuring Webhooks**

* In the **Asset Dashboard**, go to **Developers → Webhooks**.
* Enter your `Endpoint URL` (HTTPS only).
* *(Optional)* Add custom `Headers` such as an `Authorization` token or an `x-asset-signature` secret.
* Click **Save**.

## **Disabling Webhooks**

There might be times in which you want to temporarily disable webhooks. To do this, follow the steps below:

1. In the **Asset Dashboard**, open **Developers → Webhooks**.
2. Toggle `Enabled` off.
3. Click **Save**.

## **Retries**

If there is non-200 response or the request times out, Asset will retry the request up to four more times,
each with an exponential backoff. The first delay will be 10 seconds, and subsequent delays will double from there.

## **Catching Up on Missed Webhooks**

If your endpoint was down or you missed some deliveries, you can replay past notifications with the
[Load webhook notifications](/api-reference/webhooks/load-webhook-notifications) endpoint:

```
GET /v0/tenant/webhook/notifications
```

* Pass `webhook_id` (the `asset-id` header of the last webhook you received) to get all notifications created after it.
* Filter by delivery status with the `status` query parameter (`pending`, `sent`, `error`), comma-separated for multiple values.
* Results are paginated.

Each item in the response contains the notification `id`, the `datetime` it was sent (or created if it has not
been sent yet), and the original `notification` message, so you can process missed events exactly as if they had
been delivered to your endpoint.

## **Headers**

Every webhook request comes with two headers `asset-id` and `asset-signature`. The `asset-id` header uniquely
identifies the webhook request, and `asset-signature` is the signature of the request. You can use the public key
at `https://api.getasset.com/.well-known/jwks.json` to validate the signature. Below is a sample Python code snippet
that shows how to validate the signature.

```python theme={null}
import json
import base64
import requests
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from jwcrypto import jwk

def base64url_decode(val):
    val += "=" * (-len(val) % 4)  # Fix padding
    return base64.urlsafe_b64decode(val)

asset_id = "<VALUE FROM HEADER>"
asset_signature = "<VALUE FROM HEADER>"
body = <BODY OF WEBHOOK MESSAGE>
payload = f"{asset_id}.{json.dumps(body)}"
decoded_signature = base64url_decode(asset_signature)

# Download the public key for signature verification and convert to RSA format
resp = requests.get("https://api.getasset.com/.well-known/jwks.json").json()
key = jwk.JWK.from_json(json.dumps(resp["keys"][0]))
n = int.from_bytes(base64url_decode(key.get("n")), "big")
e = int.from_bytes(base64url_decode(key.get("e")), "big")
public_numbers = rsa.RSAPublicNumbers(e, n)
rsa_key = public_numbers.public_key(default_backend())

# Validate the signature
rsa_key.verify(
    decoded_signature,
    payload.encode(),
    padding.PKCS1v15(),
    hashes.SHA256(),
)

```

## **Notifications**

### Plaid connections

For bank integrations, we have the following notifications available:

* **PLAID\_ACCOUNT\_CONNECTED**: Sent when a new account is connected via Plaid.
* **PLAID\_ACCOUNT\_DISCONNECTED**: Sent when an existing account is disconnected through the Plaid link flow.
* **PLAID\_ACCOUNT\_EXPIRED**: Sent when Plaid detects that the account connection is not active. This means the account must be reconnected.
* **PLAID\_SYNC\_STARTED**: Sent when a transactions sync starts for a Plaid-connected account.
* **PLAID\_TRANSACTIONS\_SYNCED**: Sent when new transactions have been synced for a Plaid-connected account.
* **ACCOUNT\_BALANCE\_UPDATED**: Sent when the balance is updated on an account.

All notifications above have the same message structure:

```json theme={null}
{
  "type": "<PLAID_ACCOUNT_CONNECTED, PLAID_ACCOUNT_DISCONNECTED, PLAID_ACCOUNT_EXPIRED, PLAID_SYNC_STARTED, PLAID_TRANSACTIONS_SYNCED, ACCOUNT_BALANCE_UPDATED>",
  "content": {
    "business_id": "biz_Pk2fNFDd8wj7EFeLWJywc7",
    "timestamp": "<current timestamp in UTC>",
    "account_id": "<the plaid linked item id>"
  }
}
```

### Bookkeeping requests

As the books are being completed for a business, Asset will send requests that lists the set of tasks that need to be completed by the
business owner.

Message structure:

```json theme={null}
{
  "type": "TASK_REQUEST",
  "content": {
    "business_id": "biz_Pk2fNFDd8wj7EFeLWJywc7",
    "task_types": [
      "categorize_transaction",
      "reconnect_account",
      "request_other_document",
      "request_receipt",
      "request_statement",
      "review_personal_transaction",
      "other"
    ]
  }
}
```

In addition, when the business owner has completed the tasks, a notification is also sent.

Message structure:

```json theme={null}
{
  "type": "TASKS_REQUEST_COMPLETED",
  "content": {
    "business_id": "biz_Pk2fNFDd8wj7EFeLWJywc7",
    "timestamp": "<current timestamp in UTC ISO 8601>"
  }
}
```

<Note>
  {" "}

  Questions? Reach out via our [Contact form](https://www.getasset.com/get-in-touch)
  or email [support@getasset.com](mailto:support@getasset.com).{" "}
</Note>

### Business notifications

We have the following notifications when a Business changes state:

* **BUSINESS\_CREATED**: Sent when a business is created.
* **BUSINESS\_ACTIVATED**: Sent when an inactive business is activated.
* **BUSINESS\_DEACTIVATED**: Sent when an active business is deactivated.

Message structure:

```json theme={null}
{
  "type": "BUSINESS_CREATED",
  "content": {
    "business_id": "biz_Pk2fNFDd8wj7EFeLWJywc7",
    "business_external_id": "<the external business id>",
    "timestamp": "<current timestamp in UTC ISO 8601>"
  }
}
```

### Document notifications

We have the following notifications for uploaded documents:

* **RECEIPT\_MATCHED**: Sent when a receipt document is matched to a transaction.

Message structure:

```json theme={null}
{
  "type": "RECEIPT_MATCHED",
  "content": {
    "document_id": "doc_2xPQDLmNeWsrahR4bj3oGc9i6Nb",
    "transaction_id": "txn_3yQRENoPfXtsbhS5ck4pHd0j7Oc",
    "timestamp": "<current timestamp in UTC ISO 8601>"
  }
}
```

* **STATEMENT\_IMPORTED**: Sent when an uploaded bank statement finishes importing into an account.

Message structure:

```json theme={null}
{
  "type": "STATEMENT_IMPORTED",
  "content": {
    "business_id": "biz_Pk2fNFDd8wj7EFeLWJywc7",
    "account_id": "<the external account id>",
    "document_id": "doc_2xPQDLmNeWsrahR4bj3oGc9i6Nb",
    "timestamp": "<current timestamp in UTC ISO 8601>"
  }
}
```
