> ## Documentation Index
> Fetch the complete documentation index at: https://docs.timetracker.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up webhook endpoints

> Add an HTTPS endpoint, pick the events it receives, copy the signing secret, send a test event, and read the delivery log with its retries.

**Settings → Webhooks** is where you register the HTTPS addresses that receive
your workspace's events. The page header says it plainly:

> Send workspace events to your own systems over HTTPS. Every delivery is signed
> with a per-endpoint secret you can verify from the `X-TimeTracker-Signature`
> header.

<Info>
  The concept and the receiving side live on
  [/integrations/webhooks](/integrations/webhooks). This page documents the screen.
</Info>

## Before you start

| Requirement | Detail                                  |
| ----------- | --------------------------------------- |
| App         | The **Webhooks & API** app must be on   |
| Plan        | Pro. The plan feature is `integrations` |
| Capability  | `webhook.manage`                        |

`webhook.manage` is held by **Owner and Admin only**. It is deliberately kept
away from Project Manager, Finance, Member and Contractor, because an endpoint
can carry every workspace event out to an external address. It can be granted to
a custom role. See [/settings/roles](/settings/roles).

Without the capability, the **Webhooks** nav item does not appear. If you reach
the URL anyway, the page shows a no-access panel.

## What is on the page

* A page action in the top right: **Add endpoint**.
* One card per endpoint, below it.

### Empty state

With no endpoints, you get:

> **No webhook endpoints yet**
> Send workspace events to your own systems. Add an HTTPS endpoint and choose
> which events to receive.

An **Add endpoint** button sits under it.

### The endpoint card

Each endpoint is its own card. The card's title is the endpoint URL – hover it to
read the full address.

| Part of the card | What it shows                                                         |
| ---------------- | --------------------------------------------------------------------- |
| Title            | The endpoint URL                                                      |
| Status badge     | **Active**, **Failing** or **Disabled**                               |
| Actions menu     | The three-dot **Endpoint actions** menu                               |
| Event badges     | One badge per selected event filter, or a single **All events** badge |
| Failure count    | "N consecutive failures", shown only when N is above zero             |
| Added            | "Added" with the date the endpoint was created                        |
| Delivery log     | An expander that opens the delivery history                           |

The status badge is derived, not something you set:

| Badge        | Meaning                                                                    |
| ------------ | -------------------------------------------------------------------------- |
| **Active**   | Switched on, with no consecutive failures                                  |
| **Failing**  | Switched on, but the last deliveries failed                                |
| **Disabled** | Switched off by you, or switched off automatically after repeated failures |

### The three-dot menu

| Item            | What it does                                               |
| --------------- | ---------------------------------------------------------- |
| Rotate secret   | Replaces the signing secret and shows the new one once     |
| Send test event | Fires a synthetic `webhook.test` delivery at this endpoint |
| Edit            | Opens the edit dialog                                      |
| Delete          | Opens the delete confirmation                              |

## Add an endpoint

<Steps>
  <Step title="Open the dialog">
    Click **Add endpoint**. The dialog is titled **Add endpoint** and says
    "Choose which events this endpoint receives. Leave the filter empty to
    receive every event."
  </Step>

  <Step title="Enter the URL">
    Type the address in **Endpoint URL**. It is required. The placeholder shows
    the shape: `https://api.example.com/webhooks/timetracker`.
  </Step>

  <Step title="Choose the events">
    Use **Event filters** to pick the categories this endpoint should receive.
    Leaving it empty means every event. The hint under the field says so:
    "No selection means this endpoint receives every event."
  </Step>

  <Step title="Save">
    Click **Add endpoint**. The dialog closes and the signing secret dialog opens
    immediately.
  </Step>

  <Step title="Copy the secret">
    Copy the secret before you close that dialog. It is never shown again.
  </Step>
</Steps>

A new endpoint is created active. Use **Edit** later if you want to switch it off.

<Warning>
  Endpoints must be public HTTPS addresses. Private, loopback and metadata
  addresses are rejected, both when you save and again at the moment of every
  delivery.
</Warning>

## The event catalogue

**Event filters** is a multi-select of ten categories. An endpoint with no filter
receives everything.

| Filter        | Covers                                   |
| ------------- | ---------------------------------------- |
| Assignments   | Work assigned to someone                 |
| Due soon      | Tasks approaching their due date         |
| Overdue       | Tasks past their due date                |
| Mentions      | Someone mentioned in a comment           |
| Timesheets    | Timesheet submission and review activity |
| Budget alerts | A project budget crossing a threshold    |
| Scope changes | Estimate and scope approval activity     |
| Invoices      | Invoice activity, including exports      |
| Time off      | Leave requests and decisions             |
| Timecard      | Clock-in and clock-out activity          |

Each category holds several individual event keys. The full list of keys and the
shape of the body is on
[/reference/webhook-events](/reference/webhook-events).

