2026-10-12
Export Toggl to JSON on the Free plan: 30 API requests an hour, an HTTP 402 when you run out, and how to pace a full-history pull
Toggl Track has no button that exports your time entries as JSON. Time entries come out as JSON through the API. On the Free plan the API has a budget: 30 requests an hour. When it is spent, Toggl answers with an HTTP 402, not the 429 most scripts are written to expect. That budget is enough to get your history out, but only if you count the requests first. This post covers what Toggl's pages say, the arithmetic that follows, how to pace the pull, and how the same job looks on Harvest.
What the Free plan gives you
Toggl's support page on exporting data says: "on Toggl Track the Free plan only supports PDF exports (CSV/other formats require a paid plan)." Its page on moving data between workspaces says the same about the report most people would reach for: "If you are not on a paid plan, you will not be able to export the Detailed Report in CSV format." The workaround it gives is "Settings > Data Export tab > Time Entries section and export your time entries 1 year at a time from there."
The exporting page also describes that Data Export page. Workspace admins can use it, and "Workspace data (projects, clients, etc.) is exported as raw JSON". Toggl emails a link that "is valid for 72 hours", and "Only one export can be compiled at a time per Workspace." The page doesn't say what format the Time Entries section produces. Run it once and look before you plan around it.
So your projects and clients can come out as JSON without a single API request. If you want your time entries as JSON too, you are using the API.
The budget: 30 an hour, per user
Toggl's support page on API limits lists three tiers for requests that point at a workspace or an organization:
- "Free: 30 requests per hour, per user, per organization"
- "Starter: 240 requests per hour, per user, per organization"
- "Premium: 600 requests per hour, per user, per organization"
On Free that is one request every two minutes.
The window slides. The page says: "The count begins when the initial request is made and remains valid for 60 minutes." Then: "After 60 minutes, the count resets." The hour starts with your first request, not on the clock hour.
The count is per user. Toggl's engineering docs say the quota "is applied per user per org". Clockify's Free budget is shared by the whole workspace, as the Clockify version of this post covers. By Toggl's wording, a teammate's script doesn't spend your 30.
There is a second, separate quota for requests about your own user data that don't target a workspace, such as the /me endpoint. The engineering docs put it at a "30 request/hour limit per user, regardless of the subscription plan". Upgrading doesn't raise that one.
The 402, and how to tell it from the other 402
The support page says: "When you reach your limit, the server responds with an HTTP 402 status code, indicating you should pause further requests." The engineering docs say the same, and add two response headers:
- X-Toggl-Quota-Remaining: "how many requests you have left in the current window."
- X-Toggl-Quota-Resets-In: "how many seconds until the current window resets."
A script that only backs off on 429 will treat the 402 as a fatal error and stop partway through your history.
Toggl also uses 402 for something else. The same docs page gives this advice for the code: "workspace should be upgraded to have access to said feature" and "don't repeat the request until that has happened". The Detailed Report endpoint's own 402 reads "Workspace needs to have this feature enabled." One status code, two meanings. So read the headers. If the last response said you had requests left, the 402 is about a feature and waiting won't help. If it said zero, wait.
The 429 exists too, for a different limit. The docs call it a leaky bucket and say "a safe window will be 1 request per second." At 30 requests an hour you won't reach it.
Where the entries come from
There are two endpoints, and only one of them is for history.
The first is GET /me/time_entries, which the docs describe as "Lists latest time entries." The tracking docs say "The limit of returned time entries is 1000" and suggest: "Consider using detailed reports for the whole list". On Toggl's community forum, a user asking for older entries got the error "start_date must not be earlier than 2024-09-08" in December 2024. Toggl's support staff replied that the endpoint is "basically the equivalent of the Timer page" and pointed to the Reports endpoints. It is the endpoint for recent entries.
The second is the Detailed Report in the Reports API: POST /reports/api/v3/workspace/{workspace_id}/search/time_entries. The docs say it "Returns time entries for detailed report according to the given filters." This is the one for a full pull. It targets a workspace, so it draws on the 30.
The docs list CSV, XLSX and PDF versions of the same endpoint. Leave those alone. The plain endpoint is the JSON one.
Page size decides how long it takes
The Reports docs say: "API results for Detailed Reports are paginated, returning 50 entries at a time." The endpoint's reference lists page_size as "optional, default 50" and gives no maximum. To get the next page, the docs say to "use the value returned in the X-Next-Row-Number header as the first_row_number parameter in your subsequent request."
At the default, the arithmetic is short:
- 30 requests an hour at 50 entries each is 1,500 entries an hour.
- 10,000 entries is 200 requests. At one every two minutes that is 6 hours 40 minutes.
- The same 200 requests fit inside one hour on Starter's 240.
The date range adds requests. Toggl's support page says "Reports have a maximum time frame of one year", and the staff reply on the forum says of the Reports endpoints "you set a date range of 365 days there." Every year of history costs at least one request, including a year with nothing in it.
Since the docs give no maximum for page_size, spend one request finding out. Ask for a larger page and count what comes back. If the larger page is honoured, the six hours shrinks in proportion. If it isn't, you have lost two minutes.
Import your Harvest account and read the reconciliation
Free for 2 people and 1 active project; $9 per active member per month after that, no usage fees on anything. The import runs on the free plan.
How to pace the pull
- Get projects and clients from the Data Export page first. That is JSON already and it costs no requests.
- Work one year at a time, oldest first. The docs say start_date and end_date are both inclusive, so run 1 January to 31 December and the years won't overlap.
- Write each page to disk as it arrives, with the year and the next row number. A run that takes hours will be interrupted, and you want to resume, not restart.
- After every response, read X-Toggl-Quota-Remaining. When it reaches zero, sleep for the number of seconds in X-Toggl-Quota-Resets-In, then carry on.
- On a 402, check the last remaining count before you decide to wait.
- Don't run anything else on the same user's token while the pull is going. It all comes out of the same 30.
- Use a workspace admin's token. Toggl's exporting page says "Admins can export all time entries", while regular users can export only their own entries and those of projects they manage.
Check the file before you trust it
A pull that runs for six hours through a quota has many chances to drop a page. Check three things.
- Every entry id appears once. A resumed run can fetch the same page twice.
- A page shorter than the page size is the last page of its year. If one turns up in the middle of a year, something was lost.
- Add up the durations for each year and compare the total with what Toggl's own report shows for the same year. The docs say the dates are evaluated "in each time entry creator's own Toggl profile time zone", so an entry logged near midnight on 31 December is the first place to look when a year is off.
An export you can't reconcile against the source is a file you have to take on trust.
The Harvest comparison
Harvest's API returns JSON as well. Its documentation says "Harvest formats response bodies in JSON". The limits are on a different scale, and they don't depend on your plan in the documentation.
- The limit: "The rate limit for general API requests is 100 requests per 15 seconds." That is 24,000 requests an hour, against Toggl Free's 30.
- The page: "The default and maximum per_page value for API requests is 2000." Toggl's default is 50.
- The same 10,000 entries: 5 requests on Harvest, 200 on Toggl at the default page size.
- The signal: "When the rate limit is exceeded Harvest will send an HTTP 429 status code", with the wait in seconds in the Retry-After header. Toggl sends a 402 and puts the wait in X-Toggl-Quota-Resets-In.
Harvest's Reports API has a slower limit of its own, "100 requests per 15 minutes", which matters when you check totals. On Harvest the request count isn't the hard part. Getting the totals to match is, and Will my Harvest history reconcile to the cent? covers that. If you would rather not use the API at all, the file exports are in how to export everything from Harvest before your renewal.
Neither tool stops you leaving. One of them makes you wait six hours. How long a full export takes, and on which plan, is a question worth asking any vendor before you need the answer. It belongs with the five in the exit test.
Import your Harvest account and read the reconciliation
Free for 2 people and 1 active project; $9 per active member per month after that, no usage fees on anything. The import runs on the free plan.