Skip to main content
Every error carries a category or a machine-readable code you can match on.

Registering a target

create_target runs one live probe. On failure it returns a category and saves nothing, so fix what it names and call it again.

Authentication errors

Signing in an app

When an app signs in, Enoki opens in your browser. If it can’t let the app in, the page says why:

Rate limits (429)

Each API key and each connected app is rate-limited per minute. Every request counts against the Standard tier; the three expensive tools additionally count against the stricter Expensive tier. On breach you get a 429 with code rate_limited. Because expensive tools spend both budgets, a burst of cheap calls can exhaust the Standard tier and 429 the next create_target.

Per-caller limits

Two further limits apply to every request, keyed on the calling IP address rather than on your key or app. They exist to stop path scanning, and normal integration traffic does not come close to either. The client-error bucket is the one to know about, because a full bucket refuses every request from that IP for the rest of the minute — not just the ones that were erroring. Two habits fill it:
  • Retrying a 404. A 404 means the resource is not there; a retry returns the same 404 and spends another entry. Do not retry them.
  • Polling for a resource before it exists. Poll the parent listing, or the run’s status, rather than the not-yet-created child.
Repeated 403 scope_denied counts too, so fix the scopes rather than looping on the failure. 429s from these two limits carry a Retry-After header and a plain detail message rather than a code field, so branch on the status and the header, not on a code, when handling them.

Daily assessment budget

Separately from the per-minute tiers above, each workspace has a budget of 20 assessment runs per rolling 24 hours. This one is not per API key and not per minute: it is shared across the dashboard, the external API, and MCP, because what it protects is the cost of running an assessment rather than request volume. Every run the workspace starts counts, whatever its outcome and whoever started it — including runs you did not trigger by hand, such as scheduled runs, safety assessments, and reporting top-ups started from the dashboard. So the budget can be spent before you have made 20 explicit trigger calls. The error message always reports the actual count, so read that number rather than assuming it matches your own triggers. The same budget refuses those creators too. A safety assessment or a reporting top-up started when the workspace has no slot left gets the same 429 with trigger_quota_exceeded and the same Retry-After; in the dashboard, all three lenses show the same “Daily assessment budget reached” notice. A reporting top-up is a run you start in Reporting when a risk needs more testing before its report can be downloaded. It tests those risks and re-tests the fixes you reported. On breach you get a 429 with code trigger_quota_exceeded — so a 429 from a trigger carries one of two codes, and they mean different things: How the reset reaches you depends on the surface. On REST, both codes carry a Retry-After header, and trigger_quota_exceeded additionally carries retryAfterSeconds in the response body. On MCP, neither does — tool errors are plain text with no headers — so trigger_assessment puts the reset time in the message itself. Treat that time as the earliest a slot can open, not a guarantee: runs started while you wait push it later. If you are hitting this from a release hook that triggers an assessment on every deploy, a scheduled re-run is the supported way to get a recurring cadence — talk to us and we will set it up rather than have you spend the budget on hook volume.

Assessment allowance (403)

Every workspace has a per-lens allowance, and a spent one returns 403. Which refusal you get depends on your plan, and the code in the body tells them apart.

Your monthly allowance is spent

A paid workspace gets a fixed number of runs per lens, per calendar month: security assessments, safety assessments and reporting top-ups are counted separately, so spending one does not reduce the others. The month is UTC and the counts reset on the 1st. Only completed runs count, in every lens. A run that ends in error, and one you cancel, costs no allowance and can be retried.
A cancelled run is not a passing run. get_assessment_status still returns a min_severity verdict once a run is terminal, and cancelled is terminal — so a run stopped early reads pass simply because it never got far enough to find anything. If you gate a pipeline on the verdict, compare categories_completed against categories_planned, or treat cancelled as its own outcome. The same applies to GET /api/v1/run/{run_id}.
When a lens’s allowance is spent, the trigger returns 403 with code assessment_allowance_spent, and the body names the count, the ceiling and the reset date:
This one does reset, on the date in resets_at — but it carries no Retry-After, because that can be most of a month away and is not a wait a client should sit through. Schedule around the date, or get in touch and we will raise the ceiling.

You are on an evaluation

Workspaces on an evaluation get a fixed number of security assessments for the life of the evaluation rather than per month. Safety assessments and reporting top-ups are not part of an evaluation and are refused outright, so there are two more refusals here. When the security allowance is spent, the trigger returns 403 with code trial_lens_limit_reached, and the body names the count and the ceiling:
Asking for a safety assessment or a reporting top-up on an evaluation returns 403 with code trial_lens_not_included instead. That is not a spent allowance, so it carries no counts:
A reporting top-up’s lens value is compliance. Neither of the two evaluation refusals resets — do not retry them. Unlike the monthly allowance above and the two 429s, no amount of waiting frees a slot; we lift the ceiling or add the lens, so get in touch. A run that ends in error does release its slot, so a run that fails on our side does not cost you an assessment. All three refusals share one body shape, so branch on code and read the counts where they apply. The examples above show only the fields each refusal fills in; the rest are present and null — resets_at on both evaluation refusals, and used and limit on trial_lens_not_included, which short-circuits before anything is counted. One more refusal applies to an evaluation only. It runs full assessments, so a trigger that passes categories returns 403 with code trial_focus_not_included. Unlike the two above, you clear this one yourself: leave categories out and trigger again. Its body carries the code and the message and nothing else:
On MCP these refusals arrive as a trigger_assessment tool error carrying the message and nothing else — an MCP tool error has no body, so there is no code to branch on there. Use the REST trigger if your client needs to tell them apart.

Category list (403)

Listing the categories (GET /api/v1/category, or the list_categories MCP tool) is part of the platform plan. A trial workspace is refused it:
Like the evaluation refusals above, it does not reset with time. A trial’s runs cover every category, so omit categories when you trigger one.

A run that could not start (502)

If Enoki accepts a trigger but cannot start the run, the trigger returns 502:
The run is recorded as failed and does not count against your assessment allowance, so trigger again. It does count as a start toward the daily assessment budget. Over MCP, trigger_assessment returns a tool error saying the run could not be started.

”Not found” for something you expect to exist

A finding, run, or target in a different workspace returns not-found, not 403, so IDs can’t be probed across workspaces. If you get not-found for an ID you believe is valid, check your key or app is connected to the right workspace.

Can’t connect at all

  • Endpoint: confirm the URL is exactly https://mcp.enokilabs.ai/mcp (streamable HTTP).
  • Auth header: the key goes in the Authorization: Bearer … header, not a query parameter.
  • Signing in: if your client never opens Enoki in your browser, it can’t sign in to Enoki; connect it with an API key.
  • Client support: for a client without native remote-MCP support, use the mcp-remote bridge (see Connect your agent).