Integrations
Incoming events
Tell AnswerStack when something changes on your side, such as a cancelled tour, with a signed request to your connection’s webhook URL.
Your CRM or calendar system can tell AnswerStack when a meeting booked through a connection is cancelled on your side. It posts a small JSON event to the connection's own webhook URL, signed so AnswerStack knows it came from you.
Get the secret and the URL#
Open the connection
In the admin app, go to Connections and find the connection the meetings were booked through.
Make a signing secret
Press Incoming events secret, then Make a secret. Copy the secret and the webhook URL. The secret is shown once; if it is lost, make a new one. Making a new one stops the previous one.
This secret is only for requests you send to AnswerStack. It is not your CRM's API key, and not the secret AnswerStack signs its own requests to you with.
Send an event#
POST /v1/webhooks/connections/conn_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE HTTP/1.1
Content-Type: application/json
X-AnswerStack-Signature: t=1758463200,v2=4f1c3d2b9a8e7f60512a4b3c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f809
{"event":"booking.cancelled","data":{"confirmationId":"8812","cancelledAt":"2026-09-21T14:00:00Z"}}| Event | data | What AnswerStack does |
|---|---|---|
booking.cancelled | confirmationId: the ID your system gave the meeting. cancelledAt (optional): ISO time | Marks the meeting cancelled |
| Anything else | Anything | Accepts it (202) and records it, no more |
AnswerStack answers 202 with {"received": true, "handled": true} when it changed something, and
handled: false when there was nothing to change (for example, the meeting was already cancelled).
Sending the same event twice is safe.
Sign the request#
The header is x-answerstack-signature with the value t=<time>,v2=<signature>:
tis the current time in whole seconds since 1970 (Unix time).v2is the lowercase hex HMAC-SHA256 of the time, a full stop, and the raw request body, byte for byte, keyed with your signing secret.
A request whose time is more than five minutes from AnswerStack's clock is refused, so a captured request cannot be replayed later. Keep your server's clock synchronised.
Node.js#
import crypto from 'node:crypto';
const SECRET = process.env.ANSWERSTACK_INBOUND_SECRET;
async function send(url, event) {
const body = JSON.stringify(event);
const t = Math.floor(Date.now() / 1000);
const v2 = crypto.createHmac('sha256', SECRET).update(`${t}.${body}`).digest('hex');
return fetch(url, {
method: 'POST',
headers: { 'content-type': 'application/json', 'x-answerstack-signature': `t=${t},v2=${v2}` },
body,
});
}Shell#
BODY='{"event":"booking.cancelled","data":{"confirmationId":"8812"}}'
T=$(date +%s)
SIG=$(printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$ANSWERSTACK_INBOUND_SECRET" -hex | sed 's/^.* //')
curl -X POST "$WEBHOOK_URL" \
-H 'content-type: application/json' \
-H "x-answerstack-signature: t=$T,v2=$SIG" \
--data "$BODY"A request with a missing or wrong signature, or for a connection that does not exist, gets 401.
Moving from the old signature#
Before signing secrets, requests were signed with the bare hex HMAC-SHA256 of the body, keyed with the connection's own credential, in the same header. That still works while you move:
- Make a signing secret for the connection, as above.
- Change your system to send
t=…,v2=…with the new secret. - From the first request AnswerStack accepts with the new signature, it refuses the old one for that connection. The Incoming events secret dialog says when that happened.
Support for the old signature will end for every connection; the changelog will say when, well in advance.