SparkVault API v1

Quick Start

Every call is plain JSON over HTTPS, authenticated with an API key: grab yours, then seal your first secret. It burns the moment it's read:

bash Your first request
curl https://api.sparkvault.com/v1/sparks \
  -H "X-API-Key: sv_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"payload": "the launch code is 793-alpha", "ttl_minutes": 60}'

The response's data.spark_id is the one-time handle to your secret: read it once and it's gone. The Authentication and Response Format sections below cover the envelope, or skip the plumbing and start from the JavaScript SDK.

Explore the API

Base URL

All API requests should be made to the following base URL:

text
https://api.sparkvault.com/v1
HTTPS Required

All API requests must be made over HTTPS. Requests over plain HTTP will be rejected.

Authentication

SparkVault supports two authentication methods:

  • API Keys: Best for server-to-server integrations and automation. Keys are prefixed sv_live_ (production) or sv_test_ (test).
  • JWT Tokens: Best for user-facing applications with session management

Include your API key in the X-API-Key header:

bash
curl https://api.sparkvault.com/v1/sparks \
  -H "X-API-Key: sv_live_YOUR_API_KEY"
Vault Access Tokens

Vault operations additionally require an X-Vault-Access-Token: {vat} header, issued when you unseal the vault. See the Vaults API for details.

See the Authentication guide for complete details.

Response Format

All successful responses follow a consistent JSON structure with data and meta fields:

json
{
  "data": {
    "spark_id": "spk_abc123...",
    "account_id": "acc_def456...",
    "content_type": "text/plain",
    "size_bytes": 1024,
    "status": "active",
    "created_at": 1702000000,
    "expires_at": 1702003600,
    "burned_at": null,
    "time_remaining": 3600
  },
  "meta": {
    "api_version": "1.x.y",
    "request_id": "req_xyz789...",
    "response_ms": 42,
    "timestamp": 1702000000,
    "pools": {
      "storage": { "used_gb": 12.5, "limit_gb": 100, "pct": 0.125, "state": "ok" },
      "bandwidth": { "used_gb": 3.25, "limit_gb": 100, "pct": 0.0325, "state": "ok", "cycle_resets_at": 1704067200 },
      "identity": { "used": 15, "limit": 500, "pct": 0.03, "state": "ok" }
    },
    "quota": {
      "limit": 300,
      "used": 15,
      "remaining": 285,
      "resets_at": 1702000060
    }
  }
}

Meta Fields

  • api_version: Semantic version of the deployed API release
  • request_id: Unique identifier for this request (useful for support)
  • response_ms: Server processing time in milliseconds
  • timestamp: Unix timestamp when response was generated
  • pools: Pooled-capacity status for your subscription's storage, bandwidth, and identity pools, attached only on authenticated, successful responses to billable routes. Each pool reports usage against its limit, a utilization fraction (pct), and a state of ok | notice | warning | exhausted. This is usage tracking, not a spendable balance.
  • quota: Rate limit status for your account (included on authenticated responses with status below 400)

Error Handling

Errors return a consistent structure with machine-readable codes and human-friendly messages:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The 'name' field is required",
    "details": {
      "field": "name",
      "reason": "missing"
    }
  },
  "meta": {
    "api_version": "1.x.y",
    "request_id": "req_xyz789..."
  }
}

Common Error Codes

Status Code Description
400 VALIDATION_ERROR Invalid request parameters or body
401 AUTHENTICATION_ERROR Missing or invalid authentication credentials
401 UNAUTHORIZED Presented token, grant, or key is invalid, expired, or revoked
402 PLAN_REQUIRED An active subscription is required for this operation
402 QUOTA_EXCEEDED A pooled-capacity or seat limit is reached (details.resource is storage, bandwidth, seats, or identity). details.action_required indicates which add-on or seat amendment unblocks you
403 FORBIDDEN Valid credentials but insufficient permissions
404 NOT_FOUND Requested resource does not exist
404 UPLOAD_SOURCE_DISABLED Vault exists but the requested upload source (portal or embedded widget) is not enabled on it
409 CONFLICT Resource conflict (e.g., duplicate name)
412 PRECONDITION_FAILED A required precondition was not met (e.g., invalid VMK)
413 PAYLOAD_TOO_LARGE Request body or upload exceeds the size limit
429 RATE_LIMIT_EXCEEDED Too many requests, slow down
500 INTERNAL_ERROR Unexpected server error (contact support)

Rate Limiting

API requests are rate limited to 300 requests per minute per account, measured in 60-second windows. The current rate limit status is included in the meta.quota field of every authenticated response with a status below 400.

json
{
  "meta": {
    "quota": {
      "limit": 300,
      "used": 42,
      "remaining": 258,
      "resets_at": 1702000060
    }
  }
}
Rate Limit Exceeded

When you exceed the rate limit, requests return 429 Too Many Requests with a Retry-After header set to the number of seconds until the window resets. The error's details include limit, used, and resets_at so you know when your quota resets.

Pagination

List endpoints use cursor-based pagination with limit and cursor query parameters. Cursors are signed per account and bound to the resource they page over. A tampered, cross-account, or cross-resource cursor returns 400 VALIDATION_ERROR.

bash
curl "https://api.sparkvault.com/v1/sparks?limit=20&cursor=eyJzcGFya19pZCI6..." \
  -H "X-API-Key: sv_live_YOUR_API_KEY"

Paginated responses include the items, a count, and cursor metadata:

json
{
  "data": {
    "sparks": [...],
    "count": 20,
    "has_more": true,
    "next_cursor": "eyJzcGFya19pZCI6..."
  }
}

next_cursor is present only when has_more is true. Pass it back as the cursor parameter to fetch the next page. A total field appears only on endpoints that compute one. Default and maximum limit vary per endpoint (default 25-100, max 100-500); check each endpoint's reference page for exact values. For example, /sparks and /vaults both default to 100 (max 500).

Security

Post-Quantum Encryption

SparkVault uses ML-KEM-1024 (CRYSTALS-Kyber) for key encapsulation and AES-256-GCM for data encryption. This provides protection against both classical and quantum computer attacks.

Zero-Knowledge Architecture

SparkVault is designed so that we cannot access your encrypted data, even with full system access. Our multi-key architecture uses three types of master keys:

  • SparkVault Master Key (SVMK): SparkVault's system-wide software ML-KEM-1024 keypair, stored in AWS SSM Parameter Store
  • Account Master Key (AMK): Your account's unique HMAC key managed in AWS KMS (FIPS 140-3 validated)
  • Vault Master Key (VMK): A per-vault key that you generate and control

Different features require different combinations of these keys:

  • Sparks (Double Zero-Trust): Requires both the SVMK and your AMK
  • Vaults (Triple Zero-Trust): Requires the SVMK, AMK, and your VMK

Key Management

Self-managed Vault Master Keys (VMKs) are generated client-side and are never stored by SparkVault. If you lose a self-managed VMK, the data in that vault is permanently unrecoverable, so always store it in a secure password manager or key management system. Vaults using the Hosted VMK option instead store the VMK KMS-wrapped (a per-vault key under the HVMK root KEK), which lets SparkVault derive vault access server-side for features like public sharing.

Client Libraries

Official SDKs handle authentication, encryption, and resumable transfers for you:

  • JavaScript SDK: @sparkvault/sdk-js for browsers and Node.js
  • Mobile SDK: @sparkvault/sdk-mobile for React Native and Expo

For other languages, any HTTP client works: the API is plain JSON over HTTPS.

Support

Need help? Include the request_id from the response when contacting support. This helps us quickly locate your request in our logs.

  • Email: support@sparkvault.com