External API

A small, fixed REST API lets a few known external systems retrieve HPA data without going through the Keycloak login used by the rest of the portal. It runs as its own process, separate from the portal (server), the extractor, and Introscope EM, so a problem with an external caller cannot affect any of them.

Two pieces of data are available, both from the environment’s HpaInfrastructure agent:

  • the list of hosts monitored in an environment - SystemEdge machines, Oracle databases and Oracle RAC instances - with their CPU model, CPU count and RAM;
  • the CPU usage of those hosts over a period.

The metric behind each field is listed in External API metrics.

Authentication

Each request must carry an opaque API key as a bearer token:

Authorization: Bearer <key>

Keys are administrator-issued and are not tied to any user account. A key does not expire on its own; it stays valid until it is revoked or the whole API is disabled by the kill switch (see below).

Managing keys

Keys are issued and revoked from the admin-only External API Access page, and the kill switch is on its own External API Kill Switch page. Both are reachable from the help menu (only shown to administrators).

  • Create a key: a label is entered to identify the consumer (e.g. the external system’s name), and a new key is generated. The raw key is shown once, immediately after creation, and is not retrievable afterward - only its label and usage metadata (creation date, last-used date) remain visible in the list. If a key is lost, it is revoked and a new one is created.
  • Revoke a key: an individual key is invalidated; it stops working within a short delay (see below), and the action cannot be undone.
  • Kill switch: a single control disables every key at once, regardless of whether each individual key is itself still valid. It is meant as an emergency stop, not day-to-day key management - individual keys are revoked instead for that.

A revoked key, or the kill switch being turned on, does not take effect instantly: the API caches each key’s validity for up to about a minute, so a request made in the seconds right after a revocation may still briefly succeed. This delay is deliberate - it protects the portal from being hit by every request re-checking a key’s validity - and is not configurable from the admin page.

Endpoints

Both endpoints are read-only (GET) and require the Authorization header above.

Timestamps are ISO-8601. UTC (2024-01-01T00:00:00Z) is the simplest form; an explicit offset works too, but its + must be percent-encoded as %2B (2024-01-01T02:00:00%2B02:00), since a raw + in a URL query is read as a space and fails to parse. A period whose begin is not strictly before its end is rejected with 400 Bad Request.

A request rejected by the HPA server (period, resolution, unknown host) is answered with 400 Bad Request and a JSON error:

{"message": "begin must be strictly before end, got begin=2024-01-02T00:00Z end=2024-01-01T00:00Z", "code": "E09", "detailedMessage": null}

List hosts

GET /external-api/hosts?environment=<environment>[&begin=<begin>&end=<end>]

Returns the machines monitored by the environment’s HpaInfrastructure agent that reported CPU usage during the period:

  • SystemEdge machines first, with cpu_model, cpu_count (logical CPUs) and ram_in_kb, and db_host set to false;
  • then Oracle databases (one entry per database host) and Oracle RAC instances (named <instance>-instance-<rank>), with ram_in_kb and db_host set to true.

Every field is always present, null when its source metric does not exist for that kind of host (e.g. cpu_model for a database host). Naming rules are detailed in External API metrics.

begin/end are optional and, when used, must be given together. When omitted, the period is the last hour. Giving only one of the two is rejected with 400 Bad Request.

{
  "hosts": [
    {"name": "srv-app-01", "cpu_model": "GenuineIntel, 4 cores", "cpu_count": 8, "ram_in_kb": 65799856, "db_host": false},
    {"name": "10.0.10.21", "cpu_model": null, "cpu_count": null, "ram_in_kb": 65536000, "db_host": true},
    {"name": "PROD1-instance-1", "cpu_model": null, "cpu_count": null, "ram_in_kb": 134217728, "db_host": true}
  ]
}

Host CPU

GET /external-api/hosts/cpu?environment=<environment>[&host=<host>]&begin=<begin>&end=<end>&resolution=<resolution>

Returns a CPU usage time series for one host, or for every host returned by List hosts for the same period when host is omitted:

  • SystemEdge machine: 100 - %Idle;
  • database host (db_host true): the host CPU utilization measured by Oracle.

host is a name returned by List hosts (case ignored). A host that List hosts does not return for that environment and period - misspelled, not monitored, or without CPU data during the period - is rejected with 400 Bad Request and a JSON error naming it, rather than answered with a grid of null points.

begin, end and resolution are all required. resolution is an ISO-8601 duration giving the bucket width (e.g. PT15M for 15 minutes). Each host has exactly one point per bucket across [begin, end] - a fixed grid, not just however many raw samples happened to exist. A bucket with no data still appears, with cpuPercent set to null, rather than being left out.

resolution must be a positive duration; zero or negative is rejected with 400 Bad Request. A period asking for more than 10 000 points per host at the requested resolution is rejected the same way, rather than served short: the bucket width is honoured literally, so the response would otherwise stop before end and fold the whole remaining period into its last point. The error names the number of points requested and the smallest resolution that fits the period.

{
  "hosts": [
    {
      "host": "srv-app-01",
      "points": [
        {"timestamp": "2024-01-01T00:00:00Z", "cpuPercent": 42.7},
        {"timestamp": "2024-01-01T00:15:00Z", "cpuPercent": null},
        {"timestamp": "2024-01-01T00:30:00Z", "cpuPercent": 38.1}
      ]
    }
  ]
}

Example

Linux / macOS (bash):

curl -H "Authorization: Bearer <key>" \
  "https://<hpa-host>/external-api/hosts?environment=cal18ds"

Windows (PowerShell), curl.exe rather than the curl alias of Invoke-WebRequest:

curl.exe -H "Authorization: Bearer <key>" `
  "https://<hpa-host>/external-api/hosts?environment=cal18ds"

Windows (cmd):

curl -H "Authorization: Bearer <key>" ^
  "https://<hpa-host>/external-api/hosts?environment=cal18ds"

Interactive documentation

The OpenAPI description of both endpoints is browsable, without API key, with Swagger UI at https://<hpa-host>/external-api/docs. Its Try it out buttons call the API once a key is entered with Authorize, and show the matching curl command for bash (Linux, macOS), PowerShell and cmd (Windows). The raw description is at https://<hpa-host>/external-api/docs/openapi.yaml.

When the HPA server does not answer, a call gets 502 Bad Gateway, or 503 Service Unavailable if the key itself could not be checked: the key may still be valid. An unknown environment is also answered with 502.