Linking Everhour as a source

Beta release

This source is currently in beta. It works end to end, but you may still hit rough edges. Let us know if you do.

Let AI connect your sources for you

Skip the manual setup — run this in your project and the wizard auto-detects your databases and APIs and connects them to PostHog.

Learn more
PostHog Wizard hedgehog

Contents

Everhour is a time-tracking, budgeting, and resource-planning tool for teams. This source syncs your Everhour clients, projects, tasks, project sections, project custom fields, team members, time records, invoices, expenses, expense categories, timecards, timesheets, and resource planner assignments, time off types and allocations into the PostHog data warehouse so you can join time-tracking data with your product and revenue data.

Prerequisites

Using the Everhour API requires a paid Everhour plan. You'll need your personal API key, which you can find in your Everhour profile settings under the API section.

Adding a data source

  1. In PostHog, go to the Sources tab of the data pipeline section.
  2. Click + New source and click Link next to this source.
  3. Enter your credentials (see Configuration below) and click Next.
  4. Select the tables you want to sync, choose a sync method and frequency, then click Import.

Once the syncs are complete, you can start querying this data in PostHog.

You'll need your Everhour API key:

  1. Sign in to Everhour.
  2. Open your profile settings.
  3. Copy the key from the API section.

Paste the key into the API key field when connecting the source in PostHog. The key is sent only over the X-Api-Key header to https://api.everhour.com.

Sync modes

Each table can be synced in one of several modes, depending on what the source supports:

  • Webhook (when available) – the source pushes changes to PostHog in real time. Fastest freshness, lowest ongoing cost, and the only mode that reliably captures updates and deletes.
  • Incremental – only new or updated rows are synced on each run, using a cursor field (such as an updated_at timestamp). Cheaper than a full refresh, but deletes aren't captured.
  • Append only – new rows are appended using a cursor field; existing rows are never updated. Ideal for immutable, append-only tables like event logs.
  • Full refresh – the whole table is reloaded on every sync. Use it when a table has no reliable cursor or when you need deletions reflected.

See sync methods for a full explanation of how each mode works and how to choose between them.

Time records support incremental sync: PostHog uses Everhour's server-side from/to date window to pull only entries on or after the last synced date.

Every other table syncs as full refresh. Clients, projects, users, tasks, sections, custom fields, invoices, expenses, expense categories, timesheets, time off types, and allocations have no server-side change timestamp to filter on. Timecards and assignments do accept a date filter, but it selects rows by the day they cover rather than the day they changed, so it cannot tell PostHog what is new since the last sync.

Configuration

OptionTypeRequired
API keypasswordYes

Supported tables

TableDescriptionSync methodIncremental fieldPrimary key
clients

A client (customer) in the Everhour account that projects can be associated with.

Full refresh——
projects

A project tracked in Everhour, including its budget settings and total tracked time.

Full refresh——
users

A member of the Everhour team.

Full refresh——
tasks

A task within a project. Fanned out over every project, with the parent project id injected as project_id.

Full refresh——
sections

A section that groups the tasks of a project. Resolves the section id carried on tasks.

Full refresh——
custom_fields

A custom field configured on a project. Needed to read the custom field values stored on tasks. Fanned out over every project, with the parent project id injected as project_id.

Full refresh——
time_records

Individual time entries logged against tasks. Supports incremental sync via the server-side from/to date window.

Incremental, Full refreshdate—
invoices

A client invoice, including its line items, totals and billing period.

Full refresh——
expenses

A cost recorded against a project, used alongside time records for margin and billing.

Full refresh——
expense_categories

Expense category definitions, resolving the category id carried on every expense row.

Full refresh——
timecards

Clock-in and clock-out attendance per user per day. Separate from time records, which log time against tasks.

Full refresh——
assignments

Planned work and time off from the resource planner, giving the scheduled counterpart to logged time records.

Full refresh——
timesheets

A user's week of tracked work and its approval state. Fanned out over every team member.

Full refresh——
time_off_types

Time off category definitions, resolving the timeOffType id carried on assignments and allocations.

Full refresh——
allocations

How much time off of each type a user is entitled to over a period, and how much of it they have used.

Full refresh——

A few notes:

  • Time values are in seconds. The time field on time records and tasks is a duration in seconds (e.g. 3600 is one hour).
  • Tasks are fanned out per project. Each task row carries the parent project_id it was fetched under, and the primary key is (project_id, id) because a task can belong to more than one project. Sections and custom fields are also fetched per project. Custom field rows carry project_id too, and their primary key is (project_id, id).
  • Integration IDs are prefixed. Projects and tasks imported from integrations use a prefixed id (e.g. as: for Asana, jira: for Jira, tr: for Trello).
  • Timecards and time records are different things. A time record is time logged against a task. A timecard is a clock-in and clock-out for one person on one day. Timecards carry no id of their own, so the table is keyed on (user, date).
  • Invoice line items are nested. Each invoice row carries its line items in the invoiceItems column rather than in a separate table.
  • Assignments cover planned work and time off. The type column tells the two apart, and the rows reach into the future because they describe scheduled work.
  • Timesheets are fetched per person. Everhour's team-wide timesheet endpoint returns one week at a time, so PostHog reads each member's own timesheet history instead, going back about five years. Each row is one person's week, with its tasks, daily totals, timecards, scheduled time off, and approval history nested inside it.
  • Lookup tables resolve the ids on other rows. Expense categories name the category on an expense, time off types name the timeOffType on an assignment or an allocation, sections name the section a task sits in, and custom fields describe the custom field values on a task.
  • Allocations are entitlements, not bookings. A row says how many days off of one type a person has over a period and how many they have used. The time off they actually booked is in assignments.

Troubleshooting

  • Invalid API key – if the connection fails to validate, regenerate your key in your Everhour profile settings and reconnect. The key requires a paid Everhour plan.
  • Rate limits – Everhour rate-limits at roughly 20 requests per 10 seconds per API key. PostHog automatically honors the Retry-After header and backs off, so large initial syncs of time records may take a while to complete.

If your sync is failing or data looks wrong, see the Data warehouse troubleshooting guide. If that doesn't help, contact support – we're happy to help.

Still have questions?

Was this page useful?