Connect FlutterFlow to Everhour using the API Calls panel — create an API Group pointing to https://api.everhour.com with a single 'X-Api-Key' header (casing matters), then call GET endpoints for projects, team members, and time entries to build a timesheet dashboard. No OAuth required. The headline gotcha: the Everhour free plan may not include API access — confirm you are on a paid Team plan before debugging '401' errors.
| Fact | Value |
|---|---|
| Tool | Everhour |
| Category | Productivity |
| Method | FlutterFlow API Call |
| Difficulty | Intermediate |
| Time required | 40 minutes |
| Last updated | July 2026 |
Build a Timesheet Dashboard in FlutterFlow with Everhour
Everhour is a time tracking tool that sits neatly inside the tools teams already use — it integrates natively with Asana, Trello, ClickUp, Basecamp, and GitHub, layering time tracking onto tasks your team manages in those platforms. This makes it popular with agency teams and consulting firms who bill by the hour. A FlutterFlow mobile app backed by Everhour's API lets team members log time, check utilization, and review timesheets from their phone — particularly useful for field workers or remote teams who are not at a desk all day.
Everhour's pricing starts with a free plan for up to 5 team members, though multiple sources conflict on whether the free plan includes API access. The paid Team plan ranges from approximately $8–$10/user/month (verify current pricing at everhour.com/pricing) and definitely includes API access. The headline advice for this integration: before spending time debugging a 401 error, first confirm that your Everhour workspace is on a paid Team plan. A 401 on a free plan is not a configuration problem — it is a plan-gating wall that no amount of header tweaking will fix.
The integration itself is genuinely straightforward. Everhour's REST API uses a single X-Api-Key header — no OAuth, no token exchange, no redirect callback. The base URL is https://api.everhour.com, and endpoints like /team/users, /projects, and /team/time give you the core data for a utilization dashboard. The only production-readiness consideration is moving the API key server-side before releasing the app — a brief Firebase Cloud Function proxy handles that in under 30 minutes.
Integration method
Everhour's REST API uses a single API key in the 'X-Api-Key' header — no OAuth, no redirect flows, no token exchange. You create one API Group in FlutterFlow's API Calls panel with the base URL https://api.everhour.com and the static header, then call GET endpoints for projects, team users, and time entries. POST calls let users log new time records directly from a FlutterFlow form. For production, the key should be proxied through a Firebase Cloud Function rather than shipped in the compiled Flutter binary.
Prerequisites
- An Everhour account on a paid Team plan (API access may not be available on the free plan — verify before starting)
- Your Everhour API token from My Profile in the Everhour dashboard
- A FlutterFlow project (any plan) with at least one screen created
- Optional: a Firebase project with Cloud Functions enabled for production key proxying
- Familiarity with FlutterFlow's API Calls panel and Data Types (no coding knowledge required)
Step-by-step guide
Confirm your plan and get the Everhour API token
Before touching FlutterFlow, confirm that your Everhour workspace is on a paid Team plan. This is not a formality — the free plan's API access status is disputed across different sources, and if your workspace is on the free tier, every API call will return a 401 Unauthorized regardless of how correctly you have configured the integration. Log into Everhour at app.everhour.com, navigate to Settings (bottom-left) → Billing, and confirm your current plan. If you see 'Free', you need to upgrade to Team to proceed. Once on a paid plan, get your API token. Navigate to My Profile (click your avatar or name, bottom-left) → API section (or look for 'Token'). Copy the API token shown there. This is a long alphanumeric string that identifies your personal Everhour account — keep it in a password manager, not a code file. Note the exact header name: X-Api-Key — capital X, capital A, capital K. Header names are technically case-insensitive in HTTP, but certain implementations and FlutterFlow's API Call matching can be sensitive to casing. Match the casing shown in Everhour's official documentation exactly to avoid silent auth failures. Also note that each team member has their own API token. If you are building a dashboard that shows all team members' data (not just your own), you will use one admin or manager token on the server side — the /team/time endpoint returns data for all users when called with a token that has the appropriate access level.
Pro tip: If you see 401 errors during testing despite a correct-looking API key, the first thing to check is not the key but the plan. Upgrade to Team if needed, then re-test — the same key will start working immediately after the plan upgrade.
Expected result: You have confirmed your Everhour workspace is on a paid Team plan and have your API token copied from My Profile.
Create the Everhour API Group in FlutterFlow
Open your FlutterFlow project in the browser. In the left navigation panel, click API Calls (the plug icon). Click + Add → Create API Group. A dialog appears for name and base URL. Set: - Group name: Everhour - Base URL: https://api.everhour.com Do not add a trailing slash after 'everhour.com' — FlutterFlow appends the endpoint path you specify in each API Call directly to the base URL, and a double slash in the resulting URL can cause routing issues on some endpoints. Click the Headers tab. Add one header: - Header name: X-Api-Key - Value: your Everhour API token The header name must be X-Api-Key (capital X, capital A, capital K) — this matches Everhour's documented header name. Do not write 'x-api-key' (all lowercase) or 'X-API-KEY' (all uppercase K). While HTTP headers are officially case-insensitive in the RFC spec, using the exact documented casing avoids any potential issues. Do not add a 'Bearer ' prefix, an 'Authorization:' wrapper, or any other formatting — the value field should contain only the raw API token string. Click Save. The API Group is now configured. All API Calls you add inside this group will automatically include the X-Api-Key header in every request.
1// Everhour API Group configuration reference:2// Group name: Everhour3// Base URL: https://api.everhour.com4// Headers (static):5// X-Api-Key: your-everhour-api-token-here6//7// Note: header casing matters — use X-Api-Key exactly as shown8// Do NOT use: x-api-key, X-API-KEY, or Authorization: Bearer ...Pro tip: For team apps that will eventually have multiple users, consider adding the API key as an App State variable (populated at login) rather than a hardcoded static header — this way different tokens can be used for different users, though a Cloud Function proxy is the safer production approach.
Expected result: An 'Everhour' API Group appears in the API Calls panel with https://api.everhour.com as the base URL and X-Api-Key as a static header. No errors shown in the group configuration.
Add GET calls for projects and team data, map to Data Types
Inside the Everhour API Group, click + Add API Call. Name it 'Get Projects'. Set the method to GET and the endpoint to /projects (the full URL becomes https://api.everhour.com/projects). Go to the Response & Test tab and click Test to fire a live request. If you see 200 OK with a JSON array, your API key and plan are confirmed working. Paste the response JSON into the sample field and click Generate JSON Paths. Everhour projects have fields including id, name, billing (budget type), and members. Create a Data Type called 'EverhourProject' with fields: id (String), name (String). Map the JSON paths: $[*].id and $[*].name. Add a second API Call: 'Get Team Users'. Endpoint: /team/users. This returns all users in your Everhour workspace. Test it and create a Data Type 'EverhourUser' with fields: id (Integer), name (String), email (String). Map from: $[*].id, $[*].name, $[*].email. Add a third API Call: 'Get Team Time'. Endpoint: /team/time. This is the main worklog endpoint — it returns time entries for all team members. Add query variable parameters: - from (String) — start date, format: YYYY-MM-DD - to (String) — end date, format: YYYY-MM-DD - limit (Integer) — max entries per call (check Everhour docs for max, typically 200-500) Create a Data Type 'EverhourTimeEntry' with fields: id (String), user_id (Integer), project_id (String), task_id (String), date (String), time (Integer — seconds tracked). Map JSON paths from the response. Test with today's date as both from and to to verify the call returns entries. Note: Everhour's practical rate limit is not publicly published but is approximately 100 requests per minute from multiple sources. Keep this in mind for dashboard polling — a call every 5-10 minutes is safe; a call every few seconds is not.
1// JSON Path mappings after generating from sample responses:2// GET /projects:3// $[*].id → EverhourProject.id (String)4// $[*].name → EverhourProject.name (String)5//6// GET /team/users:7// $[*].id → EverhourUser.id (Integer)8// $[*].name → EverhourUser.name (String)9// $[*].email → EverhourUser.email (String)10//11// GET /team/time (with from/to query params):12// $[*].id → EverhourTimeEntry.id (String)13// $[*].user → EverhourTimeEntry.user_id (Integer)14// $[*].projectId → EverhourTimeEntry.project_id (String)15// $[*].date → EverhourTimeEntry.date (String)16// $[*].time → EverhourTimeEntry.time (Integer, seconds)Pro tip: Store projects and team users in App State after the first load and refresh them only occasionally (e.g., once per app session) — these lists change infrequently and do not need real-time updates. Save your rate-limit budget for the time entries endpoint.
Expected result: Three API Calls (Get Projects, Get Team Users, Get Team Time) exist in the Everhour group. Each returns 200 OK in the test panel. Data Types for projects, users, and time entries are created with JSON Path mappings.
Build the utilization dashboard: timesheet list and project breakdown
Create your main dashboard screen. At the top, add two DatePicker widgets (or a date range picker): start_date and end_date. Store the selected dates in App State variables. Add a 'Load Timesheets' Button. When the button is tapped, trigger an Action Flow that: 1. Calls Get Projects and stores the result in App State (List of EverhourProject) 2. Calls Get Team Users and stores in App State (List of EverhourUser) 3. Calls Get Team Time with the selected date range and stores in App State (List of EverhourTimeEntry) For the main list, add a ListView bound to the App State users list. Inside each row, show the user's name and their total time for the selected period. Use a Custom Function (not a Custom Action) in FlutterFlow to calculate the total: filter the EverhourTimeEntry list where user_id matches the current list item's id, then sum the 'time' field (in seconds). Divide by 3600 and format as 'Xh Ym' for display. Add a second list for project breakdown: a horizontal scrolling row of project chips or a separate screen showing time per project. Again use Custom Functions to group and aggregate the time entries list by project_id, look up the project name from the EverhourProject list, and display total hours. For the 'today' quick view, show a filtered subset: filter the time entries where date equals today's date string. Display these as a compact list at the top of the dashboard for the manager's first glance. Add empty state widgets to all ListViews so the screen does not appear broken when no time has been logged for the selected date range.
Pro tip: Convert Everhour's time field (stored in seconds as Integer) to hours and minutes for display using a Custom Function: hours = time / 3600, minutes = (time % 3600) / 60. FlutterFlow's Custom Functions support these integer operations and run in the widget build cycle without requiring a device build.
Expected result: The dashboard screen shows a list of team members with their total hours for the selected date range. A project breakdown section shows time allocated per project. The today view shows current-day entries.
Add a POST call to log time from a form
Inside the Everhour API Group, add a fourth API Call. Name it 'Log Time'. Set the method to POST. Everhour's time logging endpoint depends on whether you are logging time against a specific task or a project. The task-level endpoint is /tasks/{task_id}/time, and there is also a general time entry endpoint — check Everhour's current API documentation for the exact URL structure, as it has changed between API versions. For a simpler implementation, use the task-level endpoint: add a path variable task_id (String). In the Variables tab, add body variables: date (String, YYYY-MM-DD format), time (Integer, seconds). In the Body tab, select JSON body type and enter: { "time": {{time}}, "date": "{{date}}" } Create a time-logging screen (or a modal/bottom sheet from the dashboard). Add: - A Dropdown widget bound to the projects list from App State — when a project is selected, store its id - A TextField for hours (convert to seconds before the API call: multiply by 3600) - A DatePicker defaulting to today - A Button labeled 'Log Time' The Button's Action Flow: convert the hours text field value to an Integer, multiply by 3600, call the Log Time API Call with the result as the 'time' variable and the selected date. On success (HTTP 200 or 201), show a SnackBar 'Time logged successfully' and optionally refresh the team time data. On error, show the error message from the response body. Test this in FlutterFlow's Test Mode by logging a small amount of time (e.g., 60 seconds) and verifying it appears in your Everhour account's timesheet immediately.
1// POST /tasks/{{task_id}}/time2// Method: POST3// Headers: inherited from API Group (X-Api-Key)4// Path variable: task_id (String)5// Body (JSON):6{7 "time": {{time_in_seconds}},8 "date": "{{date}}"9}10// time_in_seconds: convert hours (e.g., 1.5) to seconds (5400) before passing11// date: YYYY-MM-DD format, e.g., '2026-07-10'12//13// To log against a project (if task_id is unknown):14// Check Everhour docs for project-level time entry endpointsPro tip: Everhour requires time in seconds (Integer), not hours. Add a FlutterFlow Custom Function to convert the user's input (hours, possibly a decimal like 1.5) to integer seconds: seconds = (hours * 3600).toInt(). Apply this conversion in the action before passing the value to the API Call.
Expected result: The time-logging form submits successfully and the new entry appears in Everhour's web interface. The SnackBar shows a confirmation message, and refreshing the dashboard shows the new entry in the team time list.
(Optional) Proxy the API key through a Firebase Cloud Function for production
For a production app release, the Everhour API key should not be embedded in the compiled Flutter binary. While time-tracking API keys have lower risk than payment credentials, a leaked key allows anyone who extracts it to read your team's time data, log fraudulent time entries, or deplete your API rate limits. The Firebase Cloud Function proxy pattern is consistent across all REST integrations: a Node.js function holds the API key in server-side Firebase environment config, receives requests from FlutterFlow, adds the X-Api-Key header, forwards the call to Everhour, and returns the response. In FlutterFlow, you update the API Group's base URL to point to the Cloud Function URL instead of api.everhour.com. The proxy function handles both GET calls (projects, users, time entries) and POST calls (logging time) by forwarding the method, path, query parameters, and request body from FlutterFlow to Everhour. Add CORS headers to the Cloud Function if you have a web build of your FlutterFlow app. Set the Everhour key using Firebase Functions config: firebase functions:config:set everhour.apikey='your-token-here'. The Cloud Function reads it as functions.config().everhour.apikey. If you prefer Supabase as your backend (many FlutterFlow apps already use Supabase), a Supabase Edge Function works identically — store the key as a Supabase environment secret and write a Deno function that proxies requests to Everhour. Choose whichever backend your app already uses to minimize new infrastructure. If you want help with this setup, RapidDev's team handles FlutterFlow integrations like this regularly and offers a free scoping call at rapidevelopers.com/contact.
1// Firebase Cloud Function — Everhour proxy (Node.js, index.js)2const functions = require('firebase-functions');3const axios = require('axios');45exports.everhourProxy = functions.https.onRequest(async (req, res) => {6 res.set('Access-Control-Allow-Origin', '*');7 if (req.method === 'OPTIONS') {8 res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');9 res.set('Access-Control-Allow-Headers', 'Content-Type');10 res.status(204).send('');11 return;12 }1314 const apiKey = functions.config().everhour.apikey;15 const path = req.query.path || '';16 const queryParams = { ...req.query };17 delete queryParams.path; // remove our own routing param1819 try {20 const response = await axios({21 method: req.method,22 url: `https://api.everhour.com/${path}`,23 headers: {24 'X-Api-Key': apiKey,25 'Content-Type': 'application/json'26 },27 params: queryParams,28 data: req.method === 'POST' || req.method === 'PUT' ? req.body : undefined29 });30 res.status(response.status).json(response.data);31 } catch (error) {32 const status = error.response ? error.response.status : 500;33 res.status(status).json(error.response ? error.response.data : { error: 'Proxy error' });34 }35});Pro tip: After switching FlutterFlow's API Group base URL to the Cloud Function URL, re-run all your API Call tests in the FlutterFlow test panel to confirm the proxy is forwarding correctly. Check the Cloud Function logs in the Firebase console if any calls start returning unexpected errors.
Expected result: FlutterFlow API Calls target the Cloud Function URL. Everhour data loads correctly through the proxy. The Everhour API key is stored in Firebase config and absent from the compiled app.
Common use cases
Agency utilization dashboard for account managers
A digital agency builds a FlutterFlow iPad app for account managers to check team utilization at a glance. The app calls Everhour's /team/users and /team/time endpoints to show hours logged per person today and this week, with a visual bar indicating how close each person is to their weekly target. Account managers can drill into any team member to see time split by project.
Build a utilization dashboard in FlutterFlow that shows each team member's hours logged today and this week from Everhour, with a progress bar showing percentage of a 40-hour target, and a drill-down to project-level breakdown.
Copy this prompt to try it in FlutterFlow
Mobile time logger for field workers
A construction consulting firm's field workers use a FlutterFlow iOS app to log their daily time entries directly from site. They select a project from a dropdown (populated from Everhour's /projects endpoint), enter hours and a note, and tap 'Log Time' — which POSTs the entry to Everhour via the API. At the end of the week, their timesheet is already populated in Everhour without manual data entry.
Build a time logging screen in FlutterFlow with a project dropdown, a duration input, and a notes field, with a 'Log Time' button that POST the entry to Everhour's API.
Copy this prompt to try it in FlutterFlow
Client billing summary app
A freelance team uses Everhour alongside ClickUp for project management. A FlutterFlow app pulls the current month's time entries from Everhour, groups them by project (which maps to client), and displays billable totals with an estimated invoice amount based on stored hourly rates. The data flows into the app in real-time via the Everhour API.
Build a monthly billing summary screen that reads this month's time entries from Everhour grouped by project, calculates billable hours, and displays total amounts per client with a grand total.
Copy this prompt to try it in FlutterFlow
Troubleshooting
401 Unauthorized on all API calls despite a correct API key
Cause: The most common cause is the free plan not including API access. Everhour's free plan API access status is inconsistent across sources — it may simply be blocked at the plan level, not a configuration error.
Solution: First, check your Everhour workspace plan in Settings → Billing. If you are on the free plan, upgrade to Team plan (approximately $8–$10/user/month, verify current pricing). After upgrading, use the exact same API key — it should start returning 200 immediately. If you are on a paid plan and still seeing 401, double-check the header name is X-Api-Key (capital X, capital A, capital K) and the value is the token from My Profile, not a different credential.
Headers work fine in a REST client but return 401 in FlutterFlow
Cause: A casing or formatting difference in the header name. The FlutterFlow API Group has the header set as 'x-api-key' (all lowercase) or 'X-API-KEY' instead of the documented 'X-Api-Key'.
Solution: Open the Everhour API Group in the API Calls panel, go to the Headers tab, and delete the existing header. Add a new one with the name typed character-by-character as X-Api-Key. Confirm the value field contains only the raw API token with no extra spaces, quotes, or 'Bearer' prefix.
GET /team/time returns an empty array even though the date range has recorded time
Cause: The date format for the from/to query parameters is incorrect, or the timezone offset in the dates does not match the Everhour account's timezone setting.
Solution: Verify the date format is YYYY-MM-DD (e.g., 2026-07-10). Everhour interprets dates in the timezone configured for your account. If you are in UTC+8 and enter today's date in UTC, you may be querying a different day than expected. Use the exact date string you see in Everhour's web interface for the same time range to cross-reference.
Rate limit errors after building a dashboard that polls frequently
Cause: Everhour's rate limit is approximately 100 requests per minute (not officially published). A dashboard refreshing every 30 seconds with 5 API calls per refresh reaches this limit in about a minute.
Solution: Add a minimum refresh interval using an App State 'lastRefreshed' timestamp. Only allow the 'Load Timesheets' button to trigger an API call if more than 5 minutes have passed since the last successful load. Cache the data in App State between refreshes. Display a 'Last updated X minutes ago' label so users understand why they cannot force-refresh immediately.
Best practices
- Check your Everhour plan first — if you are on the free tier, upgrade to Team before any debugging; free-plan 401 errors look identical to misconfiguration errors.
- Use the exact documented header casing 'X-Api-Key' — while HTTP headers are case-insensitive in spec, matching documentation casing avoids any potential implementation-specific failures.
- Never hardcode the API key as a static string in a FlutterFlow action — use a static header in the API Group for prototyping, and move to a Cloud Function proxy before releasing to app stores.
- Cache projects and team users in persisted App State and only refresh them on demand — these rarely change and should not consume rate-limit budget on every session open.
- Always include from/to date parameters when calling /team/time — open-ended calls may return unexpectedly large datasets and are slower than bounded queries.
- Convert time values before display (Everhour stores seconds as Integer) and before POST calls (user input in hours must be multiplied by 3600 before submission) — handle this in a FlutterFlow Custom Function.
- Add a visible 'last updated' timestamp and a minimum refresh interval to protect against rate-limit exhaustion when users tap the refresh button repeatedly.
- Test POST calls (time logging) with small values (e.g., 60 seconds) first to confirm they appear in Everhour's web interface before wiring up the production form.
Alternatives
Time Doctor provides activity monitoring, screenshots, and app-usage tracking that Everhour does not offer — choose it for remote teams where manager visibility into productivity is a requirement alongside time logging.
Teamwork bundles project management and time tracking in one platform with a similar API-key auth model, worth considering if your team wants combined task and time data without a separate integration tool.
ClickUp's built-in time tracking API uses personal tokens and is tightly integrated with ClickUp tasks — a natural choice if your team already uses ClickUp for project management and you want time data in the same ecosystem.
Frequently asked questions
Does the Everhour free plan include API access?
API access on the Everhour free plan is unclear — multiple sources conflict on whether it is included for free (up to 5 members) or requires a paid Team plan. The safest assumption is that a paid Team plan is required. Before spending time debugging a 401 error, check your plan in Everhour's Settings → Billing and upgrade if you are on the free tier. The same API key will work immediately after upgrading.
What is Everhour's API rate limit?
Everhour does not publish an official rate limit in their documentation. From practical experience, approximately 100 requests per minute is a safe threshold to stay under. Build your FlutterFlow dashboard with a minimum refresh interval of 5 minutes and avoid polling on every screen open — cache data in App State between refreshes to stay comfortably below the limit.
Can I read time entries from Everhour's integrations with Asana or Trello through the API?
Yes. Everhour's /team/time endpoint returns all time entries regardless of which platform the task originated from — whether it came from Asana, Trello, ClickUp, or Everhour's own interface. The project_id and task_id in the response correspond to Everhour's internal IDs, and you can cross-reference them using the /projects endpoint to get project names.
Does each team member need their own API key to log time, or can I use one key?
Each Everhour user has their own API token from their My Profile page. For a team app where each member logs their own time, each user should authenticate with their own token — stored securely server-side in a Cloud Function, with the FlutterFlow app authenticating users and then calling the appropriate proxy. For an admin-only dashboard that reads all team data, one manager-level token is sufficient, as the /team/time endpoint with an admin token returns data for all users.
Can I use Everhour to track time against specific tasks pulled from Asana or Trello?
Yes — if your Everhour account is connected to Asana, Trello, or ClickUp, the Everhour API exposes those tasks with their Everhour-assigned IDs. Use the /projects and task-level endpoints to list tasks, then POST to the task-level time endpoint to log time against them. Your FlutterFlow app would load Everhour tasks (which mirror your project management tool's tasks) and let users select and log against them.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation