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

Rate limits (429)

Each API key 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 API key. 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 key’s 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 safety-suite generation and compliance workflows. 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. 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.

Evaluation allowance (403)

Workspaces on an evaluation get a fixed number of security assessments. Safety-suite generations and compliance workflows are not part of an evaluation and are refused outright, so there are two refusals here rather than one. 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-suite generation or a compliance workflow on an evaluation returns 403 with code trial_lens_not_included instead. That is not a spent allowance, so it carries no counts:
Neither of these resets — do not retry them. Unlike the two 429s above, 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 failed harness or an Enoki-side fault does not cost you an assessment. On MCP the same refusal arrives as a trigger_assessment tool error carrying that message. If you are on a paid plan you will never see this code.

”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 is for 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.
  • Client support — for a client without native remote-MCP support, use the mcp-remote bridge (see Connect your agent).
  • at_capacity (503) — the server is momentarily at its concurrent-session cap; retry shortly.