Authentication v1

Overview

SparkVault supports two authentication methods:

Method Header Best For
API Key X-API-Key Server-to-server integrations, automation, CI/CD pipelines
JWT Token Authorization: Bearer User-facing applications, browser sessions
Which should I use?

For most integrations, API keys are the simplest choice. Use JWT tokens only if you're building a user-facing application that needs to manage individual user sessions.

API Key Authentication

API keys provide simple, persistent authentication for server-side integrations. Create an API key from the API Keys page and include it in the X-API-Key header.

bash Using an API key
curl https://api.sparkvault.com/v1/sparks \
  -H "X-API-Key: sv_live_abc123xyz789..."

API Key Format

API keys follow a consistent format:

  • sv_live_...: Production keys (live data)
Keep API keys secret

API keys grant full access to your account. Never expose them in client-side code, public repositories, or logs.

If a key is compromised, revoke it immediately from the API Keys page.

Example: Creating a Spark with an API key

bash
curl -X POST https://api.sparkvault.com/v1/sparks \
  -H "X-API-Key: sv_live_abc123xyz789..." \
  -H "Content-Type: application/json" \
  -d '{
    "payload": "super_secret_password_123"
  }'

Managing API Keys Programmatically

API keys can be managed in the app at app.sparkvault.com/api/keys, or programmatically with the endpoints below. All three endpoints require authentication (JWT or API key). Creating and revoking keys additionally require an admin or owner role. Non-admin users receive 403 FORBIDDEN.

POST /v1/api-keys

Create a new API key. Requires an admin or owner role. The full key string is returned once and is never retrievable again.

Request Body

ParameterTypeRequiredDescription
name string Required Display name identifying the key's purpose (max 100 characters).
expires_in_days integer Optional Days until the key expires (1-3650). Omit for a non-expiring key.

Response Fields

FieldTypeDescription
api_key_id string Unique key identifier (key_...). Use this id to revoke the key.
api_key string The full API key (sv_live_...). Shown only in this response. Store it securely.
key_preview string Masked preview for display (e.g. sv_live_ab...wxyz).
name string The key's display name.
created_at integer Creation time (Unix epoch seconds).
expires_at integer Expiration time (Unix epoch seconds), or null if the key does not expire.
warning string Reminder that the key will not be shown again.

Example

Request
bash
curl -X POST https://api.sparkvault.com/v1/api-keys \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI/CD pipeline",
    "expires_in_days": 90
  }'
Response
json
{
  "data": {
    "api_key_id": "key_abc123...",
    "api_key": "sv_live_abc123xyz789...",
    "key_preview": "sv_live_ab...z789",
    "name": "CI/CD pipeline",
    "created_at": 1783036800,
    "expires_at": 1790812800,
    "warning": "Store this API key securely. It will not be shown again."
  }
}
GET /v1/api-keys

List the account's API keys with cursor-based pagination. Key strings are never returned, only masked previews.

Query Parameters

ParameterTypeRequiredDescription
limit integer Optional Maximum keys per page (1-100).Default: 50
cursor string Optional Pagination cursor from a previous response's next_cursor.

Response Fields

FieldTypeDescription
api_keys array Key objects: api_key_id, name, key_preview, status (active | expired | revoked), created_at, last_used_at, expires_at, revoked_at.
count integer Number of keys in this page.
has_more boolean Whether more pages are available.
next_cursor string Cursor for the next page. Present only when has_more is true.
active integer Number of active keys in this page.
DELETE /v1/api-keys/:id

Revoke an API key by its api_key_id. Requires an admin or owner role. Idempotent: revoking an already-revoked key succeeds and returns its original revocation time.

Response Fields

FieldTypeDescription
api_key_id string The revoked key's identifier.
name string The key's display name. Returned only on first revocation. When the key was already revoked, the response omits name and includes a message field instead.
status string Always revoked.
revoked_at integer Revocation time (Unix epoch seconds).

JWT Token Authentication

JWT tokens are used for user session management in browser-based applications. SparkVault uses the Identity Product as an OIDC provider for user authentication. After successful authentication via Identity, you'll receive SparkVault session tokens.

bash Using a JWT token
curl https://api.sparkvault.com/v1/sparks \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Token Types

Type Lifetime Purpose
Access Token 1 hour Short-lived token for API requests
Refresh Token 30 days Single-use token to obtain new access tokens (rotated on every refresh)

User Authentication Flow

SparkVault uses an OIDC (OpenID Connect) flow with the Identity Product for user authentication. This provides passwordless login via passkeys, magic links, social login, and more.

