Webhooks
Webhooks inform your backend when there are changes to data in Abound.
Setting up webhooks only takes two steps:
- The first step is to set up your webhooks in the dashboard. You can adjust your webhook URLs, manage whether your webhooks are enabled or disabled, and subscribe to specific events. Events represent changes to a resource within Abound. Abound supports webhooks for the following events:
documents.created
documents.updated
mailings.created
mailings.updated
users.updated
- The next step is to test your webhook connection to ensure you are receiving events. Below is an example of the webhook request payload that would be sent to your URL when the
documents.created
event occurs:
{
"resource":"documents",
"resourceId":"documentId_XXXXXXXXXXXXXXXXXXXXXX",
"resourceURL":"https://sandbox-api.withabound.com/<<apiVersion>>/users/userId_8e01c68862ff080637075b7f0e2105bd7229f434/documents/documentId_9a1ccd4967787ea24bbcc2e818f619697b518338",
"event":"documents.created",
"userId":"userId_8e01c68862ff080637075b7f0e2105bd7229f434",
"webhookId":"webhookId_XYZZYXYZZYXYZZY",
"webhookURL":"https://webhook.site/87a85187-96bc-42eb-81bc-65fb66369c44",
"webhookRequestId": "webhookRequestId_YYYYYYYYYYYY"
}
If an error occurs on the resource connected to the webhook, the webhook will also return a resourceMessage
.
{
"resource": "documents",
"resourceId": "documentId_XXXXXXXXXXXXXXXXXXXXXX",
"resourceURL": "https://sandbox-api.withabound.com/<<apiVersion>>/users/userId_0aa8b15c0cce59aa766156e6328798c80512131a/documents/documentId_9a1ccd4967787ea24bbcc2e818f619697b518338",
"resourceStatus": "error",
"resourceMessage": "payerError",
"event": "documents.updated",
"userId": "userId_0aa8b15c0cce59aa766156e6328798c80512131a",
"webhookId": "webhookId_XYZZYXYZZYXYZZY",
"webhookURL": "https://webhook.site/e665ac70-4914-4d8b-ab48-fa2b47680b4a",
"webhookRequestId": "webhookRequestId_YYYYYYYYYYYY"
}
Important considerations for webhook requests:
- Webhook requests may be sent out of chronological order in which the events took place.
- Multiple webhook requests may be attempted for a single event.
- HTTPS URLs are required for use in the production environment.
Validation
Abound includes a validation header with each webhook call by including the header value ["Abound-Signature"]
. This allows you to verify that the events were sent by Abound and not a third party. The signature is a a hash-based message authentication code (HMAC) with SHA-256.
Below is an example of how to validate
const {
createHmac
} = await import('crypto');
// Header containing webhook signature
const sigHeader = event.headers['Abound-Signature'];
// Raw body of received request
const rawBody = event.body;
const hmac = createHmac('sha256', 'YOUR_APP_SECRET');
hmac.update(event.body);
const sigGenerated = hmac.digest('hex');
// Returns true if match
return sigGenerated === sigHeader
import hmac
import hashlib
## Header containing webhook signature
sig_header = request.headers.get("Abound-Signature")
## Raw body of received request
raw_body = request.get_data(parse_form_data=True)
digest = hmac.new(
key="YOUR_APP_SECRET".encode("utf-8"),
msg=raw_body.encode(),
digestmod=hashlib.sha256,
).hexdigest()
## Returns true if match
return digest == sig_header
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
// Header containing webhook signature
sig_header:= r.Header.Get("Abound-Signature")
// Raw body of received request
raw_body := r.Body
hmacVal := hmac.New(sha256.New,[]byte("YOUR_API_KEY"))
hmacVal.Write([]byte(raw_body))
sigGenerated := hex.EncodeToString(hmacVal.Sum(nil))
// Returns true if match
fmt.Println( hmac.Equal([]byte(sigGenerated), []byte(sig_header)))
}
require 'openssl'
## Header containing webhook signature
sig_header = request.headers.get("Abound-Signature")
## Raw body of received request
raw_body = request.body
hmac = OpenSSL::HMAC.hexdigest("SHA256", 'YOUR_API_KEY', raw_body)
## Returns true if match
return hmac == sig_header
Updated 11 days ago