Uniqkey can stream your organization's security events to your SIEM (Microsoft Sentinel, Splunk, Elastic, Wazuh, or any tool that can poll a REST API). This article explains how to enable the integration in the Admin Portal, how the events API works, and what to expect from the data.
Who can use this
- The integration is enabled per organization by an organization admin in the Admin Portal.
- Your SIEM needs outbound HTTPS access to the Uniqkey events endpoint.
- Events are the same audit log entries you already see under Audit logs in the Admin Portal. Nothing that is not visible there is exported, and no vault secrets, passwords, or keys are ever included.
Step 1: Enable the integration and generate a token
- Log in to the Admin Portal as an admin.
- Go to Integrations and open the SIEM tab.
- Copy the API endpoint shown at the top of the widget. This is the URL your SIEM will poll.
- Switch the SIEM toggle on, or click Generate Token. A dialog shows your new token.
- Copy the token and store it in your SIEM's secret store. The token is shown only once. After you close the dialog it cannot be displayed again.
Managing the token later:
- Regenerate Token issues a new token and immediately invalidates the old one. Update your SIEM before or right after regenerating, otherwise polling stops.
- Switching the SIEM toggle off deletes the token and disables the integration. Your SIEM will receive
403 Forbidden until a new token is generated. - There is one token per organization. If several tools need the feed, they share the token.
- Generating or deleting a token is itself recorded in the audit log.
Step 2: Configure your SIEM
Every SIEM connector needs the same three things:
| Setting | Value |
|---|---|
| Request | GET on the API endpoint copied from the SIEM tab (.../api/v1/events) |
| Authentication | HTTP header Authorization: Bearer <your token> |
| Paging | Persist the cursor from every response and send it back as the cursor query parameter on the next request. Keep polling while has_more is true. |
A poll every 5 minutes is a good default. Events become available about 2 minutes after they happen (see "What to expect" below), so polling faster than every 2 minutes gains nothing.
Quick test with curl
curl -s "https://<endpoint>/api/v1/events?limit=5" \ -H "Authorization: Bearer <your token>"
A working setup returns HTTP 200 with a JSON body like the one in the "Response" section. 401 means the Authorization header is missing or not a Bearer token. 403 means the token is unknown, was regenerated, or the integration is disabled.
API reference
Request
GET /api/v1/events
| Query parameter | Description |
|---|---|
cursor | Position marker from a previous response. Send it back unchanged. When present it decides where the page starts; start is ignored. |
start | Lower time bound, inclusive, ISO 8601 (for example 2026-09-01T00:00:00Z). Use it for the first poll or a backfill. UTC is assumed when no time zone is given. |
end | Upper time bound, exclusive, ISO 8601. Applied together with cursor, so a bounded backfill can page through. |
limit | Events per page. Default 200, maximum 1000. Values outside the range are clamped, not rejected. |
category | Filter to one or more categories. Repeat the parameter or separate values with commas: ?category=authentication,credential_access. Omitted means all categories. |
A request with no parameters is valid and returns your organization's history from the beginning, one page at a time.
The cursor is opaque. Do not build, parse, or modify it. Its format may change without notice, but a cursor you received will always keep working.
Response
{
"events": [ ... ],
"has_more": true,
"cursor": "eyJUIjoiMjAyNi0wOS0wMVQwOToxNDoyMi4xMTdaIiwiSSI6Ijlh..."
}
- Events are returned oldest first.
has_moretells you whether to request the next page right away. Loop onhas_more, not on an emptyeventsarray: a page can be empty while more data remains.cursoris always present, including on empty pages and whenhas_moreisfalse. Store it as your checkpoint after every response.
Errors return HTTP 400 with a machine-readable code:
{ "error": { "code": "invalid_cursor", "message": "Cursor is not valid. Submit the cursor from a previous response verbatim." } }
| Code | Meaning |
|---|---|
invalid_cursor | The cursor was modified or is not from this API. Restart from a start time. |
invalid_category | Unknown category value. The message lists the valid values. |
Newline-delimited JSON
If your collector prefers one event per line (Splunk generic REST inputs, Elastic, log shippers), send Accept: application/x-ndjson. The body then contains one JSON event per line with no envelope, and the paging fields move to response headers:
Content-Type: application/x-ndjson X-Next-Cursor: eyJUIjoi... X-Has-More: true
The headers carry the same guarantees as the JSON body: the cursor is always present, including on an empty page.
Event format
{
"id": "9a1c7f2e-4b13-4a8e-9f21-0c2b7d5e8a44",
"timestamp": "2026-09-01T09:14:22.117Z",
"category": "credential_access",
"action": "get_vault_password_details",
"action_id": "daf12269-a58f-4e3a-ab01-05b1293a7cac",
"action_source": "extension",
"outcome": "success",
"organization_id": "d5ecd732-4a67-418c-9dea-38a097fba1f6",
"actor": { "id": "3f2a...", "email": "jane.doe@example.com", "type": "user" },
"client": { "system": "extension", "ip": "185.23.44.9" },
"target": { "type": "vault", "id": "7c9d...", "name": "GitHub build account" }
}
| Field | Description |
|---|---|
id | Unique event id. Use it to deduplicate. |
timestamp | When the event happened, UTC. |
category | One of the categories below. Stable: a given action never changes category. |
action | Human-readable action name, for example login_to_extension. Not unique (the same action from two surfaces shares a name) and not guaranteed stable. Use it for display. |
action_id | Stable identifier of the action type. Build detection rules on this, not on action. |
action_source | Which part of Uniqkey defines the action: extension, mobile, web_portal, partner_portal, scim_service, desktop_extension, queue_messages, breach. Use it to tell apart two events with the same action. |
outcome | success or failure. See the note under "What to expect". |
organization_id | Your organization id. |
actor.id, actor.email | The employee who performed the action, when there is one. |
actor.type | user, scim, system, supporter (a partner support user), or breach. |
client.system | Where the request came from: extension, mobile, web, desktop, or undefined. Many events carry undefined; prefer action_source when you need the surface. |
client.ip | Source IP of the request, when recorded. May be absent. |
target.type, target.id, target.name | The object acted on: vault, employee, group, employee_group, resource_collection, or tag. name is the object's name at the time of the event and can be absent (tags never carry a name). |
Categories
| Category | Contains |
|---|---|
authentication | Sign-ins and sign-outs, master password lifecycle, SSO sign-in, trusted browser and portal sessions |
account_management | Employee lifecycle and profile changes: invited, activated, archived, deleted, including SCIM provisioning |
privilege_management | Admin promoted or revoked, partner support access granted |
group_management | Groups, employee groups, resource collections, tags, and their membership |
credential_access | A secret was viewed, copied, or its details requested, approved, or rejected. The highest-volume category. |
credential_management | Vault items and passkeys created, edited, or deleted |
sharing | Anything that changes who can reach a credential: shares, revokes, expiries, moves, unlinks |
data_export | Data leaving the system in bulk, such as login exports |
policy_management | Security settings, restrictions and restriction templates, retention periods, SSO provider configuration |
device_management | Devices and companion apps paired or unpaired, passive extension registration |
organization_management | Organization details, verified domains, organization archive and restore, SIEM token generated or deleted |
threat_detection | Data breach and password reuse monitoring events |
other | Generic events with no security meaning on their own, plus events recorded before the current categorization existed |
Because every event carries a category, you can point several connectors at the same endpoint with different category filters, for example to route credential_access to a cheaper storage tier and keep the rest in your analytics tier.
What to expect from the data
- Delivery is at least once. Under some conditions an event can be delivered twice. Deduplicate on
id. - Events appear about 2 minutes after they happen. The feed deliberately holds back the newest 2 minutes so no event is ever skipped while writes are still completing. This is why your SIEM should not poll faster than every 2 minutes.
- History is bounded by your audit log retention. The feed serves what your organization retains. Check Data Cleanup & Retention under organization settings. If your collector is down for longer than the retention period, the expired events cannot be recovered. Keep the collector running continuously.
outcomeis not a failed-login signal. Uniqkey does not currently record failed sign-in attempts, so everyauthenticationevent is a successful one.failureis used only for actions whose purpose is to record a denial, for example an approval request rejected on the mobile app. Do not build brute-force detections on this feed.client.ipis not always present. Events written by background processes, SCIM, or from some client flows carry no IP. The value is taken from the request as received and should be treated as reported by the client rather than verified by infrastructure.- Sensitive data is never included. Passwords, secure notes, card numbers, keys, and other encrypted vault content never leave the zero-knowledge boundary. The feed contains only the metadata visible in the Admin Portal audit log.
Notes per SIEM
Uniqkey does not ship pre-built connector packages yet. The endpoint follows the same conventions as other identity and password-manager vendors, so the standard REST polling mechanism of each SIEM works.
- Microsoft Sentinel: use a Codeless Connector or a Logic App with API key authentication (
Authorizationheader, prefixBearer). Configure paging on thecursorresponse field, sent back as thecursorquery parameter, and usehas_moreas the loop condition. The API acceptsstartandcursortogether, which is how the Codeless Connector Framework sends its second page. - Splunk: a REST modular input or an Add-on Builder input works. Send
Accept: application/x-ndjsonso each event is indexed as its own record, and readX-Next-CursorandX-Has-Morefor checkpointing. - Elastic: the Elastic Agent or Filebeat HTTP JSON / CEL input can poll the endpoint, persist
cursoras its cursor state, and loop onhas_more. NDJSON mode is also supported. - Wazuh: Wazuh has no native REST poller. Run a small scheduled script that polls the endpoint, keeps the
cursorin a state file, and writes events as JSON lines to a log file that a Wazuh agent monitors withlog_format: json.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
401 Unauthorized | No Authorization header, or it does not start with Bearer | Check the header format in the SIEM connector |
403 Forbidden | Token is wrong, was regenerated, or the integration was disabled | Generate a new token in the SIEM tab and update the SIEM |
400 invalid_cursor | Cursor was edited, truncated, or came from another organization | Reset the connector checkpoint and restart from a start time |
400 invalid_category | Typo in the category filter | Use one of the values from the category table |
| Feed is empty but the Admin Portal shows events | Events are younger than 2 minutes, or the category filter excludes them | Wait, or remove the filter |
| Connector stops after a while | Checkpoint was lost, or the token was regenerated | Confirm the cursor is persisted; confirm the token in the SIEM matches the latest one |
| Missing older events | Audit log retention has expired them | Check the retention period; run the collector continuously |
| Duplicate events | Normal for at-least-once delivery | Deduplicate on id |
When contacting support, include your organization id, the exact request URL without the token, the HTTP status, and the response body.