A developer's guide to the monday.com GraphQL API - the three required headers, the complexity budget that stops integrations before the daily call limit does, column_values as JSON strings, and how to size a sync that will not die at scale.
Key takeaways
- The daily call limit is rarely what stops you. The complexity budget - points per minute, in a sliding 60-second window - is the real constraint, and one badly nested query can exhaust it in a single request.
- Add the complexity field to your queries. It reports the cost of the query, the budget remaining before and after, and when the window resets - turning capacity planning from guesswork into measurement.
- The API-Version header is mandatory and pins behaviour to a dated version. Omitting it or letting it drift is how an integration that worked for months changes behaviour without a deploy.
- Column values come back as JSON encoded inside a string, and writing them requires the same double encoding. This single detail causes most first-day failures against the monday API.
monday.com has exactly one API, and it is GraphQL. There is no REST, no per-resource endpoints - everything is a single POST to the same URL, and the difference between requests lives in the query itself. That is liberating, but it also shifts all responsibility for efficiency onto you, and that is where most integrations fail.
The basics
The single endpoint is https://api.monday.com/v2, and every request is a POST with three mandatory headers:
Authorization- your API tokenContent-Type: application/jsonAPI-Version- a dated version, for example2023-07
The version header is not optional and not a formality. It pins API behaviour to a specific version. An integration that does not send an explicit version, or sends a deprecated one, can change behaviour without anyone touching the code. Version upgrades should be deliberate, tested in a non-production account, and never a default.
What actually limits you: the complexity budget
This is the most important point in the article. There are two completely different limits, and most people watch the wrong one.
Daily call limit
| Plan | Calls per day |
|---|---|
| Free / Basic / Standard | 1,000 |
| Pro | 10,000 |
| Enterprise | 25,000 |
Complexity budget - the real constraint
Every query is scored for complexity, and the budget is measured in points per minute: around one million for free and trial accounts, and between five and ten million depending on token type. The window slides and resets 60 seconds after the first call. Exceeding it returns a ComplexityException.
The practical difference: you can be blocked after a single call. A query asking for every board, every item in each board, and every column value and update on each item is a multiplication, and that multiplication can consume millions of points at once. The 1,000-calls-per-day ceiling stays far away while the integration dies anyway.
Measure instead of guessing
Add the complexity field to a query and the response reports the query's cost, the budget before and after, and when the window resets. This is the core capacity-planning tool. Run the query against a small board, read the number, and multiply by the expected size - that is the difference between an integration that holds and one that dies the day a client adds another 5,000 items.
There is also a concurrency limit, published in the RateLimit-Policy response header. Read it from the response rather than assuming a number.
The day-one trap: column_values
In monday, an item's column values are not ordinary fields. They come back as JSON encoded inside a string, and each column type has its own shape - a status column, a date column and a people column look nothing alike.
Writing makes it more confusing still: the mutation takes the values as a JSON string, which itself contains the structure for that column type. So there is double encoding - you build an object, serialise it to a string, and place that string as a value inside a GraphQL query.
Two practical rules:
- Never build the string by concatenation. Use your language's JSON serialiser. Manual concatenation breaks on quotes, on Hebrew, and on empty values.
- Never guess a column's shape. Read an existing item that is already set correctly, look at exactly what comes back, and write in that same shape. It saves hours against the documentation.
Four more things worth the time
- GraphQL returns 200 on errors. This is standard GraphQL behaviour, not a monday quirk: the status is 200 and the error is in an
errorsarray in the body. Code that checks only the status code will believe everything succeeded. Always inspect the body. - Paginate. Do not rely on fetching everything at once. Working in pages is both the operational requirement and the most direct way to reduce complexity.
- Request only the fields you need. That is the whole point of GraphQL, and in monday it is also what determines how many complexity points you pay. A query asking for three fields is far cheaper than one asking for twenty.
- Webhooks over polling. monday supports webhooks, and for any "when something changes" scenario they beat periodic polling on both complexity and freshness.
When monday is enough and when it is not
The monday API is excellent for reading and writing items, building automations around boards, and connecting monday to other systems. It is a poor fit when you try to turn monday into an operational database - heavy reporting, cross-board queries and complex joins will burn the complexity budget.
On projects where volume grows, the pattern that holds is to sync what you need into your own database and run the reporting there, leaving monday as the team's working interface. That is also the broader question of when an off-the-shelf CRM is enough and when you need a custom one.
Frequently asked questions
Does monday.com have a REST API?
No. monday.com exposes a single GraphQL API at https://api.monday.com/v2. Every request is a POST to that one URL with three headers - Authorization, Content-Type: application/json, and a dated API-Version header. All the variation between requests lives in the GraphQL query itself.
What is the monday.com API complexity limit?
Every query is scored for complexity against a budget measured in points per minute - roughly one million on free and trial accounts, and five to ten million depending on token type. The window slides and resets 60 seconds after the first call, and exceeding it returns a ComplexityException. This limit, not the daily call count, is what usually stops an integration.
How can I check a query's complexity before it fails?
Add the complexity field to the query. The response then includes the cost of that query, the budget remaining before and after it, and when the limit resets. Running it against a small board and multiplying by the expected data volume is the reliable way to size a sync before it hits production.
Why do monday.com column values come back as a string?
Because column values are JSON encoded inside a string, with a different internal shape for each column type. Writing them requires the same double encoding - build an object, serialise it, and pass that string into the mutation. Always use a JSON serialiser rather than string concatenation, and copy the shape from an existing correctly configured item rather than guessing it.
Why does my monday.com API call return 200 but nothing happened?
GraphQL returns HTTP 200 even for failed operations - the failure appears in an errors array inside the response body. Any client that branches only on the HTTP status code will treat a rejected mutation as a success. Always parse the body and check for errors before considering the call successful.
How many API calls per day does monday.com allow?
1,000 per day on Free, Basic and Standard, 10,000 on Pro and 25,000 on Enterprise. In practice this ceiling is rarely reached, because the per-minute complexity budget is the limit that bites first - a single deeply nested query can exhaust it on its own.
Keep reading
Related service
Custom CRM
A CRM built around your pipeline, connected to the tools you already use.
About the author
Yehonatan Saadia
Freelance automation, web & MVP engineer
I'm Yehonatan Saadia, a senior engineer who builds business automation, custom websites, and MVPs for small and mid-sized companies across the US, Europe, and Israel. These guides come from real client work, not theory.
Work with meHave a project like this?
Tell me what you're trying to automate or build and I'll tell you the fastest reliable way to ship it.