Flow Overview

  1. Initiate Login: Redirect user to Identity Product with PKCE challenge
  2. User Authenticates: Via passkey, magic link, or social login
  3. Callback: Identity Product redirects back with authorization code
  4. Token Exchange: Exchange code for SparkVault session tokens
  5. Registration (New Users): Complete profile setup if needed
Identity Product

For detailed OIDC integration instructions, see the Identity Product documentation. The SparkVault web app uses Identity Product for all user authentication.

Session Endpoints

POST /v1/auth/identity/token

Exchange an OIDC authorization code from Identity Product for SparkVault session tokens. This is called after the user completes authentication via Identity Product.

Request Body

ParameterTypeRequiredDescription
code string Required Authorization code from Identity Product callback (max 512 characters).
code_verifier string Required PKCE code verifier that must match the code_challenge sent to Identity Product. 43-128 characters, per RFC 7636.

Response (Existing User)

FieldTypeDescription
access_token string JWT access token (1 hour lifetime)
refresh_token string JWT refresh token (30 day lifetime)
user object User profile information
account object Account information

Response (New User)

FieldTypeDescription
access_token string Identity-only JWT (limited access)
refresh_token string Identity-only refresh token
user null null indicates registration required
account null null indicates registration required

Example

Request
bash
curl -X POST https://api.sparkvault.com/v1/auth/identity/token \
  -H "Content-Type: application/json" \
  -d '{
    "code": "auth_code_from_identity_product",
    "code_verifier": "your_pkce_code_verifier"
  }'
Response
json
{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "refresh_token": "eyJhbGciOiJSUzI1NiIs...",
    "user": {
      "user_id": "usr_abc123...",
      "email": "user@example.com",
      "name": "John Doe",
      "role": "admin"
    },
    "account": {
      "account_id": "acc_xyz789...",
      "organization_name": "Acme Corp",
      "status": "active"
    }
  }
}
POST /v1/auth/identity/verify

Directly verify an Identity Product JWT token without using the OIDC redirect flow. Useful for XHR-based authentication where redirect flows are not practical.

Request Body

ParameterTypeRequiredDescription
token string Required JWT token received from Identity Product verification

Response

FieldTypeDescription
access_token string JWT access token (1 hour lifetime)
refresh_token string JWT refresh token (30 day lifetime)
user object User profile (null if registration required)
account object Account information (null if registration required)

Example

Request
bash
curl -X POST https://api.sparkvault.com/v1/auth/identity/verify \
  -H "Content-Type: application/json" \
  -d '{"token": "eyJhbGciOiJFZDI1NTE5..."}'
Response
json
{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "refresh_token": "eyJhbGciOiJSUzI1NiIs...",
    "user": {
      "user_id": "usr_abc123...",
      "email": "user@example.com",
      "name": "John Doe",
      "role": "admin"
    },
    "account": {
      "account_id": "acc_xyz789...",
      "organization_name": "Acme Corp",
      "status": "active"
    }
  }
}
When to use this endpoint

Use this endpoint when you're using the Identity Product SDK in XHR mode (without redirects). The SDK will return a JWT token directly after verification, which you can exchange for SparkVault session tokens using this endpoint.

POST /v1/auth/complete-signup

Complete registration for new users. Requires an identity-only JWT (from token exchange with user: null). Creates the account and upgrades to full session tokens.

Request Body

ParameterTypeRequiredDescription
organization_name string Required Name of the organization/company (1-255 characters)
full_name string Optional User's display name (up to 255 characters)

Response

FieldTypeDescription
access_token string Full JWT access token
refresh_token string Full JWT refresh token
user object Created user profile
account object Created account object
Authentication Required

This endpoint requires an identity-only JWT in the Authorization header. The JWT proves email ownership via the Identity Product verification.

Claimed Domains

Signup returns 403 Forbidden if the email's domain is already claimed by another organization. The user must be invited by that organization's admin instead.

POST /v1/auth/refresh

Exchange a refresh token for a new access token and a new refresh token. Use this when your access token expires.

Request Body

ParameterTypeRequiredDescription
refresh_token string Required Valid refresh token

Response

FieldTypeDescription
access_token string New JWT access token
refresh_token string New rotated refresh token. Replace your stored token
token_type string Always "Bearer"
expires_in integer Token lifetime in seconds

Example

