# Secure Entropy: SparkVault API Reference

> Generate cryptographically secure random data backed by AWS KMS hardware security modules (FIPS 140-3 Level 3 validated, NIST SP800-90A CTR_DRBG with AES-256), XORed with a local CSPRNG for hybrid defense-in-depth.

Canonical: https://sparkvault.com/api/docs/entropy/ · OpenAPI: https://sparkvault.com/openapi.yaml

## Overview

The Secure Entropy API provides enterprise-grade, hardware-backed random number generation suitable for cryptographic operations. Unlike software-based PRNGs (which can be predictable if seeded improperly), every request is served by AWS KMS `GenerateRandom`, which draws from FIPS 140-3 Level 3 validated hardware security modules using a NIST SP800-90A CTR\_DRBG with AES-256, seeded from a 384-bit entropy source (these are platform properties of AWS KMS).

For defense-in-depth, the KMS output is XORed with an independent local CSPRNG before it is returned: the hybrid result is at least as random as the stronger of the two sources, so even if one source were compromised the output remains cryptographically secure. There is no software fallback. If the KMS hardware entropy source is unavailable, the request hard-fails rather than degrading to weaker entropy.

FIPS 140-3

Level 3 Validated HSMs

384-bit

Entropy Source

AES-256

CTR\_DRBG Algorithm

NIST

SP800-90A Compliant

> **Cryptographic Grade**
>
> This entropy source is suitable for generating encryption keys, session tokens, nonces, salts, and any other application requiring true cryptographic randomness. The underlying AWS KMS DRBG passes NIST statistical randomness tests and provides prediction resistance (guarantees of the AWS KMS platform), and the hybrid XOR construction adds an independent local entropy layer on top.

## API Reference

#### `POST /v1/entropy/generate`

Generate cryptographically secure random bytes in the specified format.

> **Authentication**
>
> This endpoint accepts standard SparkVault authentication: a session JWT via `Authorization: Bearer …` or an API key via the `X-API-Key` header (API keys are prefixed `sv_live_`). The examples below use API-key auth.

#### Request Body

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `format` | string | Optional | Output encoding format. See Format Options below for valid values.Default: `hex` |
| `num_bytes` | integer | Required | Number of random bytes to generate. Range: 1-1024 (1-512 for `alphanumeric`, `alphanumeric-mixed`, and `password`). For character-based formats, this is the output length in characters. For `uuid`, the value is still required and validated but the output always uses 16 bytes. |

#### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `value` | string | array | The generated random data in the requested format |
| `format` | string | The format used for encoding |
| `num_bytes` | integer | Number of raw random bytes actually generated. For `hex`, `base64`, `base64url`, `numeric`, and `bytes` this equals the requested value. For the character-set formats (`alphanumeric`, `alphanumeric-mixed`, `password`) it is the raw bytes consumed by rejection sampling (2x the requested length). Because the hardware draw is capped at 1024 raw bytes, character-set requests support at most 512 characters; larger values are rejected with `400 VALIDATION_ERROR`. For `uuid` it is always 16, regardless of the request. |
| `reference_id` | string | Unique reference ID for this request (for audit logging) |

## Format Options

| Format | Character Set | Use Case |
| --- | --- | --- |
| `hex` | 0-9, a-f | Encryption keys, debugging, hex-based systems |
| `base64` | A-Z, a-z, 0-9, +, / | General encoding, email-safe data |
| `base64url` | A-Z, a-z, 0-9, -, \_ | URLs, tokens, API keys, JWT |
| `alphanumeric` | A-Z, 0-9 | Case-insensitive codes, serial numbers |
| `alphanumeric-mixed` | A-Z, a-z, 0-9 | Case-sensitive codes, identifiers |
| `password` | A-Z, a-z, 0-9, !@#$%^&\*()\_+-=\[\]{}|;:,.<>? | Secure password generation |
| `numeric` | 0-9 | PINs, verification codes, OTPs |
| `uuid` | UUID v4 format | Unique identifiers, database keys |
| `bytes` | Raw byte array (JSON) | Direct cryptographic use, custom encoding |

## Examples

### Generate Hex-Encoded Random Data

```bash
curl -X POST https://api.sparkvault.com/v1/entropy/generate \
  -H "X-API-Key: sv_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "hex",
    "num_bytes": 32
  }'
```

```json
{
  "data": {
    "value": "a3f9b2c8d4e6f1a87b3c5d9e0f2a4b6c8d1e3f5a7b9c0d2e4f6a8b0c2d4e6f80",
    "format": "hex",
    "num_bytes": 32,
    "reference_id": "ent_a1b2c3d4"
  },
  "meta": {
    "api_version": "1.2.828",
    "response_ms": 42,
    "request_id": "9b2f6d1c-4e3a-4c8b-9f0d-2a7e5b1c8d3f",
    "timestamp": 1782864000
  }
}
```

### Generate a UUID

```bash
curl -X POST https://api.sparkvault.com/v1/entropy/generate \
  -H "X-API-Key: sv_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "uuid",
    "num_bytes": 16
  }'
```

