A webhook tells another system when something happens on your Tender site. When a discussion is started, a reply is posted, a knowledge base article is published, and so on, Tender sends the details as JSON to a web address you choose. Use webhooks to keep your own tools in step with Tender without asking the API over and over.
Set up a webhook
Webhooks are in your dashboard under Account & Settings › Extras, then Webhooks in the sidebar (under Advanced). You need access to your site's settings.
- Click Create a webhook (or Create your first webhook).
- Choose the event that fires it (see below).
- Choose a built-in service, or fill in Custom web URL with your own address.
- Give it a name, leave Active? ticked, and click Save webhook.
Untick Active? to pause a webhook without deleting it. Remove on the list deletes it.
Events
| Event | When it fires |
|---|---|
| A discussion is created | Once, when a new discussion's first message is posted. |
| A discussion is created or replied to | For every message: the first one, each reply, and internal notes and the notes Tender adds itself (such as "The discussion has been closed."). |
| A discussion is added to a queue | When a discussion goes into a queue, including when it's assigned to someone. |
| A new user signs up | When anyone new is added to your site: people signing up, people writing in by email for the first time, people coming in through single sign-on, and users created through the API. |
| A knowledge base article is first published | When a published article is saved with a new publish date, which is usually the moment it's published. |
| A published knowledge base article is updated | Each time a published article is saved, including when it's first published. |
Messages Tender holds as spam, or that wait for your approval, don't fire a webhook. Drafts never do, and an article scheduled for a future date doesn't fire one when that date comes.
Internal notes are included. The "created or replied to" event sends internal notes too, with "internal": true. If your webhook passes messages on to customers or to a public place, check that field.
The request Tender sends
For each event, Tender sends a POST with Content-Type: application/json to your address, a second or so after the event. The body is a JSON object; its shape depends on the event.
Users: the user, as the Users API shows them to support staff:
{
"name": "Grace Liu",
"email": "grace@harborpine.example.com",
"created_at": "2026-10-09T07:16:24Z",
"activated_at": "2026-10-09T07:16:24Z",
"state": "user",
"title": "Operations Lead",
"trusted": false,
"company_id": 4,
"external_id": "hp-2041",
"href": "https://api.tenderapp.com/yoursite/users/20",
"discussions_href": "https://api.tenderapp.com/yoursite/users/20/discussions{?page,user_email}"
}
Discussions and replies: the message, as in Comments, with its author (user, when they have an account), its discussion and the discussion's category:
{
"body": "Thanks Priya. This is fixed in version 4.2: update the app and export again, and the custom field columns will be filled in.",
"formatted_body": "<div><p>Thanks Priya. This is fixed in version 4.2: update the app and export again, and the custom field columns will be filled in.</p></div>",
"created_at": "2026-10-09T07:17:25Z",
"number": 3,
"user_is_supporter": true,
"resolution": true,
"via": "web",
"internal": false,
"system_message": false,
"author_name": "Maya Okafor",
"author_email": "maya@juniper.example.com",
"user_href": "https://api.tenderapp.com/yoursite/users/10",
"user": {
"name": "Maya Okafor",
"email": "maya@juniper.example.com",
"state": "support",
"title": "Head of Support",
"href": "https://api.tenderapp.com/yoursite/users/10"
},
"discussion": {
"title": "Export to CSV leaves out custom fields",
"public": false,
"number": 10,
"state": "resolved",
"comments_count": 2,
"author_name": "Priya Nair",
"author_email": "priya.nair@example.com",
"extras": {
"plan": "Business",
"account_id": "4821"
},
"href": "https://api.tenderapp.com/yoursite/discussions/21",
"comments_href": "https://api.tenderapp.com/yoursite/discussions/21/comments{?page}",
"html_href": "https://yoursite.tenderapp.com/discussions/problems/10"
},
"category": {
"name": "Problems",
"permalink": "problems",
"public": true,
"href": "https://api.tenderapp.com/yoursite/categories/8",
"html_href": "https://yoursite.tenderapp.com/discussions/problems"
},
"assets": [],
"html_href": "https://yoursite.tenderapp.com/discussions/problems/10"
}
number is the message's place in the discussion (1 is the first message), resolution is true when the message resolved the discussion, and assets lists its attachments. The discussion has all the fields in Discussions and the category those in Categories.
Queues: the named_queue, the discussion (with its category inside it) and the user who queued it (null when Tender did it, for example through a filter):
{
"named_queue": {
"name": "Key accounts",
"permalink": "key-accounts",
"user_id": null,
"open_discussions_count": 2,
"href": "https://api.tenderapp.com/yoursite/queues/10",
"html_href": "https://yoursite.tenderapp.com/dashboard/queues/10-key-accounts"
},
"discussion": {
"title": "Export to CSV leaves out custom fields",
"state": "resolved",
"href": "https://api.tenderapp.com/yoursite/discussions/21",
"category": {
"name": "Problems",
"href": "https://api.tenderapp.com/yoursite/categories/8"
},
"html_href": "https://yoursite.tenderapp.com/discussions/problems/10"
},
"user": {
"name": "Maya Okafor",
"state": "support",
"href": "https://api.tenderapp.com/yoursite/users/10"
}
}
A queue with a user_id is that person's own queue: the discussion was assigned to them.
Knowledge base articles: the article, as in KB Articles:
{
"title": "Sharing a dashboard",
"body": "Open the dashboard and click **Share**.\n\n## Who can see it\n\nAnyone in your workspace can open a shared dashboard.",
"formatted_body": "<div><p>Open the dashboard and click <strong>Share</strong>.</p>\n<h2><a name=\"who-can-see-it\" class=\"anchor\" href=\"#who-can-see-it\"></a>Who can see it</h2>\n<p>Anyone in your workspace can open a shared dashboard.</p></div>",
"permalink": "sharing-a-dashboard",
"published_at": "2026-10-09T07:15:00Z",
"keywords": "dashboard share link public",
"version": 2,
"html_href": "https://yoursite.tenderapp.com/kb/reports-dashboards/sharing-a-dashboard",
"href": "https://api.tenderapp.com/yoursite/faqs/18",
"section_href": "https://api.tenderapp.com/yoursite/sections/7"
}
The bodies above are trimmed; the real ones have every field. Records don't carry a separate id: it's the number at the end of their href. All hrefs point at https://api.tenderapp.com, even if your site has its own domain.
Answer with any 2xx status, quickly. Tender doesn't read the answer.
Security: no signature, no retries
Tender doesn't sign its webhook requests, so your server can't tell from the request alone that it came from Tender. Put a secret in the address, such as a long random path or token, and refuse requests without it:
https://hooks.example.com/tender/7f3c9a51e2b84d06?token=Wq4nS8vL2xR9
Use https so the secret isn't sent in the clear. Tender refuses self-signed certificates.
Each event is sent once. If your server is down or answers with an error, Tender doesn't try again, and requests can arrive in a different order from the events. If you need to be sure you have everything, use the webhook as a nudge and fetch the current state from the API.
Test a webhook
Open a webhook from the list to see its settings and its Recent requests: the last five sends, each marked Success or Failed. Failed means Tender couldn't deliver the request at all (it couldn't connect, the address was wrong, or the certificate was refused); an error status from your server still shows as Success.
Test this webhook sends a real, recent record to it straight away: your newest user, a public message, your most recently updated published article or your latest queued discussion, depending on the event. Tender says whether it worked; it counts only a 200 answer as success.
Built-in services
Instead of your own address you can send discussion and queue events to a chat or phone service:
- Slack: posts the discussion's title with a link, who opened, replied to or resolved it (or which queue it went into), and the first lines of the message. Fill in Token with a Slack incoming webhook URL (
https://hooks.slack.com/services/...), Subdomain with your Slack workspace (examplefor example.slack.com) and Channel (such as#support). - Prowl: push notifications to an iPhone, for discussion events. Fill in your Prowl API key.
The list also shows HipChat and Campfire. Both services have closed, and those webhooks don't send anything.
Built-in services use the same events, so a Slack webhook on "created or replied to" posts internal notes in Slack too.
