Skip to content

Request an integration

Tell us which system you want to connect. We review every request each week. Then we publish a step-by-step guide or build the connection.

REST hooks for Zapier, Make and n8n

Let Zapier, Make and n8n subscribe to TimeTracking events themselves: POST /hooks to subscribe, DELETE /hooks/{id} to unsubscribe, GET /hooks/samples for field mapping, with setup steps per tool.

Last updated: · Markdown version

1. Summary

Status: Live (REST hooks API). Listed marketplace apps for Zapier and Make and a community node for n8n are still Planned; until then you build the trigger in each tool's developer platform or with plain HTTP steps, as described below.

Direction: TimeTracking to the tool (triggers). For actions (the tool writing to TimeTracking) use the REST API as in the Zapier, Make and n8n recipes.

A REST hook is a webhook that the automation tool creates and removes itself: when a zap, scenario or workflow is switched on, the tool calls POST /hooks with its own receiving URL; when it is switched off, it calls DELETE /hooks/{id}. No one has to copy URLs or secrets between the dashboard and the tool.

2. Endpoints

All endpoints need an API key with the admin scope (dashboard Rules & integrations → API keys → Admin), because a hook sends organisation data to a URL. Use a separate key per tool.

Call Purpose
POST /api/v1/hooks Subscribe. Body: url (aliases target_url, hookUrl), event or events, optional source (zapier, make, n8n, …) and name. Returns the subscription with id and the signing secret (once).
DELETE /api/v1/hooks/{id} Unsubscribe (deletes the webhook). Answers { "deleted": true }; 404 when it is already gone.
GET /api/v1/hooks/{id} Does the subscription still exist? (n8n checkExists.)
GET /api/v1/hooks Subscriptions made through POST /hooks.
GET /api/v1/hooks/samples?event=… Example events (the exact delivered envelope) for field mapping. Without event: one example per event type. Any valid key.
curl -s -X POST "$TT/hooks" -H "Authorization: Bearer $ADMIN_KEY" -H "content-type: application/json" \
  -d '{"target_url":"https://hooks.zapier.com/hooks/standard/123/abc/","event":"timesheet.submitted","source":"zapier"}'
{ "data": { "id": "6b0f…", "url": "https://hooks.zapier.com/hooks/standard/123/abc/", "events": ["timesheet.submitted"],
            "source": "zapier", "name": "Zapier", "active": true, "created_at": "2026-10-30T09:12:01.120Z", "secret": "whsec_…" } }

Deliveries are ordinary webhooks: an HTTPS POST with the envelope { id, type, created, data }, the tt-signature header, retries with backoff (7 attempts over about 21 hours), a delivery log and replay. The URL must be https:// and resolve to a public address. An organisation can have at most 100 REST hooks. Subscriptions show on the dashboard (Rules & integrations → Zapier, Make and n8n), where an admin can delete them.

The events are listed in the event catalogue; GET /hooks/samples returns the same shapes.

3. Zapier

In the Zapier Platform UI (or CLI) create a private integration:

  1. Authentication → API Key: one field api_key; add the header Authorization: Bearer {{bundle.authData.api_key}} to every request. Test call: GET https://app.timetracking.tech/api/v1/hooks/samples?event=webhook.test.
  2. Trigger → REST Hook, one trigger per event (for example "Hours submitted" = timesheet.submitted):
    • Subscribe: POST https://app.timetracking.tech/api/v1/hooks, body {"target_url": "{{bundle.targetUrl}}", "event": "timesheet.submitted", "source": "zapier"}.
    • Unsubscribe: DELETE https://app.timetracking.tech/api/v1/hooks/{{bundle.subscribeData.data.id}}.
    • Perform List (sample data and polling fallback): GET https://app.timetracking.tech/api/v1/hooks/samples?event=timesheet.submitted, and return response.data (an array with id).
    • Perform: return [bundle.cleanedRequest] (the delivered event).
  3. Actions: Create claim, Upsert person by external ID and so on, as plain API requests (see the Zapier recipe). Send an Idempotency-Key header.

Without your own integration, the Catch Raw Hook recipe still works: create the webhook yourself in the dashboard.

4. Make

In Make's custom app editor (My apps → Create a new app):

  1. Connection: one parameter apiKey; base headers Authorization: Bearer {{connection.apiKey}}.
  2. Webhook (type dedicated, attached):
    • Attach: POST https://app.timetracking.tech/api/v1/hooks, body {"url": "{{webhook.url}}", "events": {{parameters.events}}, "source": "make"}, response "data": {"externalHookId": "{{body.data.id}}"}.
    • Detach: DELETE https://app.timetracking.tech/api/v1/hooks/{{webhook.externalHookId}}.
  3. Instant trigger using that webhook; Samples: paste a result of GET /hooks/samples?event=…, or call it in the module's epoch/sample request.

Without a custom app: create a Custom webhook in a scenario, then register its URL once with POST /hooks (HTTP module or curl) and remove it with DELETE /hooks/{id} when the scenario is retired.

5. n8n

For a community/custom node, implement the trigger node's webhookMethods.default:

  • checkExists: GET /api/v1/hooks/{{webhookData.hookId}} → true on 200, false on 404.
  • create: POST /api/v1/hooks with {"url": this.getNodeWebhookUrl("default"), "events": [...], "source": "n8n"}; store data.id as webhookData.hookId and data.secret to verify tt-signature in webhook().
  • delete: DELETE /api/v1/hooks/{{webhookData.hookId}}.

Without a custom node: add a Webhook trigger node (POST, response 200), activate the workflow, and register the production URL once with an HTTP Request node (POST /hooks, header Authorization: Bearer <admin key>). Use GET /hooks/samples?event=… to pin test data. Verify the signature with a Crypto node as in the n8n recipe.

6. Limits and errors

Answer Meaning
403 forbidden "Admin role required" The key has no admin scope.
422 invalid No url/event, an unknown event, an http:// URL, or a URL that resolves to a private address.
409 conflict reason: hook_limit 100 REST hooks in the organisation; delete unused ones.
404 not_found on DELETE Already removed (treat as success).
429 rate_limited Over the key's budget; see rate limits and the X-RateLimit-* headers.

Rotate a hook's secret with POST /webhooks/{id}/rotate-secret; replay a failed delivery with POST /webhook-deliveries/{id}/replay.