Overview
SparkVault records security-relevant activity in a unified audit log. Every entry captures what happened (event_type), when (timestamp), who did it (actor_id), and from where (ip_address, user_agent), plus event-specific metadata. Events are partitioned into three scopes, each with its own list endpoint:
| Scope | What it records | Endpoint | Auth |
|---|---|---|---|
| Account | Console sign-in, members and licenses, API keys, custom domains, vault create/delete, SparkLink lifecycle and receipts, Identity sign-in verification | GET /v1/audit-logs |
API key or JWT |
| Vault | Vault settings, seal/unseal, sharing, upload portals, DVAKs, folder operations | GET /v1/vaults/{vault_id}/audit-logs |
API key or JWT + X-Vault-Access-Token |
| Ingot | Per-file activity: creation, uploads, downloads, renames, moves, deletion, SparkLink opens | GET /v1/vaults/{vault_id}/ingots/{ingot_id}/audit-logs |
API key or JWT + X-Vault-Access-Token |
Entries are returned newest-first with sealed cursor pagination. Account entries are stored in plaintext. Vault and ingot entry metadata is encrypted at rest with AES-256-GCM under a key derived (HKDF) from the vault's Vault Access Key (VAK) when the event is recorded through an unsealed session. It can only be decrypted with a valid Vault Access Token. Events recorded outside a vault session (such as retention_changed) store their metadata in plaintext.
Entry Fields
Audit Log Entry
| Field | Type | Description |
|---|---|---|
timestamp |
integer | Unix timestamp of the event in epoch seconds |
event_type |
string | Event identifier (see Event Types) |
actor_id |
string? | Who performed the action: a user (usr_...); for a request made with an API key, the key (key_...), whose creator the entry's metadata.api_key_created_by names; for a verified-interaction receipt, the identity the recipient verified; system for a change SparkVault makes on its own, such as a license change taking effect at renewal. An entry a SparkVault product writes while serving your request (Structured Ingots storing, reading or deleting an ingot) names whoever called the product, user or API key, and the client that call came from. null when no user or key is attributable: a visitor on a shared link or a public upload page, or a person using the Identity product (the events it records for them, such as a sign-in, a passkey change or an identity merge, and the sign-in link it sends them), each described by its metadata. |
actor_type |
string? | user or api_key, present when the actor still exists in your account and could be resolved |
actor_display |
string? | Human-readable actor: the user's email or the API key's name, present when resolved |
ip_address |
string? | Client IP address that triggered the event; null on a system entry and on an event the Identity product records, whose metadata carries the address only hashed |
user_agent |
string? | Client user agent; for a system entry, the SparkVault operation that made the change |
metadata |
object? | Event-specific details. Decrypted transparently on vault/ingot endpoints using your VAT session; null when the event carries none. |
vault_id |
string? | Present on vault- and ingot-scope entries |
ingot_id |
string? | Present on ingot-scope entries |
Audit logs answer who did what, and when. For usage aggregates and analytics dashboards, see Reporting.
Event Types
Each scope has its own set of event types. The account, vault, and ingot list endpoints return the full valid set for their scope in the response's event_types field, so you can build filters without hardcoding the lists below.
Account Events
| Category | Event Types |
|---|---|
| Members and licenses | user_invited, user_removed, user_deleted_self, user_seat_type_set, user_license_requested |
| Console sign-in | login, logout |
| Account settings | organization_name_changed, logo_updated, custom_domain_added, custom_domain_removed |
| Vault lifecycle | vault_created, vault_deleted |
| API keys | api_key_created, api_key_revoked |
| Delegated Vault Access Keys (DVAKs) | dvak_auto_revoked: a member's DVAKs revoked because they left the account or their license changed |
| SparkLink lifecycle | sparklink_created, sparklink_updated, sparklink_deleted |
| Verified-interaction receipts | sparklink_accessed, sparklink_signed, sparklink_approved, sparklink_denied, sparklink_replied |
| Identity sign-in | auth_attempt, auth_success, auth_failure, passkey_removed, identity_merged |
The account-scope event_types response set also includes platform-admin event types (admin_impersonate, admin_account_deleted, admin_status_changed, admin_pricing_updated, dvak_rekey_plan, and the admin_identity_* directory events). These are recorded only under the SparkVault platform admin account, so your own audit logs will never contain them.
Verified-interaction receipt events (sparklink_accessed, sparklink_signed, sparklink_approved, sparklink_denied, sparklink_replied) are recorded at the account scope in plaintext so they can be presented as third-party proof without a vault key: the signed EdDSA receipt token and action_hash ride in metadata and are JWKS-verifiable.
Vault Events
| Category | Event Types |
|---|---|
| Vault operations | vault_renamed, vault_settings_changed, vault_unsealed, vault_sealed |
| Sharing | sharing_enabled, sharing_disabled, sharing_config_changed |
| Upload portal and widget | upload_portal_enabled, upload_portal_disabled, upload_portal_repaired, upload_widget_enabled, upload_widget_disabled, upload_widget_repaired |
| Hosted key wrapper | hvmk_key_created |
| Delegated Vault Access Keys | dvak_created, dvak_revoked, dvak_used |
| Folders | folder_created, folder_renamed, folder_moved, folder_updated, folder_deleted |
| Ingot deletion (an ingot's own log is deleted with it) | ingot_deleted |
| Retention | retention_changed |
Ingot Events
| Category | Event Types |
|---|---|
| Lifecycle | ingot_created, ingot_uploaded, ingot_renamed, ingot_moved |
| Access (a download through a SparkLink included) | ingot_downloaded |
Pagination and Filtering
All list endpoints share the same cursor-based pagination and filtering contract:
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | Optional | Entries per page, at most 100: a larger value reads as 100, and a missing, zero, negative or non-numeric one as 25 (Pagination).Default: 25 |
cursor |
string | Optional | Opaque sealed pagination cursor: pass back the next_cursor from the previous responseDefault: null |
event_types |
string | Optional | Comma-separated event type filter, e.g. ?event_types=login,logoutDefault: none (all events) |
- Ordering: entries are returned newest-first;
timestampis epoch seconds. has_more/next_cursor:next_cursoris present only whenhas_moreistrue. Keep requesting with?cursor=untilhas_moreisfalse.- Sealed cursors: a cursor is encrypted and authenticated under a key derived for it from your account's key, and bound to the exact audit scope it was minted for, so it reveals nothing about the entries it resumes from. A tampered cursor, a cursor from another account, or a cursor replayed against a different scope returns
400 VALIDATION_ERROR. - Filtered pages can run short: with an
event_typesfilter, a page may contain fewer thanlimitentries (even zero) whilehas_moreis stilltrue. Always page byhas_more, not by page size.
Account Audit Logs
/v1/audit-logs
List account-scope audit logs: console sign-in, members and licenses, API keys, custom domains, vault lifecycle, SparkLink lifecycle and receipts, and Identity sign-in verification.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | Optional | Entries per page, at most 100; a larger value reads as 100Default: 25 |
cursor |
string | Optional | Sealed pagination cursor from a previous responseDefault: null |
event_types |
string | Optional | Comma-separated filter of account event typesDefault: none (all events) |
Response
| Field | Type | Description |
|---|---|---|
entries |
array | Audit log entries, newest first (see Entry Fields in the Overview) |
count |
integer | Number of entries in this page |
has_more |
boolean | Whether more pages exist |
next_cursor |
string? | Sealed cursor for the next page (present when has_more is true) |
event_types |
string[] | Every valid account-scope event type, useful for building filter UIs |
List Recent Sign-ins
Requestcurl "https://api.sparkvault.com/v1/audit-logs?limit=2&event_types=login,logout" \
-H "X-API-Key: sv_live_xxx"
{
"data": {
"entries": [
{
"timestamp": 1702000600,
"event_type": "login",
"actor_id": "usr_abc123...",
"actor_type": "user",
"actor_display": "admin@example.com",
"ip_address": "203.0.113.7",
"user_agent": "Mozilla/5.0...",
"metadata": null
},
{
"timestamp": 1702000000,
"event_type": "logout",
"actor_id": "usr_abc123...",
"actor_type": "user",
"actor_display": "admin@example.com",
"ip_address": "198.51.100.23",
"user_agent": "Mozilla/5.0...",
"metadata": null
}
],
"count": 2,
"has_more": true,
"next_cursor": "eyJrZXkiOnsi...",
"event_types": ["user_invited", "user_removed", "user_seat_type_set", "..."]
}
}
Vault Audit Logs
/v1/vaults/{vault_id}/audit-logs
List vault-scope audit logs: settings, seal/unseal, sharing, upload portals, DVAKs, and folder operations. Requires an unsealed vault session (VAT).
This endpoint requires the X-Vault-Access-Token header with a valid VAT obtained by unsealing the vault. Entry metadata is stored encrypted and is decrypted transparently with the VAK held by your VAT session. Vault-scope events cover the vault itself. Per-file events live on the per-ingot endpoint.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
vault_id |
string | Required | Vault identifier (vlt_...) |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | Optional | Entries per page, at most 100; a larger value reads as 100Default: 25 |
cursor |
string | Optional | Sealed pagination cursor from a previous responseDefault: null |
event_types |
string | Optional | Comma-separated filter of vault event typesDefault: none (all events) |
Response
| Field | Type | Description |
|---|---|---|
entries |
array | Audit log entries, newest first; each includes vault_id |
count |
integer | Number of entries in this page |
has_more |
boolean | Whether more pages exist |
next_cursor |
string? | Sealed cursor for the next page (present when has_more is true) |
vault_id |
string | The requested vault |
event_types |
string[] | Every valid vault-scope event type |
List Vault Events
Requestcurl "https://api.sparkvault.com/v1/vaults/vlt_abc123/audit-logs?limit=25" \
-H "X-API-Key: sv_live_xxx" \
-H "X-Vault-Access-Token: vat_xyz789..."
{
"data": {
"entries": [
{
"timestamp": 1702000000,
"event_type": "vault_unsealed",
"actor_id": "usr_abc123...",
"actor_type": "user",
"actor_display": "admin@example.com",
"ip_address": "203.0.113.7",
"user_agent": "Mozilla/5.0...",
"metadata": { "ttl_seconds": 3600 },
"vault_id": "vlt_abc123..."
}
],
"count": 1,
"has_more": false,
"vault_id": "vlt_abc123...",
"event_types": ["vault_renamed", "vault_settings_changed", "..."]
}
}
The VAT must belong to the requested vault and to your account: a mismatch, or a token that has expired, returns 403 FORBIDDEN. A missing, malformed, or unknown token returns 401 AUTHENTICATION_ERROR, and a vault that does not exist (or is not owned by your account) returns 404 NOT_FOUND.
Ingot Audit Logs
/v1/vaults/{vault_id}/ingots/{ingot_id}/audit-logs
List per-ingot audit logs: creation, uploads, renames, moves and downloads (a SparkLink download included) on a single file. Requires an unsealed vault session (VAT).
The per-ingot endpoint follows the same auth, pagination, and filtering contract as the vault endpoint above: X-Vault-Access-Token required, encrypted metadata decrypted via your VAT session, and a response carrying entries (each with vault_id and ingot_id), count, has_more, next_cursor, and the valid ingot-scope event_types. Full documentation lives on the Ingots page.
Retention
Every audit entry is written with an expiry and is removed automatically when it lapses. The default retention window is 90 days (7,776,000 seconds).
Each vault additionally carries a configurable access-log retention setting (GET/PUT /v1/vaults/{vault_id}/access-log-retention, see the Vaults docs) that governs how long ingot access events recorded through public sharing surfaces (public portal uploads and SparkLink downloads) are kept. Setting it to 0 (Disabled) turns that logging off entirely: no entries are written. The change itself is always recorded as a retention_changed vault event under the default window, so the configuration trail survives even when access logging is disabled.
| Value (seconds) | Window |
|---|---|
0 | Disabled: no access-log entries are written |
86400 | 24 hours |
604800 | 7 days |
2592000 | 1 month |
5184000 | 2 months |
7776000 | 3 months (default) |
15552000 | 6 months |
23328000 | 9 months |
31536000 | 1 year |
63072000 | 2 years |
94608000 | 3 years |
Audit logs are owned by the entity they describe. Deleting an ingot, a vault, or your account permanently deletes the audit history recorded under it. Export anything you need for compliance before deleting.
Error Reference
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR |
Invalid or tampered pagination cursor (wrong account or scope) |
| 401 | AUTHENTICATION_ERROR |
Missing or invalid API key/JWT; missing, malformed, or unknown X-Vault-Access-Token on vault and ingot endpoints |
| 403 | FORBIDDEN |
The VAT belongs to a different vault or account than the one requested, or the token has expired |
| 404 | NOT_FOUND |
Vault does not exist or is not owned by your account |
| 429 | RATE_LIMIT_EXCEEDED |
Too many requests |