POST when something changes in your org’s sessions and tasks. Each org has one endpoint.
Set the endpoint
Set it in the console (Settings → Webhooks), or withPUT /v1/webhook. Leave events empty to get every type, or list the ones you want; an unknown type is a 400. Only the fields you send change: leave out url to keep the endpoint, leave out events to keep the filter, and send { "url": null } to remove the endpoint. It needs the admin role or an API key.
Response
- To rotate the secret, send
{ "rotate_secret": true }(the URL and events stay as they are). The old secret stops working at once, so deploy the new one to your receiver first or accept both for a moment. - To remove the endpoint, send
{"url": null}. GET /v1/webhookreturns the currenturl,events,has_secretand the list ofevent_types.
Public HTTPS only
The URL must usehttps and resolve to a public address. Private and local addresses (10.x, 127.x, 172.16–31.x, 192.168.x, localhost, *.local, *.internal and the like) are refused with 400 invalid_request, and the check runs again on every delivery. Redirects are not followed. For local development, expose your receiver through a tunnel with a public HTTPS URL.
Event types
A task that asks several questions sends
task.waiting_for_user and task.question_answered for each, and likewise task.waiting_for_approval and task.approval_decided for each approval.
task.question_answered tells you what the answer was and who gave it: answered_by is customer (the person at the computer, in the GuidingHand app) or operator (your team, through the API or the console). Use it to close the question in your own tool when the customer answered it first. data.task is the task just after the answer, so its pending is null.
task.approval_decided does the same for approvals. data.decision has the approval_id, the decision (approve or deny), your team’s note (or null) and answered_by:
Payload
Every event has the same envelope.data.task and data.session are the same objects the API returns.
metadata to find your ticket, and id to ignore an event you’ve already handled.
Verify the signature
Every request has aGuidingHand-Signature header:
t is the Unix time the request was signed. v1 is the hex HMAC-SHA256 of "{t}.{raw body}", keyed with your endpoint’s whole secret (including the whsec_ prefix). To verify:
- Read the raw request body, before any JSON parsing. Re-serialized JSON won’t match.
- Compute the HMAC of
t, a., and the raw body with your secret. - Compare it with
v1in constant time. - Reject the request if
tis more than 5 minutes from your clock. This stops replays of old requests.
2xx quickly and do slow work afterwards, so the delivery doesn’t time out.
Delivery and retries
- Each delivery waits up to 10 seconds for your answer. Any
2xxcounts as received. - On a timeout, a network error or any other status (including
3xx), GuidingHand retries up to 4 times, after about 5 seconds, 20 seconds, 1 minute and 2 minutes: about 3 minutes in total. Then it gives up on that event. - A retry sends the same body with the same
id, and a freshtand signature. - Events can arrive out of order, and more than once. Use
idto skip duplicates, and trust thestatusandupdated_atinsidedatarather than the order of arrival. When in doubt,GETthe task or session.
GET /v1/tasks to catch up.