## The signing secret

Every endpoint has its own secret. It is shown **exactly once** and there is no
screen anywhere that shows it again.

### Right after you add an endpoint

The dialog is titled **Copy your signing secret**:

> This secret is shown once. Store it now – you won't be able to see it again.
> Use it to verify the X-TimeTracker-Signature header.

It holds a read-only field with the secret, a **Copy** button that turns into
**Copied**, and a **Done** button. Copying raises a "Copied to clipboard." toast.

### Rotating the secret

<Steps>
  <Step title="Open the menu">
    On the endpoint card, open the three-dot menu and choose **Rotate secret**.
  </Step>

  <Step title="Confirm">
    A confirmation asks "Rotate signing secret?" and explains: "Rotating
    invalidates the current secret immediately. In-flight deliveries keep their
    existing signature; new deliveries use the new secret." Click **Rotate
    secret**.
  </Step>

  <Step title="Copy the new secret">
    A dialog titled **New signing secret** appears: "The previous secret is now
    invalid. Update your receiver with this value. It won't be shown again."
    Copy it, then click **Done**.
  </Step>
</Steps>

<Warning>
  Rotate only when your receiver is ready to accept the new value. The old secret
  stops being valid the moment you confirm.
</Warning>

## Turning an endpoint on and off

The **Active** switch lives in the edit dialog. Its hint reads: "When off, no
events are delivered to this endpoint."

Switching it off is not the same as deleting. The endpoint, its filters and its
delivery history all stay.

## Edit an endpoint

<Steps>
  <Step title="Open the dialog">
    Three-dot menu, then **Edit**. The dialog is titled **Edit endpoint**.
  </Step>

  <Step title="Change what you need">
    You can change the **Endpoint URL**, the **Event filters** and the **Active**
    switch. The signing secret is not touched here – rotating is a separate
    action.
  </Step>

  <Step title="Save">
    Click **Save changes**. A toast confirms "Endpoint updated."
  </Step>
</Steps>

## Send a test event

Open the three-dot menu and choose **Send test event**. The item shows a spinner
while it sends, and every other action stays usable.

| Result | What you see                                      |
| ------ | ------------------------------------------------- |
| Sent   | Toast: "Test event sent."                         |
| Failed | Toast: "Test event failed: …" with a short reason |

A test delivery appears in the delivery log with the event `webhook.test`. It
never creates or changes any real workspace data, so you can verify your
receiver's signature check and reachability without waiting for a real event.

## The delivery log

Each endpoint card has a **Delivery log** expander. Open it to see recent
attempts.

While it loads you get placeholder rows. With no history it reads
"No deliveries yet."

| Column    | What it holds                                                                       |
| --------- | ----------------------------------------------------------------------------------- |
| Event     | The event's identifier, or `webhook.test` for a test delivery                       |
| Status    | The delivery state badge, with the HTTP response code after a dot when there is one |
| Attempt   | Which attempt number this row is                                                    |
| Time      | When the attempt ran                                                                |
| Redeliver | A **Redeliver** button for that attempt                                             |

Delivery states:

| Badge         | Meaning                                    |
| ------------- | ------------------------------------------ |
| **Delivered** | Your endpoint accepted it                  |
| **Retrying**  | It failed and another attempt is scheduled |
| **Failed**    | It gave up on this delivery                |
| **Pending**   | It is queued and has not run yet           |

The log shows the most recent **100** attempts, newest first.

### Redelivering

Click **Redeliver** on any row to send that event again.

| Result  | What you see                  |
| ------- | ----------------------------- |
| Queued  | Toast: "Delivery re-queued."  |
| Refused | Toast: "Couldn't re-queue: …" |

A redelivery creates a **new** attempt row. The original attempt is never
changed, so the log stays a faithful history. The redelivery uses whatever secret
is current, so it works after a rotation.

## Retries and automatic disabling

| Rule                                   | Value                                           |
| -------------------------------------- | ----------------------------------------------- |
| Attempts per delivery                  | Up to 6                                         |
| First retry wait                       | 30 seconds                                      |
| Backoff                                | Doubles each attempt, up to 1 hour, with jitter |
| Rate limited (429)                     | Honours your `Retry-After` header               |
| Server errors (5xx) and network errors | Retried                                         |
| Client errors (4xx)                    | Not retried – it fails straight away            |
| Auto-disable                           | After **20** consecutive terminal failures      |

A rejected or unsafe URL is never retried.

### When an endpoint is auto-disabled

The card shows a red alert above everything else:

> **Endpoint disabled after repeated failures**
> We stopped sending after N consecutive failures. Fix your receiver, then
> re-enable this endpoint.

A **Re-enable** button sits beside it.

