Skip to main content
RapidDev - Software Development Agency
v0-integrationsNext.js API Route

How to Integrate Clockify with V0

To integrate Clockify with V0 by Vercel, create a Next.js API route at app/api/clockify/route.ts that calls the Clockify REST API using an API key stored in CLOCKIFY_API_KEY. V0 generates time tracking dashboards and report components that fetch from your API route. Clockify offers a generous free tier with unlimited users, making it ideal for displaying team time data in custom apps.

What you'll learn

  • How to generate a Clockify API key and find your workspace ID
  • How to create a Next.js API route that fetches time entries and project summaries
  • How to prompt V0 to generate time tracking dashboards and weekly report views
  • How to filter Clockify data by date range, project, and user
  • How to display billable hours and budget tracking information in your V0 app
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read20 minutesProductivityApril 2026RapidDev Engineering Team
TL;DR

To integrate Clockify with V0 by Vercel, create a Next.js API route at app/api/clockify/route.ts that calls the Clockify REST API using an API key stored in CLOCKIFY_API_KEY. V0 generates time tracking dashboards and report components that fetch from your API route. Clockify offers a generous free tier with unlimited users, making it ideal for displaying team time data in custom apps.

Building Time Tracking Dashboards with Clockify and V0

Clockify is one of the most popular free time trackers because it places no artificial limits on users, projects, or tracked time — the core functionality is genuinely free. Many freelancers, agencies, and distributed teams use Clockify but want custom-branded reports or client-facing dashboards that look better than Clockify's built-in reports. V0 makes it easy to build exactly those custom views.

The integration pattern creates a Next.js API route that authenticates with Clockify using your API key stored in Vercel's environment variables. V0 generates the front-end components — weekly summaries, project hour breakdowns, billable versus non-billable charts, or team utilization heatmaps — that fetch data from your secure API route. The Clockify API key never touches the browser, which is important because Clockify API keys grant access to your entire workspace including all team members' time data.

Clockify's API covers three main data categories: time entries (individual tracked sessions with start/end times and project association), summary reports (pre-aggregated totals grouped by user, project, client, or date), and detailed reports (all entries with full metadata). For most dashboards, the summary report endpoint is more efficient because Clockify does the aggregation server-side rather than returning thousands of raw entries for your app to sum up.

Integration method

Next.js API Route

V0 generates React dashboard components for displaying Clockify time tracking data. A Next.js API route on Vercel proxies requests to the Clockify REST API, keeping your API key server-side. The components fetch from /api/clockify/entries rather than calling Clockify directly, which avoids CORS errors and keeps credentials out of the browser.

Prerequisites

  • A V0 account with a Next.js project at v0.dev
  • A Clockify account at clockify.me with at least one workspace and some tracked time entries
  • A Clockify API key generated from your Clockify profile settings
  • Your Clockify Workspace ID (visible in the Clockify workspace settings URL)
  • A Vercel account with your V0 project connected via GitHub

Step-by-step guide

1

Get Your Clockify API Key and Workspace ID

You need two values from Clockify before writing any code: your API key and your Workspace ID. Both are straightforward to find in the Clockify web app. To get your API key, click on your profile picture or initials in the top-right corner of Clockify, then select 'Profile Settings' from the dropdown. Scroll down to find the 'API' section. You will see your API key displayed there — click the 'Copy' button. The key is a long hexadecimal string. This key grants full API access to your Clockify workspace including reading all team members' time entries and reports. To find your Workspace ID, go to your Clockify workspace settings. The simplest way is to look at the URL when you are in the workspace settings: https://clockify.me/workspaces/{workspaceId}/settings. The workspaceId portion of the URL (a 24-character hexadecimal string) is your Workspace ID. Alternatively, once you have your API key, you can make a quick test call to https://api.clockify.me/api/v1/workspaces with your API key in the X-Api-Key header — the response contains an array of your workspaces with their IDs. Clockify's API also uses user IDs for fetching specific users' time entries. If you need to filter by user, note the user ID from the /api/v1/workspaces/{workspaceId}/users endpoint. For workspace-wide reports, you only need the workspace ID. Keep both values secure — your API key in particular should never be committed to code or shared publicly.

Pro tip: Clockify API keys do not expire, but you can revoke and regenerate them from the Profile Settings page if you suspect a key has been compromised.

Expected result: You have your Clockify API key (24-character hex string) and Workspace ID (24-character hex string), both ready to add as Vercel environment variables.

2

Add Clockify Credentials to Vercel