Request
bash
curl -X POST https://api.sparkvault.com/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJhbGciOiJSUzI1NiIs..."}'
Response
json
{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "refresh_token": "eyJhbGciOiJSUzI1NiIs...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}
Refresh Tokens Rotate on Every Use

Refresh tokens are one-time-use. Every call to /v1/auth/refresh revokes the presented token and returns a new refresh_token. Always replace your stored token with the one in the response. Reusing an already-rotated token fails with 401 AUTHENTICATION_ERROR; if two requests race with the same token, the loser fails with 401 TOKEN_REPLAY. In either case, discard stored tokens and sign the user in again.

POST /v1/auth/logout

Revoke a refresh token. Requires authentication. Returns 204 No Content on success.

Request Body

ParameterTypeRequiredDescription
refresh_token string Required Refresh token to revoke

Example

Request
bash
curl -X POST https://api.sparkvault.com/v1/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJhbGciOiJSUzI1NiIs..."}'
Response
text
(204 No Content)
POST /v1/auth/viewer-token

Generate a short-lived viewer token for cross-domain direct-access viewing on x.sv. Requires authentication. Takes no request body.

Response

FieldTypeDescription
viewer_token string Short-lived JWT for the x.sv viewer (5 minute lifetime)
expires_in integer Token lifetime in seconds, always 300

Vault Access Tokens (VAT)

Vault Access Tokens are special, short-lived tokens required for reading and writing data in encrypted vaults. They are obtained by "unsealing" a vault with its Vault Master Key (VMK).

Property Value
Header X-Vault-Access-Token
Lifetime 1 hour (default), up to 24 hours
Scope Single vault only
Revocation Automatic on expiry, or manual via seal operation
POST /v1/vaults/:id/unseal

Unseal a vault with its Vault Master Key to obtain a Vault Access Token.

Request Body

ParameterTypeRequiredDescription
vmk string Required The Vault Master Key. Also accepts a dvak_ token (Delegated Vault Access Key) in place of the raw VMK.
ttl_seconds integer Optional VAT lifetime in seconds (1-86400).Default: 3600

Response Fields

FieldTypeDescription
vat string The Vault Access Token (vat_...). Send it in the X-Vault-Access-Token header.
vault_id string The unsealed vault's id.
issued_at integer Issue time (Unix epoch seconds).
expires_at integer Expiration time (Unix epoch seconds).
ttl_seconds integer Effective VAT lifetime in seconds.
warning string Reminder to store the VAT securely.
bash Using a Vault Access Token
# First, unseal the vault to get a VAT
curl -X POST https://api.sparkvault.com/v1/vaults/vlt_abc123/unseal \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{"vmk": "YOUR_VAULT_MASTER_KEY"}'

# Then use the VAT for ingot operations
curl https://api.sparkvault.com/v1/vaults/vlt_abc123/ingots \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "X-Vault-Access-Token: vat_xyz789..."
VAT Best Practices
  • Obtain a VAT only when you need to access vault contents
  • Store VATs securely in memory, never persist to disk
  • VATs are vault-specific. Each vault requires its own VAT.
  • Consider sealing vaults when done to immediately invalidate VATs

Authentication Errors

Error Responses

StatusCodeDescription
400 VALIDATION_ERROR Missing or invalid request parameters
401 AUTHENTICATION_ERROR Invalid credentials, expired access token, invalid or revoked refresh token, or suspended account
401 TOKEN_REPLAY Refresh token was consumed by a concurrent rotation. Sign in again
403 FORBIDDEN Insufficient permissions: e.g. identity-only token on a protected endpoint (complete registration first), or admin role required
429 RATE_LIMIT_EXCEEDED Too many requests

Security Best Practices

API Keys

  • Generate separate API keys for each integration or service
  • Use descriptive names to identify key purpose
  • Rotate keys periodically (every 90 days recommended)
  • Revoke keys immediately if compromised
  • Never commit keys to version control. Use environment variables.

JWT Tokens

  • Store access tokens in memory only (not localStorage)
  • Implement automatic token refresh before expiry
  • Persist the rotated refresh token from every refresh response. The old one is immediately revoked
  • Clear tokens on logout and tab close
  • Handle 401 errors by redirecting to login

PKCE Security

  • Always use S256 code challenge method (never plain)
  • Generate cryptographically random code verifiers (32+ bytes)
  • Store PKCE parameters in sessionStorage (not localStorage)
  • Validate the state parameter to prevent CSRF attacks

General

  • Always use HTTPS. Never send credentials over plain HTTP.
  • Implement proper error handling for auth failures
  • Log authentication events for security monitoring
  • Use passkeys where possible for phishing resistance