Audit Logs v1

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

FieldTypeDescription
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.

Portable Receipts Live at the Account Scope

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

ParameterTypeRequiredDescription
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; timestamp is epoch seconds.
  • has_more / next_cursor: next_cursor is present only when has_more is true. Keep requesting with ?cursor= until has_more is false.
  • 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_types filter, a page may contain fewer than limit entries (even zero) while has_more is still true. Always page by has_more, not by page size.

Account Audit Logs

GET /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

ParameterTypeRequiredDescription
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

FieldTypeDescription
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

Request
bash
curl "https://api.sparkvault.com/v1/audit-logs?limit=2&event_types=login,logout" \
  -H "X-API-Key: sv_live_xxx"
Response
json
{
  "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

GET /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

ParameterTypeRequiredDescription
vault_id string Required Vault identifier (vlt_...)

Query Parameters

ParameterTypeRequiredDescription
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

FieldTypeDescription
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

Request
bash
curl "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..."
Response
json
{
  "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", "..."]
  }
}
VAT Context Checks

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

GET /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
0Disabled: no access-log entries are written
8640024 hours
6048007 days
25920001 month
51840002 months
77760003 months (default)
155520006 months
233280009 months
315360001 year
630720002 years
946080003 years
Deletion Cascades to Audit History

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

StatusCodeDescription
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