Skip to main content

Account Hooks

Introduction

Account Hooks are a way to add further customization to your Neosync account.

Neosync Version Availability

Account Hooks are available for all accounts in Neosync Cloud.

For OSS users, Account Hooks are only available with a valid Enterprise license.

How to configure Account Hooks

This section will cover how to configure hooks in the Neosync UI. They can also be configured via the API and soon the Terraform provider.

Getting there

Account Hooks can be via the settings page for your account.

Account Hooks Settings

Creating a new hook

From here a new hook may be created. Click on the new hook button and you'll be presented with a new hook form to fill out.

There are a few different configuration options available to you to further fine tune when the hook runs.

Today, Webhook and Slack hooks are supported, with plans for, Discord, and other integrations in the future.

New Hook Form

Execution order strategy

When an event is emitted, Neosync retrieves all active hooks for the event and executes each hook in order of creation. Today they are executed in synchronous fashion, meaning that each hook is executed one at a time. This may change in the future to allow for parallel execution of hooks.

Enabling/Disabling Hooks

Hooks can be easily enabled or disabled by clicking the toggle button in the hook creation or edit form.

This is useful if you want to temporarily disable a hook without having to delete it.

Events

Today, there are 3 events that can trigger a hook:

  • Job Run Created
  • Job Run Failed
  • Job Run Succeeded

Each event follows the same format, with the only difference being the payload.

{
"name": "1", // The enum value of the event name
"accountId": "<account-id>", // The account ID the event occurred in
"timestamp": "<timestamp>", // The timestamp the event occurred in UTC time.

// The payload for the event. The presence of the key depends on which event occurred.
"jobRunCreated": {},
"jobRunSucceeded": {},
"jobRunFailed": {},
}

Job Run Created

The payload for the Job Run Created event is the following:

{
"jobId": "<job-id>",
"jobRunId": "<job-run-id>"
}

Job Run Failed

The payload for the Job Run Failed event is the following:

{
"jobId": "<job-id>",
"jobRunId": "<job-run-id>"
}

Job Run Succeeded

The payload for the Job Run Succeeded event is the following:

{
"jobId": "<job-id>",
"jobRunId": "<job-run-id>"
}

Webhooks

Webhooks are bare bones web requests that give you full control over what to do with the messages. The possibilities are endless!

Webhook Authentication

Webhooks are authenticated using a HMAC hash of the payload and a secret key.

The secret key is set when the webhook is created and is used to verify that the webhook is coming from Neosync.

The HMAC hash is generated using the SHA256 algorithm and the secret key.

The HMAC hash is sent in the X-Neosync-Signature header.

The HMAC hash algorithm is sent in the X-Neosync-Signature-Type header.

More Request Details and Response Information

Each webhook is sent as a POST request to the webhook URL.

The timeout for webhooks is 10 seconds.

If the webhook does not respond within 10 seconds, it is considered to have failed.

The webhook is considered to have failed if the response status code is not in the 200-299 range.

The webhook request body is sent as JSON and the content type is application/json.

Example Verification in Go

package main

import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
)

const SECRET = "your-secret-key"
const WEBHOOK_SIG_HEADER = "X-Neosync-Signature"

func main() {
mux := http.NewServeMux()
mux.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
receivedSignature := r.Header.Get(WEBHOOK_SIG_HEADER)
payload, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

verified, err := verifyHmac(SECRET, payload, receivedSignature)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}

if !verified {
w.WriteHeader(http.StatusUnauthorized)
return
}

// do something with the payload
w.WriteHeader(http.StatusOK)
})

http.ListenAndServe(":8080", mux)
}

func verifyHmac(secret string, payload []byte, signature string) (bool, error) {
mac := hmac.New(sha256.New, []byte(secret))
_, err := mac.Write(payload)
if err != nil {
return false, fmt.Errorf("unable to write payload to hmac: %w", err)
}
expectedMAC := mac.Sum(nil)
expectedSignature := hex.EncodeToString(expectedMAC)
return hmac.Equal([]byte(signature), []byte(expectedSignature)), nil
}

Slack

The Slack configuration offers a first-party way of receiving notifications.

Today the messages are fully controlled by Neosync and cannot be altered.

Configuring the Slack hook requires using Oauth to install the Neosync Slack App into your Slack's workspace. The hook configuration itself asks for the Channel Id that will be used to send the notifications for your specific hook configuration.

When creating the hook, the Slack app will attempt to automatically join the channel, provided it is public.

For private slack channels, the Neosync app will have to be manually invited to it, as Slack does not provide a way to automatically do this.

Setting up OAuth

When in the slack hook form for the first time, you'll see a notice that says Slack is not connected.

There are two buttons, Verify and Connect. Click the Connect button first. This will open a pop-up window that will take you through the Slack oauth flow of installing the Neosync app to your workspace. If all goes well, you'll land back on the Neosync page with a success and can simply close the window. If an error occurred, that will surface on the page as well.

After closing the window, the hook form may still show that it is not connected. Click the Verify button to initiate a request to re-check that Neosync is now connected to your Slack. If so, you'll see a message like Slack is connected to <team>. You should only ever have to do this once, but if something needs to change, you can now click on the Re-connect button to go through the oauth flow a second time.

You may now enter your channel id and submit the form!

Finding your Slack Channel Id.

In slack, go to your channel. Click the name of your channel at the top of the app. This will open a channel info dialog. At the bottom if this dialog you will find your channel's id. Copy that and paste it into the slack configuration.

Retries

If any account hook fails, it will be retried up to 3 times.

The backoff coefficient is 2.0, with an initial interval of 1 second.

The maximum interval is 100x the initial interval.

The retry policy is applied per hook execution.