Add your Clockify credentials to Vercel's environment variables so your Next.js API route can authenticate with the Clockify API securely. Open your Vercel Dashboard, navigate to your project, click the 'Settings' tab, and select 'Environment Variables' from the left sidebar. Add the following two variables: CLOCKIFY_API_KEY: Set this to your Clockify API key. This is a secret — add it for Production, Preview, and Development environments. Do not add a NEXT_PUBLIC_ prefix, which would expose your key in the browser JavaScript bundle and allow anyone who views your site's source to access your workspace data. CLOCKIFY_WORKSPACE_ID: Set this to your 24-character Workspace ID. This identifies which Clockify workspace to query. While not strictly a secret (it appears in API URLs), keeping it in an environment variable makes it easy to switch workspaces without changing code. Save both variables. Trigger a redeployment of your project by pushing a commit to GitHub or clicking 'Redeploy' in Vercel. The new environment variables will be available in the next deployment. For local development, create a .env.local file in your project root with the same variable names and values. This file is already excluded from Git by the V0-generated .gitignore, so your credentials stay out of your repository.

.env.local
1# .env.local local development only, excluded from Git
2CLOCKIFY_API_KEY=your_clockify_api_key_here
3CLOCKIFY_WORKSPACE_ID=your_workspace_id_here

Pro tip: Clockify uses a custom X-Api-Key header for authentication rather than the standard Authorization: Bearer header used by most APIs. Your API route must set 'X-Api-Key' specifically.

Expected result: Vercel Dashboard shows CLOCKIFY_API_KEY and CLOCKIFY_WORKSPACE_ID saved as environment variables across Production, Preview, and Development environments.

3

Create the Clockify API Routes

Create Next.js API routes that fetch time data from Clockify. Clockify has two main API surfaces: the basic REST API (individual endpoints for time entries, users, projects) and the Reports API (pre-aggregated summaries). For dashboards, the Reports API is usually more efficient because it aggregates data server-side. The Clockify Reports API base URL is https://reports.api.clockify.me/v1 (different from the main API at https://api.clockify.me/api/v1). Both use the same X-Api-Key header for authentication. The summary report endpoint (POST /workspaces/{workspaceId}/reports/summary) accepts a JSON body with date range (dateRangeStart and dateRangeEnd in ISO 8601 format), groupings (USER, PROJECT, CLIENT, or DATE), and optional filters. It returns pre-aggregated totals — much more efficient than fetching thousands of individual time entries and summing them in your app. For the date range, Clockify uses ISO 8601 datetime strings with timezone information. The start of a week in UTC is straightforward to compute in JavaScript. Pass the user's desired date range from the frontend as query parameters (start and end) and convert them to Clockify's expected format in the API route. The basic time entries endpoint at GET /workspaces/{workspaceId}/user/{userId}/time-entries returns individual entries with full detail including description, start, end, project, and tags. This is useful for detailed weekly views. It supports pagination via page and page-size parameters (max 50 entries per page by default).

V0 Prompt

Create a Next.js API route at app/api/clockify/summary/route.ts that calls the Clockify Reports API to fetch a summary report. Accept query parameters: start (ISO date string), end (ISO date string), groupBy (default 'PROJECT'). Use CLOCKIFY_API_KEY (X-Api-Key header) and CLOCKIFY_WORKSPACE_ID from environment variables. Post to https://reports.api.clockify.me/v1/workspaces/{workspaceId}/reports/summary. Return the summary data with project names and total durations in seconds. Handle errors.

Paste this in V0 chat

