> ## 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](/developer-guides/implementation/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** of 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.
