# Webhooks

Source: https://docs.tightly.io/help/settings/webhooks
Reviewed: 2026-09-07

## The question this page answers

Which outside systems are told when a purchase order is created or changes, is the last post arriving, and how do I add, re-sign or stop one? The Webhooks page is built but not yet open on Tightly: it has no address a customer can reach, so the Developer group of the settings rail shows API keys and Metrics without it, Integrations draws no Webhooks row, and an old Webhooks link lands on the Integrations list. This article says what the page shows and does once it opens. How to verify a signed post and what a delivery carries is the developer portal's Webhooks guide.

## What you see

Where there are webhooks the head says nothing, because the rows are the count; with none the card reads "No webhook fires yet."

One table, newest first: **Address**, the URL in ink, cut in the middle where it is too long for the column so two addresses on one host still differ, with the whole address on hover; **Event**, `New purchase order` or `Purchase order updated`, the two the page adds, and a webhook subscribed to another event through the API shows that event's own name; **Delivered**, `Not sent yet` for a signed webhook or `No secret yet` for one added before signing existed; **Since**, the day it was added, or `Not dated`. The Delivered column stands only once a row differs from the rest: while every row reads the same absence the column leaves the table rather than repeating one word down it. The row menu offers Deliveries, and to members New secret and Remove.

**Deliveries** opens a drawer with one row per post: When, Event (dropped where every post is the same event), Status (`Delivered` or `Failed`, or the server's own word for a post still being retried) and Attempts, a count of tries for one post. The last try's answer rides the status word on hover: "Last attempt answered {status}." or "Last attempt reached no server."

## What to do

**Add a webhook** opens a drawer with Address and Event, and the consequence before the one button: "Tightly posts each {event} to this address as it happens." The receipt is the signing secret, shown once, with Copy and "Copy it now; Tightly cannot show this secret again." The new row appears first.

**New secret** rotates the secret and shows the new one once; the consequence is "A new secret signs every post from now; anything checking the old one stops accepting them."

**Remove** carries "{System} stops firing on purchase orders." before the button, where the system is the host the address names, or the whole address where two rows share a host; the decline is Keep it.

Members change these, because a webhook is not a key and does not outlive a person; a viewer reads the table, and "Members change this" stands once where the buttons would be. The page and its routes are on Tightly Essentials, Essentials+ and Pro; a Lite tenant is refused, unless it held a live webhook before the plan gate existed. Every post is signed with the webhook's secret in an `X-Tightly-Signature` header. A post that fails is retried three times, after one minute, ten minutes and an hour, so four attempts in all, and every attempt is recorded.

## When it is empty or failed

A failed read prints "The webhooks did not load." with Try again; a failed deliveries read "The deliveries did not load." No posts yet prints "Nothing sent to this address." in the drawer. Removing or re-signing a webhook that no longer exists prints the server's own sentence:

> Webhook not found

A write the server refused without a sentence reads "The webhook was not added; nothing changed.", "The webhook was not removed; nothing changed." or "The secret was not changed; nothing changed."