```json
{
  "data": {
    "value": "550e8400-e29b-41d4-a716-446655440000",
    "format": "uuid",
    "num_bytes": 16,
    "reference_id": "ent_b2c3d4e5"
  },
  "meta": {
    "api_version": "1.2.828",
    "response_ms": 38,
    "request_id": "4c7a1e9d-2b5f-4d3a-8c6e-0f9b3a7d5e21",
    "timestamp": 1782864060
  }
}
```

### Generate a Secure Password

```bash
curl -X POST https://api.sparkvault.com/v1/entropy/generate \
  -H "X-API-Key: sv_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "password",
    "num_bytes": 24
  }'
```

```json
{
  "data": {
    "value": "Kx9!mP@qR2#vL5^nW8&jT3*b",
    "format": "password",
    "num_bytes": 48,
    "reference_id": "ent_c3d4e5f6"
  },
  "meta": {
    "api_version": "1.2.828",
    "response_ms": 35,
    "request_id": "7e3b9f5a-1d8c-4a2e-b6f4-5c0d2e9a1b7c",
    "timestamp": 1782864120
  }
}
```

> **Why num\_bytes is 48 here**
>
> Character-set formats (`alphanumeric`, `alphanumeric-mixed`, `password`) use rejection sampling to avoid modulo bias, so the service consumes 2x the requested bytes and the response echoes the raw bytes consumed. Because the hardware draw is capped at 1024 raw bytes, these formats support at most 512 characters per request. Larger values are rejected with `400 VALIDATION_ERROR`. The `value` is still exactly the requested length in characters (24 here).

### Generate a 6-Digit PIN

```bash
curl -X POST https://api.sparkvault.com/v1/entropy/generate \
  -H "X-API-Key: sv_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "numeric",
    "num_bytes": 6
  }'
```

```json
{
  "data": {
    "value": "847291",
    "format": "numeric",
    "num_bytes": 6,
    "reference_id": "ent_d4e5f6g7"
  },
  "meta": {
    "api_version": "1.2.828",
    "response_ms": 31,
    "request_id": "2a8d4c6f-9e1b-4f7a-a3c5-8b6e0d4f2a19",
    "timestamp": 1782864180
  }
}
```

## Language Examples

### JavaScript / Node.js

```javascript
const response = await fetch('https://api.sparkvault.com/v1/entropy/generate', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.SPARKVAULT_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    format: 'base64url',
    num_bytes: 32
  })
});

const result = await response.json();
const sessionToken = result.data.value;
console.log('Generated token:', sessionToken);
```

### Python

```python
import os
import requests

response = requests.post(
    'https://api.sparkvault.com/v1/entropy/generate',
    headers={
        'X-API-Key': os.environ['SPARKVAULT_API_KEY'],
        'Content-Type': 'application/json'
    },
    json={
        'format': 'hex',
        'num_bytes': 32
    }
)

result = response.json()
encryption_key = result['data']['value']
print(f"Generated key: {encryption_key}")
```

### Go

```go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
    "os"
)

func generateEntropy() (string, error) {
    payload := map[string]interface{}{
        "format":    "base64url",
        "num_bytes": 32,
    }
    body, _ := json.Marshal(payload)

    req, _ := http.NewRequest("POST",
        "https://api.sparkvault.com/v1/entropy/generate",
        bytes.NewBuffer(body))

    req.Header.Set("X-API-Key", os.Getenv("SPARKVAULT_API_KEY"))
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)

    data := result["data"].(map[string]interface{})
    return data["value"].(string), nil
}
```

## Error Responses

#### Error Responses

| Status | Code | Description |
| --- | --- | --- |
| 400 | `VALIDATION_ERROR` | Invalid format or num\_bytes parameter. Check that format is a valid option and num\_bytes is between 1 and 1024. |
| 401 | `AUTHENTICATION_ERROR` | Missing or invalid credentials. Provide a session JWT or a valid X-API-Key header. |
| 402 | `PLAN_REQUIRED` | An active subscription is required for this operation. Subscribe to continue. |
| 402 | `QUOTA_EXCEEDED` | The account bandwidth pool is exhausted (details include `resource: bandwidth`). Add a capacity block to continue. |
| 429 | `RATE_LIMIT_EXCEEDED` | Too many requests. Wait and retry. Check Retry-After header. |
| 500 | `CRYPTOGRAPHIC_ERROR` | Entropy generation failed because the KMS hardware entropy source was unavailable. There is no software fallback. This is rare. Retry the request. |

A `503` response can only originate from upstream infrastructure, not from the API itself; such responses do not carry the SparkVault error envelope or an error `code`. Retry with exponential backoff.

## Usage

| Operation | Usage |
| --- | --- |
| Entropy Generation (any format, any size) | Draws pooled bandwidth (included with subscription) |

Entropy generation is covered by your seat subscription and tracked as usage. Each customer call also draws the account bandwidth pool by its request plus response size; there is no per-request charge. Requests are subject to your plan's rate limits regardless of the number of bytes requested (up to the 1024 byte limit). When the bandwidth pool is exhausted, the call is refused with `402 QUOTA_EXCEEDED`; extend the pool with a capacity block to continue.

## Try It

You can test secure entropy generation interactively in the SparkVault dashboard. Open the Entropy panel from the dashboard shortcut, the command palette, or the console footer.

[Open Dashboard](https://app.sparkvault.com/entropy)