app/api/clockify/summary/route.ts
1import { NextRequest, NextResponse } from 'next/server';
2
3interface ClockifySummaryGroup {
4 _id: string;
5 duration: number;
6 amounts: { amount: number; currency: string }[];
7 name?: string;
8}
9
10interface ClockifySummaryResponse {
11 groupOne: ClockifySummaryGroup[];
12 totals: { totalTime: number; totalAmount: number }[];
13}
14
15export async function GET(request: NextRequest) {
16 const apiKey = process.env.CLOCKIFY_API_KEY;
17 const workspaceId = process.env.CLOCKIFY_WORKSPACE_ID;
18
19 if (!apiKey || !workspaceId) {
20 return NextResponse.json(
21 { error: 'Clockify configuration missing' },
22 { status: 500 }
23 );
24 }
25
26 const { searchParams } = new URL(request.url);
27
28 // Default to current week
29 const now = new Date();
30 const weekStart = new Date(now);
31 weekStart.setDate(now.getDate() - now.getDay());
32 weekStart.setHours(0, 0, 0, 0);
33
34 const weekEnd = new Date(weekStart);
35 weekEnd.setDate(weekStart.getDate() + 6);
36 weekEnd.setHours(23, 59, 59, 999);
37
38 const start = searchParams.get('start') || weekStart.toISOString();
39 const end = searchParams.get('end') || weekEnd.toISOString();
40 const groupBy = searchParams.get('groupBy') || 'PROJECT';
41
42 const reportPayload = {
43 dateRangeStart: start,
44 dateRangeEnd: end,
45 summaryFilter: {
46 groups: [groupBy],
47 },
48 exportType: 'JSON',
49 };
50
51 try {
52 const response = await fetch(
53 `https://reports.api.clockify.me/v1/workspaces/${workspaceId}/reports/summary`,
54 {
55 method: 'POST',
56 headers: {
57 'X-Api-Key': apiKey,
58 'Content-Type': 'application/json',
59 },
60 body: JSON.stringify(reportPayload),
61 next: { revalidate: 300 }, // Cache for 5 minutes
62 }
63 );
64
65 if (!response.ok) {
66 const error = await response.text();
67 console.error('Clockify Reports API error:', error);
68 return NextResponse.json(
69 { error: `Clockify returned ${response.status}` },
70 { status: response.status }
71 );
72 }
73
74 const data: ClockifySummaryResponse = await response.json();
75
76 const groups = data.groupOne.map((group) => ({
77 name: group.name || group._id,
78 totalSeconds: group.duration,
79 totalHours: Math.round((group.duration / 3600) * 100) / 100,
80 billableAmount:
81 group.amounts?.[0]?.amount ?? 0,
82 currency: group.amounts?.[0]?.currency ?? 'USD',
83 }));
84
85 const totals = data.totals?.[0] ?? { totalTime: 0, totalAmount: 0 };
86
87 return NextResponse.json({
88 groups,
89 totalSeconds: totals.totalTime,
90 totalHours: Math.round((totals.totalTime / 3600) * 100) / 100,
91 dateRange: { start, end },
92 });
93 } catch (error) {
94 console.error('Clockify summary fetch failed:', error);
95 return NextResponse.json(
96 { error: 'Failed to fetch Clockify summary' },
97 { status: 500 }
98 );
99 }
100}

Pro tip: The Clockify Reports API base URL (reports.api.clockify.me) is different from the main API (api.clockify.me). Using the wrong base URL will result in 404 errors even though your credentials are correct.

Expected result: Calling /api/clockify/summary returns a JSON object with groups (project/user summaries) and totals for the current week. Each group has totalHours and billableAmount.

4

Generate Dashboard Components with V0

With the Clockify API route returning summary data, prompt V0 to generate the visualization components. Time tracking dashboards typically need clear number formatting (converting seconds to hours and minutes), date range controls for navigating between reporting periods, and visual emphasis on the most important metrics. Before crafting your V0 prompt, test your /api/clockify/summary endpoint and note the exact structure of the response data. This lets you reference real field names in your prompt, which produces more accurate components. For a project summary table, describe the columns you want (Project Name, Total Hours, Billable Hours, Billable Amount), any formatting rules (hours displayed as h:mm, amounts formatted as currency), and how you want totals shown. For a chart, describe the chart type (bar chart for comparison, pie chart for proportion) and what each segment or bar represents. Ask V0 to add a date range picker so users can switch between 'This Week', 'Last Week', 'This Month', and 'Custom Range'. When the date range changes, the component should refetch /api/clockify/summary with the new start and end parameters. Include a loading indicator that appears during the refetch. For teams with multiple members, consider asking V0 to add a user filter dropdown that fetches team members from /api/clockify/users and allows filtering the report to a specific person. The Clockify API supports filtering reports by userId in the report payload.

V0 Prompt

Create a time tracking summary dashboard that fetches data from /api/clockify/summary on load. The response has groups (array with name, totalHours, billableAmount, currency) and totalHours. Display a summary card at the top showing Total Hours this week as a large number. Below, show a table with columns: Project, Hours Tracked, Billable Amount. Add a row at the bottom with totals. Add three filter buttons above the table: 'This Week', 'This Month', 'Last Month' — clicking each refetches with the corresponding date range. Show a loading spinner on the table while fetching. Format currency as '$X,XXX.XX'.

Paste this in V0 chat

Pro tip: To convert seconds to a readable h:mm format, use: const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); return `${hours}h ${minutes}m`.

Expected result: V0 generates a time tracking summary dashboard with a weekly hours card, project breakdown table, and date range filter buttons. The data updates when filter buttons are clicked.

5

Deploy to Vercel and Test

