Limits and errors
What every account gets, how rate limiting works, and what each error means.
Plan limits
Every account is free and gets the same limits:
| Limit | Amount |
|---|---|
| Counters | 5 per account, shared across all the workspaces you own |
| Workspaces | 3 that you own. You can be a member of any number. |
| Counts | 10,000 a day per account, across all your workspaces. Resets at 00:00 UTC. |
| Milestones | 10 per counter |
| Milestone texts | 5 a day per phone number |
| Sign-in codes | 5 an hour per phone number, and 10 tries at entering them |
A count is any change to a counter: up, down, set, reset, like, vote or rate, whether it comes from the API, a widget, a badge or the dashboard. Reading counters, stats and history doesn't count.
The counters in a workspace you've been added to use its owner's allowance, not yours. Deleting a counter frees its slot straight away.
Rate limits
Each token, or each IP address for requests without a token, can make 600 requests a minute to any one URL. Every API response tells you where you stand:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
Over the limit you get 429 with the code rate_limited and a Retry-After header with the number of seconds to wait. There's an example of retrying in the code examples.
Badges and pixels have the same per-visitor limit, but they never show an error. Over the limit, a badge still shows the number and the visit simply isn't counted. Widgets call the API, so they follow the API's limits.
Error format
Every API error has the same shape:
{
"error": {
"code": "unauthorized",
"message": "“down” needs an API token with 'write' permission."
}
}
Use code in your program; it won't change. message is written for people and may be reworded.
Error codes
| Status | Code | What happened |
|---|---|---|
| 400 | invalid_value | A by, value or choice is missing, isn't a whole number, or is out of range. |
| 400 | out_of_bounds | set was given a value outside the counter's minimum and maximum. |
| 400 | unsupported_action | The action doesn't fit the counter type, such as vote on a normal counter or up on a poll. |
| 400 | invalid_window | window isn't like 15m, 24h or 7d, or is longer than 90 days. |
| 400 | invalid_range | range isn't 24h, 7d, 30d or 90d. |
| 400 | invalid_name | A new counter's name isn't 1 to 64 lowercase letters, digits, - or _. |
| 400 | invalid_setting | A counter setting isn't valid, for example a minimum above the maximum. |
| 400 | invalid_body | The request body is JSON but not an object. |
| 401 | unauthorized | This request needs a token and none was sent. |
| 401 | invalid_token | The token is wrong or has been revoked. |
| 403 | forbidden | The token doesn't have the permission this request needs. |
| 403 | wrong_workspace | The token belongs to a different workspace. |
| 403 | counter_limit | You've used all 5 counters. Delete one to create another. |
| 404 | not_found | The workspace, counter or action doesn't exist. Names are case-sensitive and always lowercase. |
| 405 | method_not_allowed | Stats, history and events only accept GET. |
| 409 | exists | A counter with that name already exists in the workspace. |
| 429 | rate_limited | Too many requests. Wait for Retry-After seconds. |
| 429 | quota_exceeded | The account has used its 10,000 counts for today. Counting resumes at 00:00 UTC; reading still works. |
Common questions
Why did my request return "counted": false?
The request worked, but the number didn't change. Either the visitor was already counted (unique counting, likes, votes and ratings), or the counter is at its maximum (counting up) or minimum (counting down).
Can people inflate my public counter?
Anyone can count up a public counter by one at a time; that's what makes widgets work without a token. Rate limits slow down anyone trying to run it up, and unique counting means repeat visits from the same person don't count. Nobody can subtract, set, reset or use a custom step without a token. If a number must only change from your own code, make the counter private.
Can I rename a counter or workspace address?
No, because the name is part of every URL that uses it. Create a new counter, set it to the old value, and delete the old one. A workspace's display name can be changed in its settings; its address can't.
Why does my count go up twice in development?
React's Strict Mode runs effects twice in development, and some dev servers reload the page. Production builds count once. See counting on a web page.
Can I use it from a static site?
Yes. Use a public counter with the widget, a badge, or a fetch call. None of them need a server or a token.
Does CountJar store visitors' IP addresses?
Yes. Each event keeps the visitor's IP address, together with the location looked up from it and their device, browser and language (see visitor details). Only the workspace owner can see IP addresses. Raw events, IP addresses included, are deleted after 90 days. Repeat visitors are recognised by a keyed fingerprint of the IP address and browser.
How do I get more than 5 counters?
Every account gets 5. Free one up by deleting a counter you no longer need. A poll or rating counter can often replace several normal ones, and custom properties let one counter track many things, such as every issue of a newsletter.