Connecting your SIEM to the Uniqkey audit log feed

Have more questions? Submit a request

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

  1. Log in to the Admin Portal as an admin.
  2. Go to Integrations and open the SIEM tab.
  3. Copy the API endpoint shown at the top of the widget. This is the URL your SIEM will poll.
  4. Switch the SIEM toggle on, or click Generate Token. A dialog shows your new token.
  5. 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:

SettingValue
RequestGET on the API endpoint copied from the SIEM tab (.../api/v1/events)
AuthenticationHTTP header Authorization: Bearer <your token>
PagingPersist 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 parameterDescription
cursorPosition marker from a previous response. Send it back unchanged. When present it decides where the page starts; start is ignored.
startLower 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.
endUpper time bound, exclusive, ISO 8601. Applied together with cursor, so a bounded backfill can page through.
limitEvents per page. Default 200, maximum 1000. Values outside the range are clamped, not rejected.
categoryFilter 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_more tells you whether to request the next page right away. Loop on has_more, not on an empty events array: a page can be empty while more data remains.
  • cursor is always present, including on empty pages and when has_more is false. 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." } }
CodeMeaning
invalid_cursorThe cursor was modified or is not from this API. Restart from a start time.
invalid_categoryUnknown 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" }
}
FieldDescription
idUnique event id. Use it to deduplicate.
timestampWhen the event happened, UTC.
categoryOne of the categories below. Stable: a given action never changes category.
actionHuman-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_idStable identifier of the action type. Build detection rules on this, not on action.
action_sourceWhich 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.
outcomesuccess or failure. See the note under "What to expect".
organization_idYour organization id.
actor.id, actor.emailThe employee who performed the action, when there is one.
actor.typeuser, scim, system, supporter (a partner support user), or breach.
client.systemWhere the request came from: extension, mobile, web, desktop, or undefined. Many events carry undefined; prefer action_source when you need the surface.
client.ipSource IP of the request, when recorded. May be absent.
target.type, target.id, target.nameThe 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

CategoryContains
authenticationSign-ins and sign-outs, master password lifecycle, SSO sign-in, trusted browser and portal sessions
account_managementEmployee lifecycle and profile changes: invited, activated, archived, deleted, including SCIM provisioning
privilege_managementAdmin promoted or revoked, partner support access granted
group_managementGroups, employee groups, resource collections, tags, and their membership
credential_accessA secret was viewed, copied, or its details requested, approved, or rejected. The highest-volume category.
credential_managementVault items and passkeys created, edited, or deleted
sharingAnything that changes who can reach a credential: shares, revokes, expiries, moves, unlinks
data_exportData leaving the system in bulk, such as login exports
policy_managementSecurity settings, restrictions and restriction templates, retention periods, SSO provider configuration
device_managementDevices and companion apps paired or unpaired, passive extension registration
organization_managementOrganization details, verified domains, organization archive and restore, SIEM token generated or deleted
threat_detectionData breach and password reuse monitoring events
otherGeneric 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.
  • outcome is not a failed-login signal. Uniqkey does not currently record failed sign-in attempts, so every authentication event is a successful one. failure is 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.ip is 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 (Authorization header, prefix Bearer ). Configure paging on the cursor response field, sent back as the cursor query parameter, and use has_more as the loop condition. The API accepts start and cursor together, 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-ndjson so each event is indexed as its own record, and read X-Next-Cursor and X-Has-More for checkpointing.
  • Elastic: the Elastic Agent or Filebeat HTTP JSON / CEL input can poll the endpoint, persist cursor as its cursor state, and loop on has_more. NDJSON mode is also supported.
  • Wazuh: Wazuh has no native REST poller. Run a small scheduled script that polls the endpoint, keeps the cursor in a state file, and writes events as JSON lines to a log file that a Wazuh agent monitors with log_format: json.

Troubleshooting

SymptomLikely causeFix
401 UnauthorizedNo Authorization header, or it does not start with BearerCheck the header format in the SIEM connector
403 ForbiddenToken is wrong, was regenerated, or the integration was disabledGenerate a new token in the SIEM tab and update the SIEM
400 invalid_cursorCursor was edited, truncated, or came from another organizationReset the connector checkpoint and restart from a start time
400 invalid_categoryTypo in the category filterUse one of the values from the category table
Feed is empty but the Admin Portal shows eventsEvents are younger than 2 minutes, or the category filter excludes themWait, or remove the filter
Connector stops after a whileCheckpoint was lost, or the token was regeneratedConfirm the cursor is persisted; confirm the token in the SIEM matches the latest one
Missing older eventsAudit log retention has expired themCheck the retention period; run the collector continuously
Duplicate eventsNormal for at-least-once deliveryDeduplicate on id

When contacting support, include your organization id, the exact request URL without the token, the HTTP status, and the response body.

Articles in this section