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.

Base URL
https://beta.opsone.silverpush.live/api/v1/external

Getting 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.

A key can also be restricted to a list of IP addresses and given its own requests-per-minute ceiling and an expiry date. Ask for those if the caller is a fixed server — they cost nothing and make a leaked key far less useful.

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.

Request
curl -s https://beta.opsone.silverpush.live/api/v1/external/me \
  -H "Authorization: Bearer opk_xxxxxxxx_your-secret-here"
Response
{
  "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 & pathWhat it returns
GET /meThe 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.

GET /employees?status=ACTIVE&limit=2
{
  "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.

ParameterDefaultNotes
limit501 to 100.
offset0Page by adding limit each time, until offset reaches pagination.total.
<filter>Per module; see the reference below. Several combine with AND.
Paging through the directory
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.

StatusCodeWhat it means
400bad_requestlimit or offset is out of range.
400bad_filterA filter is unknown, or its value is not legal.
401unauthorizedNo Authorization: Bearer header was sent.
401invalid_keyThe key is malformed, unknown, revoked or wrong.
401key_expiredThe key passed its expiry date.
403api_disabledAn administrator has switched the External API off.
403ip_not_allowedThis key is restricted to other IP addresses.
403scope_deniedThe key's scopes do not cover this module or action.
404module_not_foundNo such module.
404not_foundNo record with that id — or the scope hides it.
429rate_limitedToo many requests this minute.
500scope_filter_invalidThe 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:

Response headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57

Over the ceiling you get 429 rate_limited. The window is a rolling minute, so waiting a moment is enough; there is no penalty period.

Every call — successful or not — is recorded against the key with its path, status, duration and source IP, and is visible to administrators under Admin → API Access. Nothing here is anonymous.

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

employees

Employee 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

employeeIdfirstNamemiddleNamelastNamefullNameofficialEmailemployeeTypedesignationdepartmentsubDepartmentregioncountryentityentityNameentityCodeworkLocationstatusjoiningDatelastWorkingDatemanagerEmployeeIdmanagerNamemanagerEmail
FilterLegal values
statusUPCOMING · ACTIVE · EXIT_INITIATED · EXITED
employeeTypeEMPLOYEE · CONSULTANT · TEMP · SYSTEM
Example
curl -s "https://beta.opsone.silverpush.live/api/v1/external/employees?limit=5" \
  -H "Authorization: Bearer $OPSONE_KEY"

Assets — Inventory

assets

Hardware inventory (no cost or supplier data)

Actions
listget· id field assetTag
Filters
statusstringcategorystringlocationstringassetTagstringassigneeEmployeeIdstring

Fields

assetTagnameserialstatuscategorylocationassigneeEmployeeIdpurchaseDatewarrantyExpiresAt
Example
curl -s "https://beta.opsone.silverpush.live/api/v1/external/assets?limit=5" \
  -H "Authorization: Bearer $OPSONE_KEY"

Spends — Expenses

expenses

Expense records (amounts + workflow status; no payment rails)

Actions
listget· id field spendNumber
Filters
statusenumcurrencystringteamstringvendorNamestringcategoryNamestring

Fields

spendNumbertitlestatusamountInINRcurrencyvendorNamecategoryNameteamexpenseDate
FilterLegal values
statusSAVED · APPROVED · HOLD · REJECTED · PAID
Example
curl -s "https://beta.opsone.silverpush.live/api/v1/external/expenses?limit=5" \
  -H "Authorization: Bearer $OPSONE_KEY"

Spends — Vendors

vendors

Vendor master data (identity only — no bank/tax fields)

Actions
listget· id field vendorId
Filters
vendorTypestringcategorystringcountrystringactiveboolean

Fields

vendorIdnamedisplayNamevendorTypecategorycountry
Example
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.