<Steps>
  <Step title="Fix your receiver first">
    Re-enabling with a broken receiver only starts the failure count again.
  </Step>

  <Step title="Click Re-enable">
    A confirmation asks "Re-enable this endpoint?" and warns: "Deliveries resume
    immediately and the failure count resets. Make sure your receiver is fixed
    first."
  </Step>

  <Step title="Confirm">
    Click **Re-enable**. A toast confirms "Endpoint re-enabled."
  </Step>
</Steps>

## Delete an endpoint

<Steps>
  <Step title="Open the menu">
    Three-dot menu, then **Delete**.
  </Step>

  <Step title="Read the warning">
    The modal asks "Delete this endpoint?" and states: "This permanently deletes
    the endpoint and its delivery history. This cannot be undone."
  </Step>

  <Step title="Type the URL">
    You must type the endpoint URL into the field labelled "Type the endpoint URL
    to confirm". The button stays disabled until it matches.
  </Step>

  <Step title="Confirm">
    Click **Delete endpoint**. A toast confirms "Endpoint deleted."
  </Step>
</Steps>

<Warning>
  Deleting removes the delivery history with it. If you only want to stop
  deliveries, switch the endpoint off instead.
</Warning>

## Error states

| Where             | Message                                                                                                                     | What it means                                                          |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Add / Edit dialog | "This URL can't be used. Endpoints must be public HTTPS addresses – private, loopback, and metadata addresses are blocked." | The address is not reachable from the public internet, or is not HTTPS |
| Add / Edit dialog | "Couldn't save this endpoint. Check the URL and try again."                                                                 | The save failed for another reason                                     |
| Card              | "Test event failed: …"                                                                                                      | The test delivery did not succeed                                      |
| Delivery log      | "Couldn't re-queue: …"                                                                                                      | The redelivery was refused                                             |

## Example

Tom Whitfield (Admin) at Northwind Studio wants their internal ops dashboard to
hear about approvals and money.

1. He clicks **Add endpoint** and enters
   `https://hooks.northwind.example/timetracker`.
2. In **Event filters** he picks **Timesheets** and **Invoices**.
3. He clicks **Add endpoint**, copies the signing secret, and pastes it into the
   dashboard's configuration.
4. He opens the three-dot menu and chooses **Send test event**, then expands
   **Delivery log** and sees one row: event `webhook.test`, status **Delivered ·
   200**, attempt 1.

Priya Raman (Project Manager) cannot see this page at all – `webhook.manage` is
Owner and Admin only.

## App off vs not on your plan

| State                           | What happens                                                                                                                                                                                                    |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Webhooks & API switched off** | The **Webhooks** nav item disappears. Endpoints stop receiving events. Anything that happens while it is off is **queued and delivered when you turn it back on**. Configuration and delivery history are kept. |
| **Not on your plan (Free)**     | The item stays in the sidebar. The page shows a blurred shape with an upgrade card: "Upgrade to Pro to unlock Integrations."                                                                                    |

<Note>
  Switching the app off does not lose events. A queued delivery waits for the
  switch rather than failing, and no retry is consumed while it waits.
</Note>

## Common questions

<AccordionGroup>
  <Accordion title="Can I see a secret again after I close the dialog?">
    No. There is no screen that shows an existing secret. If you lost it, use
    **Rotate secret** and update your receiver with the new value.
  </Accordion>

  <Accordion title="How quickly does an event arrive?">
    An event reaches a matching endpoint within about a minute of it happening.
  </Accordion>

  <Accordion title="Can I use an http:// address or a local one?">
    No. Endpoints must be public HTTPS addresses. The address is checked when you
    save it and again at the moment of every delivery, so an address that later
    points somewhere private is rejected then too.
  </Accordion>

  <Accordion title="What happens to queued retries when I rotate the secret?">
    A delivery already in flight keeps the signature it was created with. New
    deliveries use the new secret. A manual **Redeliver** uses the current one.
  </Accordion>

  <Accordion title="Why does my endpoint say Failing when deliveries look fine?">
    **Failing** means at least one consecutive failure has been recorded since
    the last success. Open the **Delivery log** and look for the most recent
    **Failed** row and its response code.
  </Accordion>
</AccordionGroup>

## Related guides

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/integrations/webhooks">
    How to receive and verify a delivery.
  </Card>

  <Card title="Webhook events" icon="list" href="/reference/webhook-events">
    Every event key and what it carries.
  </Card>

  <Card title="Apps" icon="toggle-on" href="/settings/apps">
    Switching Webhooks & API on or off.
  </Card>

  <Card title="Roles and capabilities" icon="shield" href="/concepts/roles-and-capabilities">
    Why `webhook.manage` is Owner and Admin only.
  </Card>

  <Card title="Free vs Pro" icon="star" href="/billing/free-vs-pro">
    What the Integrations feature includes.
  </Card>

  <Card title="All settings" icon="gear" href="/settings/overview">
    Every settings page and who can open it.
  </Card>
</CardGroup>
