← Back to changelog

Public API: Hardening Pass

If you drive Nairi from code, we've spent the past month tightening up the public API — validation that used to be too loose, error responses that used to be too vague, and a few endpoints that quietly differed from what the docs said.

Most of this is invisible if your integration is healthy. Three changes are worth a sanity check.

Breaking changes

These used to be silently coerced or accepted. They now return 400.

  • Cron schedules under 5 minutes are rejected. * * * * * (every minute) and */2 * * * * now return 400. The minimum granularity is 5 minutes. Pre-existing schedules created before this rolled out keep running — only new ones are validated.
  • instances_count <= 0 is rejected when creating an agent. Previously coerced to 1, now returns 400.
  • limit <= 0 is rejected on conversation list endpoints. Previously coerced to the default, now returns 400 — so a typo no longer silently returns an unbounded page.

Quality of life

  • Slug or ULID, your choice. Every endpoint that takes an {agent_id} now accepts either the ULID (cci_...) or the human-readable slug. Slugs may contain / (for example presmihaylov/claudecontrol) — accepted raw or URL-encoded.
  • Clear a custom system prompt without recreating the agent. PATCH /agents/{id} with system_prompt: null now reverts to the platform default. Sending the field as "" is still distinct (sets it to empty), and omitting it leaves it untouched.
  • More sort options on conversation lists. sort=created_at_asc and sort=updated_at_desc were documented but not accepted. Now they are.
  • Empty PATCH bodies are true no-ops. Sending PATCH /vaults/{id} or PATCH /vault-secrets/{id} with {} no longer bumps updated_at or writes an audit-log entry.
  • NAIRI_ and CCAGENT_ are reserved env-var prefixes. EKSEC_ is no longer reserved (carry-over from the old branding).
  • New integrations and models endpoints. List your LLM integrations, GitHub installs and connected repos, and the LLM model catalog (slugs + pricing). These were previously the missing piece for agent-resources assignment.

Better errors

  • Typed 4xx instead of generic 500. Delete-while-assigned, duplicate-key collisions, and "can't continue a non-API job" now return proper 400 / 404 with a clear message body — not the generic 500 they used to.
  • 404 actually means 404. Missing resources on assign / unassign paths now return 404, not 400 with "not found" in the body.
  • Stricter 404 / 405 bodies. Unknown routes and disallowed methods now return JSON-shaped error bodies instead of plain text.
  • conversations/continue returns 201 Created. Docs previously said 200.

See the API reference for the full surface.