OpsOne · External API
Read OpsOne from another system
A read-only HTTP API over the directory, the asset inventory, spends and vendors. Every request carries a key; every key carries scopes; a scope names the exact modules, actions and fields it may read. Nothing outside a key's scopes is reachable, and nothing writes.
https://beta.opsone.silverpush.live/api/v1/externalGetting a key
Keys are issued by an OpsOne administrator under Admin → API Access. Ask for one and say what you need to read — the administrator builds a scope with exactly those modules and fields, then creates a key against it.
The full secret is shown once, at creation. OpsOne stores only its hash, so a lost key cannot be recovered — it is rotated, which issues a new secret and stops the old one immediately.
Authentication
Send the key as a bearer token. Keys look like opk_<id>_<secret> — the first two segments identify it in logs, the whole string is the credential.
curl -s https://beta.opsone.silverpush.live/api/v1/external/me \
-H "Authorization: Bearer opk_xxxxxxxx_your-secret-here"{
"data": {
"name": "grafana-dashboard",
"prefix": "opk_xxxxxxxx",
"scopes": ["read-employees-basic"],
"rateLimitPerMinute": 60,
"expiresAt": null
}
}/me is the quickest way to prove a key works and to see what it is allowed to do.
Endpoints
| Method & path | What it returns |
|---|---|
| GET /me | The calling key: name, scopes, rate limit, expiry. |
| GET /{module} | A page of records, filtered and projected to the key's scope. |
| GET /{module}/{id} | One record by its stable id. Each module names its own id field — see the module reference below. |
Every response is JSON. A list wraps its rows in data with a pagination block; a single record returns data alone.
{
"data": [
{ "employeeId": "SP0123", "firstName": "Asha", "officialEmail": "asha@silverpush.co" },
{ "employeeId": "SP0124", "firstName": "Rahul", "officialEmail": "rahul@silverpush.co" }
],
"pagination": { "limit": 2, "offset": 0, "total": 214 }
}Filtering & paging
Any filter a module declares can be passed as a query parameter. Unknown parameters are refused rather than ignored, so a typo tells you instead of quietly returning everything.
| Parameter | Default | Notes |
|---|---|---|
| limit | 50 | 1 to 100. |
| offset | 0 | Page by adding limit each time, until offset reaches pagination.total. |
| <filter> | — | Per module; see the reference below. Several combine with AND. |
curl -s "https://beta.opsone.silverpush.live/api/v1/external/employees?status=ACTIVE&limit=100&offset=0" \
-H "Authorization: Bearer $OPSONE_KEY"What a scope controls
A scope is three decisions, made per module, at the time the key is issued.
Actions
Whether the key may list many records, get one, or both.
Fields
The exact columns that come back. A field left out of the scope is absent from the response — not blank, absent.
Forced filters
A restriction applied on top of whatever you ask for. If the scope forces status=ACTIVE, no request can see anybody else.
Forced filters always win over query parameters, so a narrow key stays narrow. If a scope's forced filter is ever unusable the request is refused rather than run without it — a broken restriction must never read as no restriction.
Errors
Failures carry the same shape every time: { "error": { "code": "...", "message": "..." } }. Match on the code; the message is written for a human and may change.
| Status | Code | What it means |
|---|---|---|
| 400 | bad_request | limit or offset is out of range. |
| 400 | bad_filter | A filter is unknown, or its value is not legal. |
| 401 | unauthorized | No Authorization: Bearer header was sent. |
| 401 | invalid_key | The key is malformed, unknown, revoked or wrong. |
| 401 | key_expired | The key passed its expiry date. |
| 403 | api_disabled | An administrator has switched the External API off. |
| 403 | ip_not_allowed | This key is restricted to other IP addresses. |
| 403 | scope_denied | The key's scopes do not cover this module or action. |
| 404 | module_not_found | No such module. |
| 404 | not_found | No record with that id — or the scope hides it. |
| 429 | rate_limited | Too many requests this minute. |
| 500 | scope_filter_invalid | The key's scope forces a filter that cannot be applied. Tell an administrator; the scope needs fixing. |
Rate limits
Each key has a requests-per-minute ceiling — its own, or the platform default when none was set. Every response carries what is left:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57Over the ceiling you get 429 rate_limited. The window is a rolling minute, so waiting a moment is enough; there is no penalty period.
Module reference
Generated from the registry the API itself reads. What is listed here is everything that exists — a key can be granted less, never more.
People — Employees
employeesEmployee directory: identity, org placement and reporting line. No personal contact details — mobile numbers, personal addresses and personal email are not reachable from here.
- Actions
- listget· id field employeeId
- Filters
- statusenumemployeeTypeenumdepartmentstringsubDepartmentstringdesignationstringentitystringworkLocationstringregionstringcountrystringemailstringmanagerEmailstringmanagerEmployeeIdstring
Fields
| Filter | Legal values |
|---|---|
| status | UPCOMING · ACTIVE · EXIT_INITIATED · EXITED |
| employeeType | EMPLOYEE · CONSULTANT · TEMP · SYSTEM |
curl -s "https://beta.opsone.silverpush.live/api/v1/external/employees?limit=5" \
-H "Authorization: Bearer $OPSONE_KEY"Assets — Inventory
assetsHardware inventory (no cost or supplier data)
- Actions
- listget· id field assetTag
- Filters
- statusstringcategorystringlocationstringassetTagstringassigneeEmployeeIdstring
Fields
curl -s "https://beta.opsone.silverpush.live/api/v1/external/assets?limit=5" \
-H "Authorization: Bearer $OPSONE_KEY"Spends — Expenses
expensesExpense records (amounts + workflow status; no payment rails)
- Actions
- listget· id field spendNumber
- Filters
- statusenumcurrencystringteamstringvendorNamestringcategoryNamestring
Fields
| Filter | Legal values |
|---|---|
| status | SAVED · APPROVED · HOLD · REJECTED · PAID |
curl -s "https://beta.opsone.silverpush.live/api/v1/external/expenses?limit=5" \
-H "Authorization: Bearer $OPSONE_KEY"Spends — Vendors
vendorsVendor master data (identity only — no bank/tax fields)
- Actions
- listget· id field vendorId
- Filters
- vendorTypestringcategorystringcountrystringactiveboolean
Fields
curl -s "https://beta.opsone.silverpush.live/api/v1/external/vendors?limit=5" \
-H "Authorization: Bearer $OPSONE_KEY"Need a module that is not here?
The registry is the safety boundary — a module or field becomes reachable only when it is added there deliberately. Ask the IT team and say what you need it for. What OpsOne holds may help you name it.
