Appearance
API
OpsMerge has a JSON HTTP API. Everything the web UI can do, the API can do — they share the same backend. This article covers authentication, scopes, rate limits, our stability policy, and the request/response conventions. For endpoint specifics, use the interactive reference:
- Interactive docs: app.opsmerge.cloud/api/docs
- Raw OpenAPI spec: app.opsmerge.cloud/api/docs/openapi.yaml — feed this into Postman, Insomnia, or your code generator of choice.
The interactive docs are generated from the OpenAPI spec and are the source of truth.
Authentication
Every authenticated endpoint takes an API key as a bearer token:
Authorization: Bearer om_your_api_key_hereAPI keys start with the om_ prefix and are long-lived — they work until they expire or you revoke them.
Creating a key
- Go to Settings → API Keys.
- Give the key a name (you'll see this name in the list later, so make it describe the integration).
- Optionally set an expiry date. No expiry means the key lives until revoked.
- Choose its access: Full access (everything your role allows) or Custom scopes (pick exactly the areas and levels the integration needs).
- Click Create key.
The key is shown once. Copy it immediately; it cannot be retrieved later. If you lose it, revoke it and create a new one.
Treat keys like passwords
A key is plain bearer auth — whoever holds it can do everything its scopes permit. Don't paste keys into chat tools, don't commit them to repositories. Use a secrets manager or your CI's secret store.
Quick way to test a key:
bash
curl -H "Authorization: Bearer om_your_api_key_here" \
https://app.opsmerge.cloud/api/v1/auth/meScopes
Scopes follow a family:level format — the family is a feature area, the level is what the key may do within it:
| Level | Allows |
|---|---|
read | List and fetch |
write | Create, update, delete |
execute | Trigger actions (run a script, reboot an agent) |
Examples: agents:read, scripts:execute, psa_tickets:write. The full family list is shown in the scope picker when you create a key, with families grouped into RMM and PSA.
Two rules to remember:
- Scopes narrow, never widen. A key can never do something its owner's role can't. Role permissions are checked first; the key's scopes are an additional restriction on top.
- Least privilege pays off. Give an integration only the families and levels it actually uses. A reporting script needs
readscopes, not full access.
If the key's owner is deactivated, the key stops working with them.
Rate limits
Each API key gets 300 requests per minute. Exceed it and you get 429 Too Many Requests with a Retry-After header (in seconds) and X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset headers describing the key's bucket. Honour Retry-After and back off.
The limit is per key, not per source IP — sharing one key across many hosts shares its budget. Give separate integrations separate keys: better isolation, better audit trail, and one noisy integration can't starve the others.
Stability tiers
Every operation in the API reference carries a stability tier (the x-stability field in the spec):
| Tier | What it covers | Our promise |
|---|---|---|
stable | The public API proper: clients, sites, agents, contacts, tickets, billing, checks, alerts, scripts, users and roles, time entries, and similar | Breaking changes only with at least 6 months' notice, signalled via Deprecation and Sunset headers and the changelog |
beta | Recently shipped and still moving | May change; changes are announced in the API changelog, but there is no sunset window |
internal | Exists to serve the web UI: settings panels, integration OAuth flows, installer plumbing | Documented for transparency, zero guarantees — may change or vanish in any release |
Build integrations on stable operations. Use beta with eyes open. Treat internal as off-limits for anything you don't want to fix at short notice.
Request and response conventions
Requests and responses are JSON. Successful responses are wrapped in a data envelope:
json
{
"data": { "id": "…", "hostname": "SERVER01" }
}Errors come back as an error object with a human-readable message and a machine-readable code:
json
{
"error": {
"message": "API key rate limit exceeded",
"code": "RATE_LIMITED"
}
}Branch on the code, not the message text — the full set is in the API error codes catalogue.
Status codes mean what you'd expect: 200/201 success, 400 malformed request, 401 missing or invalid key, 403 valid key but insufficient permissions or scopes, 404 not found, 429 rate-limited, 5xx our fault — retry with backoff and tell us if it persists.
Pagination
List endpoints are page-based: ?page= (starting at 1) and ?per_page= (default 50, maximum 100). List responses include the items and a total count:
bash
curl -H "Authorization: Bearer om_your_api_key_here" \
"https://app.opsmerge.cloud/api/v1/agents?page=2&per_page=100"json
{
"data": { "items": [ … ], "total": 173, "page": 2 }
}Keep requesting pages until you've collected total items. Exact response shapes vary slightly per endpoint — the interactive docs show the precise schema for each.
Common issues
401 on every call. Almost always a copy-paste problem with the key — check for stray whitespace, and make sure the header reads Authorization: Bearer om_… with a space between Bearer and the key.
403 on calls that should work. Both the key's scopes and the owner's role permissions must allow the action. Check the key's scopes in Settings → API Keys first, then the role.
429s under load. You're over the 300 requests/minute budget for that key. Honour Retry-After, batch where you can, and split unrelated integrations onto their own keys.
Next
- Interactive API docs — every endpoint, schema, and example
- API changelog — release notes and change announcements
- API error codes — every machine-readable error code, with status and meaning
- Audit log — API actions are audited the same way UI actions are
- Users & roles — the permission model that scopes narrow from