Webhooks

Webhooks allow you to get programmatic notifications or automated messages from Core about changes to your data as they happen.

Rather than requiring you to pull information via our API, webhooks allow you to push information to your endpoint. You can choose which events you should be notified about by subscribing to them. When a subscribed event is triggered (say a new project is added), Core sends it as an HTTP POST request with a JSON body to the endpoint you specify.

Adding Webhook Event Subscriptions

You can add webhook event subscriptions to your application via your Core Developer account.

webhooks-form
  1. Log in to your Developer Portal account and go to the Dashboard.
  2. Click the Webhooks button next to your application.
  3. In the Edit Webhooks dialog, check the Enable Webhooks toggle and enter the Endpoint URL where you want to receive the events.
  4. Select the Action (e.g., Create, Update, Delete, etc.) for each Entity (e.g., Account, Activity, Invoice, etc.) that should trigger webhook events.
  5. Click Save.

You are now subscribed to the webhook events represented by the Entity-Action combination, and when any of the actions occurs for an entity, the event is sent to the endpoint URL.

You can enable webhooks only after an app is created. Make sure you refresh the token after enabling webhooks.

Events in Core

Events are our way of letting you know when something important happens to your data. You can select what kind of events you want to receive and which ones you don't. Each module (i.e., entity) in Core supports the following event types (i.e., actions):

Event TypeDescription

Create

Occurs when a new object is created

Update

Occurs when an existing object is updated

Delete

Occurs when an object is deleted

An endpoint URL is the HTTP endpoint where your preferred events are sent. Core can send them only to a full, valid, and publicly accessible URL.

Webhooks JSON Format

Webhook events are sent as HTTP POST requests with a JSON body. The JSON body has a standard format and includes metadata, EventId as well as actual data that has changed in the event (Payload). It contains the following fields:

FieldDescription

Id

Identifier of the entity or object on which the event has occurred

CompanyId

Identifier of the Core company where the event has occurred

UserId

Identifier of the Core user who triggered the webhook event

Timestamp

The date and time of the event in Epoch time format

EventId

Unique identifier of the event

Event

The type of the event, e.g., “invoice.delete”

Payload

The full JSON object associated with the event

Type

Type of the Payload, e.g., “Invoice”

For example, if an event is triggered on the deletion of an invoice, the following JSON may be sent in its body:

Event JSON Body

For Delete events, the payload is empty because the object gets deleted.

Retry Logic and Status Codes

Core expects a range of status codes or messages in response to the webhook events it sends. If the delivery of the events is not successful for some reason, Core attempts a finite number of retries in some cases. A total of 5 attempts are made with an interval of 30 seconds between each retry.

A 2XX status code range indicates a successful delivery of the webhook event to the endpoint URL.

A 4XX status code indicates the endpoint did not accept the event for some reason. So no further attempts (or retries) are made to send the event as the response is not expected to change. Exceptions to this are the 408 (Request Timeout) and 429 (Too Many Requests) status codes, because here the response is expected to change.

A 5XX status code indicates a server error, usually on the user’s end. Core treats such responses as a failure and attempts retries.

Validating Webhook Events

To make sure the webhook events you receive are authentic and not tampered with, Core sends a signature in the form of the X-BQECore-Signature header in the HTTP POST request of the event. This signature header is a base64 encoded string computed using the SHA-256 hashing algorithm and contains the hash of the payload concatenated with the hash of the Client Secret of your app. If your app does not have a Client Secret, it uses the Client ID. Using the Payload in computing the hash ensures that you can verify it has not been tampered with, while using the client key ensures the event is coming from Core. The signature is computed as:

X-BQECore-Signature = base64 (SHA-256 (SHA-256 (Payload) + SHA-256 (Client Secret or Client ID) ) )

You can compute the above signature at your end using the Payload you receive in the event and the Client Secret or Client ID of your application. If it matches the signature you received in the X-BQECore-Signature header, you can be sure of the authenticity of the event.

Best Practices

When using webhooks in Core, we recommend that you follow these best practices in order to make the most of this feature.

  • Listen for limited event types: You should configure your webhook endpoint to receive only those types of events that are required by your integration. Listening for extra events (or all events) puts undue strain on your server and is not recommended. You can change the events that are sent to a webhook endpoint in the Core Developer account dashboard.
  • Delivery attempts and retry logic: When webhook events are not acknowledged by your endpoint within a stipulated time, Core makes a finite number of retry attempts for them in some cases as discussed in the Retry Logic and Status Codes section. So you must configure your endpoint to handle the retries.
  • Event handling: Handling webhook events correctly is crucial to making sure that the business logic of your integration works as expected.
    • Duplicate events: Webhook endpoints can sometimes receive the same event more than once. You can handle duplicate receipts by making your event processing idempotent. One way of doing this is logging the events you have processed and then not processing already-logged events. As each event contains a unique EventId, it is easy to identify duplicates.
    • Order of events: Core does not guarantee delivery of events in the order in which they are generated. For example, creating an invoice also updates the associated time entries, and it may generate events in the following order:

      invoice.create
      time entry.update (multiple events if there are multiple time entries)

      Your endpoint should not expect delivery of these events in this order and should handle this accordingly.
  • Security: Keeping your endpoints secure is critical to protecting your clients’ information. There are several ways to make sure the events are coming from Core in a secure manner.
    • X-BQECore-Signature header: Core sends an X-BQECore-Signature header in the HTTP POST request of the events. We strongly recommend that you validate the events you receive using this header as discussed in the Validating Webhook Events section.
    • Receiving events with an HTTPS server: If you use an HTTPS URL for your webhook endpoint, Core validates that the connection to your server is secure before sending you webhook events. For this to work, you must configure your server to support HTTPS, with a valid server certificate.