Projects & scoping
A project is one chatbot. A workspace can own several, and most endpoints let you either look at one of them or at all of them together.
Omitting projectId
Leave projectId off and the request covers every project the key's workspace owns. That is the right default for a billing report or a workspace-wide dashboard.
curl -H "X-API-Key: $NUBO_KEY" \
"https://api.nubo-chat.com/v1/usage?days=30"Narrowing to one project
Add projectId to restrict the request to a single chatbot. Get the ids from GET /v1/projects.
curl -H "X-API-Key: $NUBO_KEY" \
"https://api.nubo-chat.com/v1/usage?days=30&projectId=8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b"It is a query parameter rather than a header on purpose: a header that quietly defaulted would let a misconfigured integration read the wrong chatbot for weeks without anyone noticing. In a URL, the scope is visible in every log line and every bug report.
Where it does not apply
Two endpoints do not accept projectId, because the thing they describe belongs to the workspace rather than to any one chatbot:
GET /v1/balance # one shared pool of replies
GET /v1/plan # one plan for the workspacePassing projectId to these is ignored rather than rejected — the answer is the workspace figure either way.
Ids that are not yours
A project id belonging to another workspace returns 404 with code project_not_found — the same response as an id that never existed.
A gotcha worth knowing
Your workspace's original project has an id that happens to equal the workspace's own id. That is a historical artefact of how Nubo evolved, and nothing should be read into it.
Do not treat them as interchangeable
Projects created later get fresh, unrelated ids. Code that assumes a project id is the workspace id will work against your first chatbot and break the day you add a second. Always take project ids from GET /v1/projects.