Skip to main content
Webhooks let your application receive HTTP POST notifications whenever something changes in Everhour — a task is created, a timer is stopped, an invoice is updated. Instead of polling the API, you register a URL and Everhour delivers events to it as they happen.

How it works

  1. You register a targetUrl via POST /hooks.
  2. Everhour performs a handshake to verify the endpoint is reachable.
  3. When a subscribed event fires, Everhour POSTs the event payload to your URL.

Getting started with webhooks

1

Register a webhook

Send a POST /hooks request with your targetUrl and the list of events you want to receive.Your endpoint must be publicly reachable. Everhour will immediately perform a handshake to confirm it is live.A successful registration returns 201 Created. If the handshake fails, you will receive an Invalid callback error. If you have already registered an active webhook for the same URL, you will receive 409 Conflict. If a previous webhook for that URL was disabled, it will be restored instead.
2

Handle the handshake

When you create (or update) a webhook, Everhour sends a POST request to your targetUrl with the following headers:
Your endpoint must respond with any 2xx status code. No specific response body is required. If you do not respond with 2xx, the subscription request is rejected.The X-Hook-Secret value is sent once during the handshake only. It is not repeated on event deliveries.For automated testing or CI environments where you cannot serve a live endpoint, include the X-Skip-Handshake: true header on your subscription request to bypass the handshake check.
3

Receive events

After a successful handshake, Everhour will POST event payloads to your URL whenever a subscribed event fires. Events are delivered asynchronously via an internal message queue.Respond with a 2xx status to acknowledge receipt. Sustained delivery failures may cause Everhour to set the webhook active=false. To reactivate a disabled webhook, send a PUT /hooks/{id} request with the desired events list.

Registering a webhook

Managing webhooks

Webhooks are scoped to the authenticated user — each API key sees only the webhooks it created. A user cannot register the same targetUrl more than once. When updating a webhook with PUT /hooks/{id}, the targetUrl field is ignored. You can change only the subscribed events and the project filter. A handshake is performed again on update to confirm the endpoint is still reachable.

Project-scoped webhooks

A webhook can be scoped to a single project by including a project field on creation. Project-scoped webhooks receive events only for that project.
Project-scoped webhooks cannot subscribe to api:project:created, api:client:*, or api:invoice:* events. Those events are account-level and are only available on unscoped webhooks.

Event types

At least one event must be selected when creating a webhook.

Event payload structure

Everhour sends a POST request to your targetUrl with a JSON body in the following shape:
  • event — the event type that fired
  • createdAt — timestamp of the event in YYYY-MM-DD HH:MM:SS format (UTC)
  • data.data — the full resource object, identical in shape to the corresponding REST API response
  • attributes.projects — list of project IDs related to the event
  • attributes.users — list of user IDs related to the event
  • user — the Everhour user whose action triggered the event

Security

Everhour does not sign event delivery payloads. There is no HMAC or signature header on the POST requests sent to your targetUrl. The X-Hook-Secret header is only sent once during the subscription handshake and is not repeated on event deliveries.To secure your endpoint, use TLS (HTTPS) and treat the targetUrl itself as a secret. Anyone who knows the URL can POST arbitrary data to it, so avoid publishing or logging the URL.
The handshake on subscription creation verifies that your endpoint is reachable, but it does not establish an ongoing trust mechanism. Design your endpoint to validate the structure and content of incoming payloads as appropriate for your use case.

Delivery and reliability

  • Deliveries are asynchronous. There is no guaranteed maximum latency between an event firing and your endpoint being called.
  • If your endpoint returns a non-2xx response, Everhour will retry delivery. Sustained failures may cause the webhook to be automatically disabled (active=false).
  • To reactivate a disabled webhook, send a PUT /hooks/{id} request with the desired events list. This triggers a new handshake.
  • Specific retry counts and timeout windows are managed internally and are not configurable via the API.