After generating your components, deploy your V0 app to Vercel and verify the Clockify integration works end-to-end in the production environment. In V0, click the 'Deploy' or 'Publish' button to create a live Vercel deployment. V0 will push your code to GitHub and trigger a Vercel build. The build takes approximately 30-60 seconds. Once the deployment URL is live, open it in your browser and navigate to your Clockify dashboard page. If the dashboard loads with real data from Clockify, the integration is working. If you see an error message, open the Vercel Dashboard, go to your project's Functions tab, and check the function logs for your /api/clockify/summary route. The logs will show any errors from the Clockify API call including authentication failures, wrong workspace IDs, or malformed request payloads. A common issue on first deployment is that environment variables are not yet set in Vercel, causing the API route to return a 500 'Clockify configuration missing' error. Verify your environment variables are saved correctly by going to Vercel Dashboard → Settings → Environment Variables. After adding or correcting variables, you must redeploy for them to take effect. Test the date range filters by clicking 'This Week', 'This Month', and 'Last Month'. Verify that different date ranges return different hour totals. Also test with an empty date range (a period with no tracked time) to confirm your empty state displays correctly. For teams building more complex reporting with custom date ranges, multi-user breakdowns, and integration with billing systems, RapidDev can help extend this Clockify integration into a full-featured client reporting platform.

V0 Prompt

Add error boundary handling to the Clockify dashboard component. If the /api/clockify/summary fetch fails, show a card with an orange warning icon, the message 'Unable to load time data', and a 'Retry' button that reruns the fetch. Also add an empty state: if groups array is empty, show a centered illustration placeholder and the message 'No time tracked for this period'.

Paste this in V0 chat

Pro tip: Check your Clockify workspace timezone settings — Clockify's weekly reports align to your workspace's configured timezone, which may differ from UTC. Set your report date ranges based on your workspace timezone for accurate weekly boundaries.

Expected result: The live Vercel deployment shows real Clockify data on the dashboard. Date range filters work correctly. Error and empty states display appropriately for edge cases.

Common use cases

Client-Facing Project Hours Report

A freelancer wants to show clients a breakdown of hours worked on their project without granting them Clockify access. V0 generates a branded report page that fetches project-specific time summary data from the Clockify API and displays weekly hour totals, task breakdowns, and billable amount calculations.

V0 Prompt

Build a project hours report page that fetches data from /api/clockify/summary. The response has projects array with name, duration.totalTime (seconds), and billableAmount. Display each project as a row in a summary table with columns: Project Name, Total Hours (converted from seconds to h:mm format), Billable Hours, and Amount (formatted as USD). Add a total row at the bottom. Include a date range selector (This Week, This Month, Last Month) that refetches data with updated parameters.

Copy this prompt to try it in V0

Team Productivity Dashboard

A startup wants an internal dashboard showing each team member's tracked hours for the current week, broken down by project. V0 generates a team utilization view with rows for each team member, columns for each active project, and color-coded cells showing hours logged. Over-budget projects are highlighted in red.

V0 Prompt

Create a team productivity dashboard that loads data from /api/clockify/team-summary. Data has users array, each with name and projects array (projectName, hours). Display as a table with users as rows and projects as columns. Cell values are hours tracked. Cells with 0 hours are grey, cells with hours are blue with intensity proportional to hours. Add a totals row and column. Show 'Loading...' while fetching.

Copy this prompt to try it in V0

Automated Weekly Time Report Email Preview

A consultant generates weekly time reports to send to clients every Friday. V0 generates a report preview page that pulls the current week's entries from Clockify, formats them as a readable table, and provides a 'Copy to email' button. The consultant can verify the data before sending.

V0 Prompt

Build a weekly time report preview with a header showing the week date range (e.g., 'Week of March 24, 2026'). Fetch report data from /api/clockify/weekly. The data has entries array with date (ISO string), project, description, and duration (seconds). Group entries by date, formatted as 'Monday, March 24'. Show each entry with time (e.g., '2h 30m'), project name as a colored tag, and description. Show total hours at the bottom. Add a 'Print / Save as PDF' button.

Copy this prompt to try it in V0

Troubleshooting

API route returns 401 with X-Api-Key header set

Cause: Clockify requires the header name to be exactly X-Api-Key (capital X and capital A). A common mistake is using Authorization: Bearer or X-API-KEY (all caps) which both fail with 401.

Solution: Verify the header name is exactly 'X-Api-Key' in your API route. Also confirm that the CLOCKIFY_API_KEY environment variable is set in Vercel and that you have redeployed after saving it.

