Public API
Authenticate to Elba’s read-only REST API and choose the correct regional endpoint.
The Elba Public REST API provides read-only access to organization security data for reporting and integrations.
Regional base URLs
Use the endpoint for the region where your Elba workspace is hosted:
| Region | v1 | v2 |
|---|---|---|
| EU | https://api.eu.elba.security/v1 | https://api.eu.elba.security/v2 |
| US | https://api.us.elba.security/v1 | https://api.us.elba.security/v2 |
Do not send an EU workspace API key to the US endpoint or a US workspace key to the EU endpoint.
Create an API key
- In the Elba admin workspace, open Settings → General.
- Find API Keys and create a key with a descriptive name.
- Copy the generated value and store it in an approved secrets manager.
- Delete keys that are no longer used.
Treat an API key like a password. Never commit it, paste it into customer-facing logs, or expose it in browser code.
Authenticate a request
Send the key as a Bearer token:
curl --request GET \
--header "Authorization: Bearer $ELBA_API_KEY" \
"https://api.eu.elba.security/v1/users?limit=100&offset=0"Replace the hostname with the US endpoint when your workspace is hosted in the US.
Available resources
The current API includes read-only endpoints for:
- users and leaderboard metrics;
- training completion;
- phishing simulation results;
- data-protection issues;
- third-party application accounts, inventory, and issues.
Most list endpoints accept limit and offset. Use pagination and request only the data you need.
Canonical application inventory (v2)
Version 2 exposes Third-Party Apps as a unified inventory. It combines verified accounts from identity and OAuth integrations, corroborating email activity, and inferred browser usage, AI account context, and browser-extension installations without turning browser observations into accounts.
Version 2 is available to every workspace. Version 1 remains available and unchanged.
The existing GET /v1/tpa/inventory response is unchanged and continues to contain connector-backed associated accounts only.
List applications
curl --request GET \
--header "Authorization: Bearer $ELBA_API_KEY" \
"https://api.eu.elba.security/v2/tpa/inventory?limit=100&offset=0"GET /v2/tpa/inventory returns one item per canonical or workspace-private application. Each item contains:
- canonical identity and product classification;
- organization policy, its nullable browser-enforceable domain, criticality, and owner;
- application posture and access exposure as separate assessments;
- user and evidence counts by evidence type;
- detection sources and first/last-seen freshness;
- aggregate work, personal, mixed, signed-out, and unknown AI account context.
The default response includes active and needs-review applications, suites, and standalone browser extensions; identity.inventory_state distinguishes them. Ambiguous detections, websites, devices, platforms, and system components remain in Elba’s classification workflow and are not returned as applications until reviewed.
Catalog posture is nullable: application_posture is null for a private provisional application. Browser-only applications return access_exposure.assessment as no_verified_access_evidence.
identity.domain describes the reviewed application identity and can be populated from an exact-host review. policy.enforceable_domain is deliberately stricter: it contains only a safe reviewed registrable domain that Browser Security can enforce, and is null when no such domain exists. A denied policy with a null value remains visible but is not applied to browser traffic.
[
{
"application_handle": "notion",
"identity": {
"type": "catalog",
"name": "Notion",
"entity_kind": "application",
"inventory_state": "active",
"url": "https://www.notion.so",
"logo_url": "https://cdn.example/notion.svg",
"domain": "notion.so",
"publisher": "Notion Labs",
"description": "Connected workspace",
"parent_application_handle": null,
"observed_surface": null
},
"policy": {
"status": "allowed",
"enforceable_domain": "notion.so",
"criticality_level": 2,
"owner": null
},
"application_posture": {
"assessment": "assessed",
"trust_score": 86,
"is_verified": true,
"last_reviewed_at": "2026-07-10T09:00:00Z",
"cves": [],
"breaches": []
},
"access_exposure": {
"assessment": "available",
"verified_users": 12,
"high_risk_permissions": 1
},
"evidence_counts": {
"total_users": 15,
"current_users": 14,
"stale_browser_users": 1,
"verified_users": 12,
"idp_accounts": 8,
"oauth_grants": 4,
"email_activity": 3,
"browser_usage": 10,
"browser_ai_account_context": 0,
"browser_extension_installations": 0
},
"detection_sources": [
{
"id": "00000000-0000-0000-0000-000000000000",
"name": "Google Workspace",
"logo_url": null,
"evidence_types": ["oauth_grant"],
"strengths": ["verified"],
"freshness": {
"first_seen_at": "2026-01-12T10:00:00Z",
"last_seen_at": "2026-07-18T08:00:00Z",
"state": "fresh"
}
}
],
"freshness": {
"first_seen_at": "2026-01-12T10:00:00Z",
"last_seen_at": "2026-07-18T08:00:00Z",
"state": "fresh"
},
"ai_account_context": {
"work": 0,
"personal": 0,
"mixed": 0,
"signed_out": 0,
"unknown": 0
}
}
]List users and evidence for an application
URL-encode applicationHandle when constructing the path.
curl --request GET \
--header "Authorization: Bearer $ELBA_API_KEY" \
"https://api.eu.elba.security/v2/tpa/inventory/notion/users?limit=100&offset=0"GET /v2/tpa/inventory/:applicationHandle/users paginates people or unlinked connector accounts, not individual evidence rows. Evidence remains attributed to its source and is labeled verified, corroborated, or inferred. Only connector-backed evidence can set can_remediate to true.
[
{
"identity": {
"type": "elba_user",
"id": "00000000-0000-0000-0000-000000000000",
"email": "[email protected]",
"display_name": "Alex Martin",
"profile_picture_url": null
},
"freshness": {
"first_seen_at": "2026-05-01T08:00:00Z",
"last_seen_at": "2026-07-18T08:00:00Z",
"state": "fresh"
},
"evidence": [
{
"type": "browser_extension_installation",
"strength": "inferred",
"source": {
"id": "00000000-0000-0000-0000-000000000001",
"name": "Chrome Browser Security",
"logo_url": null
},
"first_seen_at": "2026-05-01T08:00:00Z",
"last_seen_at": "2026-07-18T08:00:00Z",
"freshness": "fresh",
"authentication": null,
"ai_account_context": null,
"installation_state": "installed",
"extension_installation": {
"state": "installed",
"enabled": true,
"install_type": "admin",
"version": "4.5.6",
"permission_summary": {
"permission_names": ["storage", "tabs"],
"unknown_permission_count": 1,
"host_permission_count": 2,
"host_permission_scope": "specific_sites"
}
},
"can_remediate": false
}
]
}
]Browser evidence never supplies an external account identifier. An elba_user email comes from the workspace member directory, not from browser content. If that member is deleted or no longer enrolled, the stable Elba user ID remains available while email, display_name, and profile_picture_url are null; browser evidence is no longer current, while connector-backed evidence keeps its connector state and can keep the subject fresh. AI evidence exposes only the context enum; it never exposes a detected email, account domain, page URL, prompt, or page content.
extension_installation is non-null only for browser_extension_installation evidence. Its permission summary is privacy-safe: permission_names contains only recognized, non-host browser API permission names; unrecognized values are represented only by unknown_permission_count; and host access is reduced to a count and the none, specific_sites, all_sites, or unknown scope. Raw host patterns, hostnames, domains, and full URLs are never returned. permission_summary is null for observations reported by earlier extension versions. This browser-observed facet remains inferred and non-remediable; it is not an application account or an OAuth permission assessment.
An external_account identity is emitted only for unlinked connector evidence. It has a stable opaque account:<sha256> identifier, nullable email and display_name fields, and the connector source; its identifier is never derived from browser activity or exposed account data.
Browser observations are fresh for 30 days after last_seen_at; older observations remain available as stale. Connector-backed evidence does not expire under this rule. An application without a usable evidence timestamp has freshness unknown.
Common errors
| Status | What to check |
|---|---|
401 Unauthorized | The Bearer header, API key value, key status, and regional endpoint. |
404 Not Found | The API version prefix, resource path, and selected region. |
429 Too Many Requests | Reduce request frequency, honor retry information, and add backoff. |
For the complete schema and response shapes, use the OpenAPI reference supplied with your Elba workspace or contact Elba support.