How it works
- You register a
targetUrlviaPOST /hooks. - Everhour performs a handshake to verify the endpoint is reachable.
- When a subscribed event fires, Everhour POSTs the event payload to your URL.
Getting started with webhooks
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.Handle the handshake
When you create (or update) a webhook, Everhour sends a POST request to your Your endpoint must respond with any
targetUrl with the following headers: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.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
| Method | Path | Description |
|---|---|---|
GET | /hooks | List all webhooks for the authenticated user |
GET | /hooks/{id} | Get a single webhook |
POST | /hooks | Create a webhook (returns 201 Created) |
PUT | /hooks/{id} | Update subscribed events or project filter |
DELETE | /hooks/{id} | Delete a webhook (returns 204 No Content) |
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 aproject 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 | Triggered when |
|---|---|
api:project:created | A project is created |
api:project:updated | A project’s details are updated |
api:project:removed | A project is deleted |
api:task:created | A task is created |
api:task:updated | A task’s details are updated |
api:task:removed | A task is deleted |
api:task:recovered | A previously deleted task is restored |
api:timer:started | A timer is started |
api:timer:stopped | A running timer is stopped |
api:time:updated | A time record is created or modified |
api:section:created | A section is created |
api:section:updated | A section’s details are updated |
api:section:removed | A section is deleted |
api:section:recovered | A previously deleted section is restored |
api:client:created | A client is created |
api:client:updated | A client’s details are updated |
api:estimate:updated | A task estimate is changed |
api:invoice:created | An invoice is created |
api:invoice:updated | An invoice is updated |
api:invoice:deleted | An invoice is deleted |
Event payload structure
Everhour sends a POST request to yourtargetUrl with a JSON body in the following shape:
event— the event type that firedcreatedAt— timestamp of the event inYYYY-MM-DD HH:MM:SSformat (UTC)data.data— the full resource object, identical in shape to the corresponding REST API responseattributes.projects— list of project IDs related to the eventattributes.users— list of user IDs related to the eventuser— the Everhour user whose action triggered the event
Security
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-
2xxresponse, 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.