typescript
1// Correct Clockify authentication header
2headers: {
3 'X-Api-Key': process.env.CLOCKIFY_API_KEY!,
4 'Content-Type': 'application/json',
5}

Reports API returns 404 or empty results

Cause: The Clockify Reports API uses a different base URL (reports.api.clockify.me) compared to the main API (api.clockify.me). Using the wrong base URL or hitting the standard API's reports endpoint returns 404.

Solution: Use https://reports.api.clockify.me/v1/workspaces/{workspaceId}/reports/summary for the Summary Report. Note that this endpoint is a POST request, not GET. Also verify your workspace ID is correct — it should be a 24-character hexadecimal string from your workspace settings URL.

typescript
1// Correct Reports API URL (POST, not GET)
2const reportsUrl = `https://reports.api.clockify.me/v1/workspaces/${workspaceId}/reports/summary`;
3const response = await fetch(reportsUrl, { method: 'POST', ... });

Summary report returns data but hours seem incorrect

Cause: Clockify returns duration in seconds as an integer, but many developers expect it in hours or minutes. Also, the date range might be using local timezone dates while Clockify expects UTC, shifting the range boundaries.

Solution: Divide duration by 3600 to convert seconds to hours. For date ranges, always send ISO 8601 strings in UTC format (ending in 'Z' or with explicit timezone offset) to ensure Clockify uses the correct time boundaries.

typescript
1// Convert seconds to hours correctly
2const totalHours = data.groupOne.reduce((sum, g) => sum + g.duration, 0) / 3600;
3
4// Use UTC date boundaries
5const startUTC = new Date(startDateString).toISOString(); // Ensures UTC format

Best practices

  • Never expose CLOCKIFY_API_KEY to the browser — it grants read access to all workspace time data including all team members' entries.
  • Use Clockify's Reports API for aggregated summaries rather than fetching all individual time entries and summing them — it is faster and reduces API call volume.
  • Cache summary report responses for at least 5 minutes (next: { revalidate: 300 }) since time tracking data does not need to be real-time in most reporting contexts.
  • Pass date range parameters from the frontend as query parameters rather than hardcoding the current week in your API route — this makes the route reusable for different reporting periods.
  • Validate that the groupBy parameter only accepts known values (PROJECT, USER, CLIENT, DATE) to prevent unexpected behavior from user-supplied input.
  • Always handle the empty state where groups is an empty array — this happens for new workspaces or date ranges with no tracked time and causes errors if your component tries to map over undefined data.
  • Test your report with different date ranges including the current day, current week, and a past month to verify that Clockify's timezone handling matches your expected output.

Alternatives

Frequently asked questions

Is Clockify's API completely free to use?

Yes, Clockify's REST API is available on all plans including the free tier. Rate limits are generous for dashboard use cases. The Reports API (reports.api.clockify.me) is also available on the free plan. Clockify paid plans add features like PDF exports, invoicing, and lock time entries — not additional API access.

Can I track time via the API from my V0 app?

Yes. The Clockify API supports creating time entries via POST /workspaces/{workspaceId}/user/{userId}/time-entries. You need the user ID (obtainable from GET /api/v1/user with your API key) and a project ID. The entry requires start (ISO datetime), end (ISO datetime), and projectId. This lets you build a custom timer interface in V0 that logs time directly to Clockify.

How do I fetch time entries for a specific project?

For individual entries, use GET /api/v1/workspaces/{workspaceId}/user/{userId}/time-entries with a project filter query parameter. To get project-specific summaries without needing a specific user ID, use the Reports API summary endpoint with a filter for the project ID in the summaryFilter.projects array in your POST body.

What is the difference between duration and billable duration in Clockify?

In Clockify, total duration includes all tracked time (billable and non-billable). Billable duration only includes time entries marked as billable. Whether a time entry is billable depends on the project settings and per-entry overrides. The Reports API returns both billableDuration and duration fields so you can display both in your dashboard.

Can I display Clockify data for only certain team members?

Yes. First fetch your workspace users from GET /api/v1/workspaces/{workspaceId}/users to get user IDs and names. Then filter your reports API call by passing the desired user IDs in the summaryFilter.users array. You can also add a user ID query parameter to your API route and build a user selector in your V0 component.

Does Clockify support webhooks for real-time updates?

Yes, Clockify supports webhooks on paid plans (Standard and above). Webhooks fire on events like timer start, timer stop, and time entry creation. For free plan users, polling your API route every 30-60 seconds using setInterval in a React useEffect hook is the practical alternative for near-real-time dashboard updates.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.