Skip to content
Developer API6 min read

Webhooks and outbound HTTP

Agentency calls your endpoint through an HTTP Call action, and receives inbound deliveries from the channels you connect.

Browse topics

What it is

"Webhooks" means two different things in Agentency, and they live in different places:

  • Outbound — Agentency calls you. Mid-conversation, when the chatbot needs something it cannot know from your knowledge, it can make an HTTP request to your endpoint and use the response in its reply. You configure this as an HTTP request Call action on the chatbot.
  • Inbound — a platform calls Agentency. When you connect a messaging channel, that platform delivers messages to an Agentency endpoint. You do not create or host that URL; connecting the channel wires it up.

What does not exist is a general event feed. There is no "subscribe to every conversation" switch and no webhook-subscription list on the Developer tab, which holds keys and the knowledge ingest reference only.

When you would use it

Use an outbound Call action when an answer depends on live data or must cause something to happen: order status, stock levels, appointment slots, creating a ticket, or firing an automation in a tool like Zapier or Make.

Use an inbound channel connection when your customers are already messaging you somewhere else and you want the chatbot to answer there.

If you need a record of conversations elsewhere, poll the API on a schedule or export from Customers — there is no push feed to subscribe to today.

Where to find it

Outbound: Dashboard → Chatbots → your chatbot → Actions.

Inbound: Dashboard → Chatbots → your chatbot → Integrations.

Steps — outbound HTTP action

  1. Open the Actions tab and create an HTTP request action.
  2. Name it and describe when it should be used. That description is what the chatbot reasons over, so "look up an order by its number" beats "order API".
  3. Set the method — GET, POST, PUT, PATCH, or DELETE — and the HTTPS URL.
  4. Declare the parameters the chatbot must collect from the visitor, so it knows what to ask for before calling you.
  5. Add authentication if your endpoint needs it: a bearer token, basic credentials, or an API key sent in a header name you choose. Credentials are stored for the action and are not echoed back.
  6. For write methods, build the body template and reference the collected parameters inside it.
  7. Optionally enable request signing. Agentency then sends an HMAC-SHA256 of the body in a header you name, so your endpoint can verify the call really came from Agentency.
  8. Enable the action and test it from Test Chatbot with a question that should trigger it.
  9. Open the action's run history and confirm the outcome.

Verifying a signed request

If you enable signing, compute the same HMAC over the raw request body with your shared secret and compare it in constant time before you trust anything in the payload.

import crypto from "node:crypto";

function isFromAgentency(rawBody, headerValue, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)          // the raw bytes, before JSON parsing
    .digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(headerValue ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Two details matter: hash the raw body, not a re-serialised object, and compare with a timing-safe function rather than ===.

What you will see

The Actions tab is a list of actions with an enabled toggle each, plus a run history. Each run records a status:

StatusMeaning
successYour endpoint answered and the result was used
failedThe call could not be completed
timed_outYour endpoint did not answer inside the allowed window
skippedThe turn did not need the action after all
confirmation_pendingThe visitor was asked to confirm before a change was made

The Channels screen shows a card per platform. Connecting one registers the delivery URL for you; platforms that are not yet available say so on the card.

Rules your endpoint must live with

HTTPS and public. The URL must be reachable from the internet. Requests to internal, private, or link-local addresses are refused before any connection is made — that guard exists so a chatbot cannot be talked into probing a private network, and it applies to redirects too.

Answer fast. Actions run inside a live conversation, with a per-call budget measured in seconds. Something slower than that should be started asynchronously: return an acknowledgement immediately and follow up by email or another channel.

Be idempotent. Calls are made at most once, and a timeout is genuinely ambiguous — the request may have arrived and completed even though Agentency never saw the response. Deduplicate on a key you control so an ambiguous outcome cannot double-charge or double-book.

Fail loudly and briefly. Return a normal HTTP error status with a short message. The chatbot will tell the visitor it could not complete the request rather than inventing a result.

Repeated failures back off. An endpoint that keeps failing is temporarily stopped from being called, so one broken integration cannot slow every conversation. Fix the endpoint and it recovers.

Limits and plan notes

Call actions are a paid-plan feature and each chatbot has its own cap on how many may be enabled at once. The free tier includes none, so a free chatbot can answer but cannot look anything up. See What are Call actions.

Actions that change something — the write methods, and anything you have marked as high risk — ask the visitor to confirm first, and that confirmation is single-use.

Inbound channel deliveries are authenticated and deduplicated by Agentency, so a platform that retries a delivery does not produce a duplicate answer.

Payment webhooks are part of the platform, not something you configure. Your side of billing is the Billing page and the payment portal — see Payment method and invoices.

Common problems

There is no Webhooks section under Developer.

There is not one. Use an HTTP request Call action for outbound, and connect a channel for inbound.

My endpoint never receives anything.

Check three things in order: the action is enabled, the plan allows the number of actions you have enabled, and the run history shows an attempt. No attempt at all means the chatbot never decided the turn needed it — sharpen the description of when to use it.

The run says the destination was blocked.

The URL resolves to a private or internal address. Publish the endpoint on a public HTTPS hostname.

Everything times out.

Your endpoint is slower than the in-conversation budget. Acknowledge immediately and do the slow work in the background.

Signature checks keep failing.

You are almost certainly hashing a re-serialised body. Capture the raw bytes before any JSON middleware touches them.

Can I get a ping for every new lead?

Not as a built-in feed. Fire a Call action during the conversation that collects the details, or export from Customers.

Should the widget carry my API key so it can call my server?

No. Anything in browser JavaScript is public. Keep credentials on the server side of a Call action — see Create a personal access token.

Common questions

There is no Webhooks section under Developer. Where is it?

There is not one. Outbound calls are HTTP request Call actions on a chatbot; inbound deliveries are wired up automatically when you connect a messaging channel.

How does my endpoint verify a call really came from Agentency?

Enable request signing on the action. Agentency then sends an HMAC-SHA256 of the body in a header you name — hash the raw bytes and compare with a timing-safe function.

Why was my URL rejected as a blocked destination?

It resolves to a private, internal or link-local address. Only public HTTPS endpoints are called, and the same guard applies to redirects.

Do you retry a failed call?

Calls are made at most once, and a timeout is ambiguous — your endpoint may have completed the work. Deduplicate on a key you control so an ambiguous outcome cannot double-charge.

Can I subscribe to every conversation event?

Not today. There is no push feed. Poll the API on a schedule, or capture what you need during the conversation with a Call action.

Was this article helpful?

Ready to try it on your own content?

Create a free workspace, add a document, and ask the questions your team is tired of answering.