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

# Webhooks

### Summary

Use Chift's webhooks to build custom applications that react to specific events from the platform and the unified APIs.

#### How can you manage your webhooks?

* Manage webhooks through the UI in your account settings
* Manage webhooks through the API

#### Technical specifications

When a specific event occurs, Chift sends a POST HTTP request to the webhook's URL.

The request contains a JSON payload with at least these mandatory attributes:

* `accountid`: guid of your Chift's account
* `event`: name of the event
* `consumerid`: guid of the consumer on which the event occurred
* `created`: timestamp (in sec) of the webhook event

The header also contains the following [encrypted Chift Signature](#x-chift-signature):

* `X-Chift-Signature`: encrypted signature of your body payload

#### List of events

Chift can emit the following events, grouped by domain. For the *connection events*, also see the [Connection lifecycle](/guides/core-concepts/monitor-connections#connection-lifecycle) section to understand when each one is sent.

<Note>
  Every webhook body includes `accountid`,`event`,`consumerid`,`created`, as described in [Technical specifications](#technical-specifications). The payloads below show only the event-specific fields added **in addition to** those.
</Note>

<Tabs>
  <Tab title="Connection events">
    <AccordionGroup>
      <Accordion title="account.connection.created">
        When a new consumer connection is created. You receive this event only when the connection is created successfully.<br /><br />Additional fields on top of the common payload for this event:

        * `connectionid:` guid of the connection on which the event occurred
        * `status`: active/inactive
      </Accordion>

      <Accordion title="account.connection.updated">
        When a consumer connection is updated.

        * `connectionid`: guid of the connection on which the event occurred
        * `status`: active/inactive
      </Accordion>

      <Accordion title="account.connection.deleted">
        When a consumer connection is deleted.

        * `connectionid`: guid of the connection on which the event occurred
        * `status`: active/inactive
      </Accordion>

      <Accordion title="account.connection.up">
        When a local agent is correctly set up.

        * `connectionid`: guid of the connection on which the event occurred
      </Accordion>

      <Accordion title="account.connection.down">
        When a local agent has not sent a ping in the last 15 minutes.

        * `connectionid`: guid of the connection on which the event occurred
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Flow events">
    <AccordionGroup>
      <Accordion title="account.flow.enabled">
        When a flow is activated for a specific consumer.

        Additional fields on top of the common payload for this event:

        * `flowid`: guid of the flow on which the event occurred
        * `syncid`: guid of the sync on which the event occurred
      </Accordion>

      <Accordion title="account.flow.disabled">
        When a flow is deactivated for a specific consumer.

        Additional fields on top of the common payload for this event:

        * `flowid`: guid of the flow on which the event occurred
        * `syncid`: guid of the sync on which the event occurred
      </Accordion>

      <Accordion title="account.flow.updated">
        When flow settings are updated for a specific consumer.

        Additional fields on top of the common payload for this event:

        * `flowid`: guid of the flow on which the event occurred
        * `syncid`: guid of the sync on which the event occurred
      </Accordion>

      <Accordion title="account.flow.executed">
        When a flow finishes executing (one event per consumer).

        Additional fields on top of the common payload for this event:

        * `flowid`: guid of the flow on which the event occurred
        * `syncid`: guid of the sync on which the event occurred
        * `status`: success/error
        * `executionid`: guid of the execution of the consumer flow
        * `parentexecutionid`: guid of the execution of the parent flow
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Data layer events">
    <AccordionGroup>
      <Accordion title="account.datalayer.refresh_initiated">
        When a data layer refresh starts for a consumer (one event per consumer).

        Additional fields on top of the common payload for this event:

        * `connectionid`: guid of the connection being refreshed
        * `api`: source API being refreshed (e.g. Accounting)
        * `scope`: the scope of the source covered by the refresh (only sent for data layer events; structure depends on the API)
      </Accordion>

      <Accordion title="account.datalayer.refresh_executed">
        When a data layer refresh finishes for a consumer, whether it succeeded or failed (one event per consumer).

        Additional fields on top of the common payload for this event:

        * `connectionid`: guid of the connection that was refreshed
        * `api`: source API that was refreshed (e.g. Accounting)
        * `scope`: the scope of the source covered by the refresh (only sent for data layer events; structure depends on the API)
        * `status`: success/error
      </Accordion>

      <Accordion title="account.datalayer.data_changed">
        When records are created or updated during a data layer refresh. Sent once per folder processed, and only when something changed.

        The `changed` array lists the data layer resources that were affected (by their table name). It does not carry record ids. Fetch the resource to retrieve the latest data.

        Additional fields on top of the common payload for this event:

        * `connectionid`: guid of the accounting connection that was refreshed
        * `changed`: array of affected data layer resource table names (e.g. `["accounting_invoices", "accounting_partners"]`)
      </Accordion>

      <Accordion title="account.datalayer.data_deleted">
        When records are deleted during a data layer refresh. Sent once per folder processed, and only when something was deleted.

        The `deletes` object maps each affected data layer resource (by its table name) to the ids of the records that were removed. Unlike `data_changed`, deletions carry their ids, since a removed record can no longer be retrieved by fetching the resource.

        Additional fields on top of the common payload for this event:

        * `connectionid`: guid of the accounting connection that was refreshed
        * `deletes`: object mapping each affected data layer resource (by its table name) to the ids of the removed records (e.g. `{"accounting_partners": ["MYPARTNERID", "MYPARTNERID2"]}`)
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Issue events">
    <AccordionGroup>
      <Accordion title="account.issue.created">
        When a new consumer issue is raised.

        Additional fields on top of the common payload for this event:

        * `issue_id`: guid of the consumer issue
        * `connectionid`: guid of the connection on which the issue occurred
        * `syncid`: guid of the sync on which the issue occurred (optional)
        * `error_code`: error code of the issue
        * `issue_status`: status of the issue
        * `message`: error message describing the issue
        * `context`: additional context information
      </Accordion>

      <Accordion title="account.issue.updated">
        When there is a new occurrence of an existing consumer issue.

        Additional fields on top of the common payload for this event:

        * `issue_id`: guid of the consumer issue
        * `connectionid`: guid of the connection on which the issue occurred
        * `syncid`: guid of the sync on which the issue occurred (optional)
        * `error_code`: error code of the issue
        * `issue_status`: status of the issue
        * `message`: error message describing the issue
        * `context`: additional context information
        * `occurrences`: number of times this issue has occurred
      </Accordion>

      <Accordion title="account.issue.closed">
        When a consumer issue is closed automatically.

        Additional fields on top of the common payload for this event:

        * `issue_id`: guid of the consumer issue
        * `connectionid`: guid of the connection on which the issue occurred
        * `syncid`: guid of the sync on which the issue occurred (optional)
        * `error_code`: error code of the issue
        * `issue_status`: auto\_closed
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="POS events">
    <AccordionGroup>
      <Accordion title="pos.order.completed">
        When an order is completed.

        Additional fields on top of the common payload for this event:

        * `order_id`: guid of the order on which the event occurred
        * `device_id`: guid of the device on which the order was completed (optional)
        * `customer_id`: guid of the customer that has made the order (optional)
        * `location_id`: guid of the location on which the order was completed
        * `updated_at`: time of completion
      </Accordion>

      <Accordion title="pos.order.updated">
        When the status of an order is updated.

        Additional fields on top of the common payload for this event:

        * `order_id`: guid of the order on which the event occurred
        * `device_id`: guid of the device on which the order was completed (optional)
        * `customer_id`: guid of the customer that has made the order (optional)
        * `location_id`: guid of the location on which the order was completed
        * `updated_at`: time of completion
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

#### X-Chift-Signature

Use the `X-Chift-Signature` attribute to verify that incoming calls on your webhook endpoint come from Chift.

Chift generates the `X-Chift-Signature` from the signing secret that you can optionally add when you create or update a webhook. It uses the HMAC authentication method, which relies on two keys: the signing secret that only you know, and the request body.

Most programming languages support HMAC hashes.

For example, in Node.js:

```javascript theme={null}
const hash = crypto
  .createHmac("sha256", encryption.decrypt(SIGNING_SECRET).toString())
  .update(JSON.stringify(REQUEST_BODY), "utf-8")
  .digest("hex");
```

For example, in Python:

```python theme={null}
import hmac
import hashlib
import json

json_data = json.dumps(REQUEST_BODY, separators=(',', ':'))
h = hmac.new(SIGNING_SECRET.encode(), json_data.encode(), hashlib.sha256)
hash = h.hexdigest()
```

By computing the hash on your endpoint, you can compare it with the `X-Chift-Signature` header attribute to confirm that the request originated from Chift.
