Skip to main content
/api/v1 on your Command Center host is the stable, documented HTTP API: what you script against to drive 2501 from a pipeline, a CMDB sync, or a shell script. It is a real contract, not a private back end that happens to be reachable - Command Center’s own hosts and agents screens are built on these same endpoints.
A call that returns 200 is how you confirm a key works. What the key can reach is fixed at creation - see Authentication.

What is in the API

Every endpoint - with its request and response schema and a live request builder - is in the API Reference in the sidebar.
Other things Command Center manages - credentials, specialties, operational rules, tickets, jobs, knowledge - are still served from unversioned routes that exist for the UI and are not part of the v1 contract yet. They can change in any release. Resources move under /api/v1 release by release, and only what is documented here is stable.

Authentication

Two ways in, and every /api/v1 endpoint accepts either:
  • An API key as a bearer token. This is the one for scripts and integrations.
  • A Command Center session cookie. This is what the web UI uses.
Generate a key in SettingsAPI Keys, or read API Keys for the full walkthrough of scopes, expiry, and revocation. The raw key is shown once, at creation.
A few things worth knowing before you script against it:
  • A key is an administrator inside its own scope. Full read and write on its organization, or on every organization in the tenant for a tenant-scoped key. That reach is frozen at creation: it does not follow the person who created it.
  • A key never reaches anything outside /api/v1. The bearer header is ignored elsewhere, and the CC-only /api/internal routes reject it outright. Notably, a key cannot create, list, or revoke keys - that stays session-only, so a leaked key cannot mint a successor.
  • A bad key is a hard failure, never a downgrade. An invalid, revoked, or expired key gets 401 UNAUTHORIZED; it never falls back to an anonymous request.
Treat a key as a password. It is a full administrator within its scope, and it does not expire unless you asked it to.

Organizations

Hosts and agents belong to exactly one organization, so anything addressing a collection has to name one:
  • reading a collection (GET /hosts, /hosts/search, /hosts/export) carries org_id in the query string,
  • creating (POST /hosts) carries org_id in the body, or in the query string for a CSV batch,
  • anything addressed by id - a read, an update, a delete, an action, a sub-resource - carries none. The id already fixes the organization.
Omitting it where it is required is a 400. Naming one you cannot reach fails in one of two ways, and the difference is deliberate: an org-scoped caller pointing anywhere outside its own organization gets 403 ORG_ACCESS_DENIED, while a tenant-scoped caller naming an organization that is not in its tenant gets 404 NOT_FOUND - another tenant’s organizations are invisible, not merely forbidden.

Reading lists

Every list endpoint answers with the same envelope:
Pages are cursors, not page numbers. Ask for limit rows, then pass the id of the last row you got as starting_after to get the next page. has_more tells you when to stop.
A cursor names a row rather than a position, so a walk is safe while other people are writing: nothing gets skipped or served twice because rows were inserted above you. There is no page parameter anywhere in v1. A cursor id that does not resolve - a deleted row, a row in another organization - is a 400 INVALID_CURSOR rather than a silent jump back to page one.

Writing

POST creates and POST updates. POST /api/v1/hosts creates a host; POST /api/v1/hosts/{id} updates that one. There is no PUT in v1. An update is a partial update, and the rules are the same everywhere:
Verbs that are not create-read-update-delete are POST actions on an item: POST /api/v1/agents/{id}/archive, POST /api/v1/agents/{id}/test-connection. Success is always 200, creates included. There is no 201 and no 204.

Errors

Every error, on every endpoint, has the same flat body:
The codes you will actually meet: code is drawn from a closed set, so it is safe to branch on. The table above is the part of that set a normal caller meets; a few others (TIMEOUT, PAYLOAD_TOO_LARGE, RATE_LIMITED) exist for the same reasons they do in any HTTP API. Treat an unrecognised code by its status class.

Rate limiting

v1 sets no rate limit of its own, but Command Center applies a per-deployment one in front of every route, and a request over it comes back 429 RATE_LIMITED. The default allows a few hundred requests a minute per client, which no ordinary integration approaches - it is there to stop a runaway loop, not to meter you. Because an operator can change it, treat the exact number as a property of the deployment you are calling, not of the API: back off on a 429 rather than pacing yourself to a constant. Two things do have fixed limits, and they are the ones a bulk caller hits first: a list page is capped at 100 rows (limit), and import and export are capped at 10000 rows. Bulk import is the one deliberate exception: POST /{resource}/batch returns 200 with a verdict per row even when every row failed, because the per-row results are the answer. A 4xx there means the request itself was wrong.

Versioning

v1 is a promise about shapes, not a frozen file. Fields and optional parameters get added; nothing documented here is renamed, removed, or given a new meaning without a new version. So:
  • read fields by name and ignore the ones you do not know,
  • do not depend on field order or on the absence of a field,
  • do not depend on undocumented fields. A response may carry extras the UI needs; those are not part of the contract,
  • treat a documented enum as open unless it is stated closed. Host tags and target_type are closed sets; a task’s status is a state machine that gains steps.
There is no deprecation channel today: the versioned path is the whole signal, and a v2 would be a new path served beside v1. Watch the release notes for the release you upgrade to.

Next

API Keys

Generating, scoping, and revoking keys.

Import and Export

Bulk CSV and JSON, in and out.