Key-Value API Documentation

Secure JSON storage API with automatic time-series classification, real-time visualization dashboards, and public sharing capabilities. Features persistent rate limiting, optional authentication, and IoT sensor data support.

Base URL
https://key-value.co

Authentication

Anonymous requests are supported, but authenticated users receive higher rate limits and dashboard visibility.

  • Bearer token: Send `Authorization: Bearer <token>` where the token comes from the `/api/auth/login` flow.
  • Anonymous: Anonymous users must pass the Cloudflare Turnstile token when bot protection is enabled. Rate limits are stricter for anonymous use.

Common Errors

  • 400Bad Request

    Missing required headers, invalid JSON payload, or failed verification challenge.

  • 401Unauthorized

    Bearer token is missing or invalid when accessing authenticated-only endpoints.

  • 404Not Found

    Token does not have any stored data (retrieve/delete).

  • 410Gone

    Token has expired because the TTL elapsed.

  • 413Payload Too Large

    Stored JSON exceeds 100KB for the free tier.

  • 429Too Many Requests

    Rate limits are exceeded for the IP address or token.

  • 500Internal Server Error

    Unexpected errors communicating with downstream services.

Rate limits

ScopeAnonymousFreeProEnterprise
generate
Token creation endpoints
5 requests per hour per IP address (Turnstile enforced when enabled).POST: unlimited for authenticated users. Anonymous callers (and all GET requests) are limited to 5 per hour per IP.
store
Writes and deletes share the same quota.
10 requests per minute per IP address.20 requests per minute per token.1,000 requests per minute per token.10,000 requests per minute per token.
retrieve
Reads per token.
Same as free tier when unauthenticated.100 requests per hour per token.10,000 requests per hour per token.100,000 requests per hour per token.
history
Historical event lookups per token.
Same as free tier when unauthenticated.100 requests per hour per token.10,000 requests per hour per token.100,000 requests per hour per token.
tokenReveals
Reveal operations for a stored token (per account).
10 per day.100 per day.1000 per day.
tokenRotations
Token rotation actions (per account).
3 per day.25 per day.100 per day.

Endpoints

POST/api/generate
Tokens

Generate Token (recommended)

Creates a new 5-word token. Anonymous callers must include a Cloudflare Turnstile token when bot protection is enabled.

Authentication

optional

Rate limit

Anonymous callers: 5 tokens per hour per IP. Authenticated POST requests skip this limit but still bypass Turnstile.

Notes

  • Tokens are generated from a curated dictionary of 7,776 words and hashed before storage.
  • If Turnstile is not configured, the service allows anonymous requests without verification.

Headers

  • Content-Type (optional)
    Must be `application/json` when providing a body.
    application/json
  • Authorization (optional)
    Bearer token obtained after signing in. Bypasses bot protection and rate limits associated with anonymous usage.
    Bearer eyJhbGciOi...

Request body

Provide the Turnstile response token when the requester is anonymous and bot protection is enabled. Authenticated requests can send an empty object.

{
  "turnstileToken": "1x00000000000000000000AA"
}

Responses

  • 200Token successfully created.
    {
      "success": true,
      "token": "capable-germinate-disbelief-survival-quantum"
    }
  • 400Missing or invalid Turnstile token while unauthenticated.
    {
      "error": "Please complete the verification"
    }
  • 429Rate limit exceeded for anonymous requests.
    {
      "error": "Rate limit exceeded. Try again in 15 minutes."
    }

Examples

cURL
curl -X POST https://key-value.co/api/generate \
  -H "Content-Type: application/json" \
  -d '{"turnstileToken": "1x00000000000000000000AA"}'
GET/api/history
Data

List token events

Returns the append-only event history for a token, ordered from newest to oldest.

Authentication

optional

Rate limit

Same as retrieve (per token, tier-based).

Notes

  • Anonymous callers inherit the free-tier quota.
  • Use the `before` cursor to paginate backwards through history.
  • Classified metrics (numeric/text) are included when available.

Headers

  • X-KV-Token
    Token returned by `/api/generate`.
    capable-germinate-disbelief-survival-quantum

Query parameters

  • limit (optional)
    Maximum number of events to return (default 50, max 200).
    50
  • before (optional)
    Only return events with a sequence number lower than the provided value (useful for pagination).
    125
  • since (optional)
    Only return events created on or after this ISO timestamp.
    2025-01-10T12:00:00Z
  • type (optional)
    Filter by classified event type (e.g., `temperature`).
    temperature

Responses

  • 200Events returned successfully.
    {
      "success": true,
      "events": [
        {
          "seq": 5,
          "created_at": "2025-01-10T12:01:00Z",
          "expires_at": null,
          "classified_type": null,
          "payload": {
            "type": "store",
            "data": {
              "status": "online"
            }
          }
        }
      ],
      "pagination": {
        "limit": 50,
        "before": null,
        "since": null,
        "has_more": false
      }
    }
  • 400Invalid pagination parameters.
    {
      "error": "limit must be a positive integer"
    }
  • 429Per-token quota exceeded.
    {
      "error": "Token rate limit exceeded. Try again in 60 seconds."
    }

Examples

cURL
curl "https://key-value.co/api/history?limit=20" \
  -H "X-KV-Token: capable-germinate-disbelief-survival-quantum"
GET/api/generate
Tokens

Generate Token (GET)

Alternative to the POST endpoint. Anonymous requests must provide the Turnstile token via query string.

Authentication

optional

Notes

  • Returns `user` metadata when a valid bearer token is provided.
  • Rate limiting applies to all GET callers (5 per hour per IP).
  • Prefer the POST endpoint for SDK usage; GET is provided for quick manual testing.

Headers

  • Authorization (optional)
    Optional bearer token to bypass Turnstile checks.
    Bearer eyJhbGciOi...

Query parameters

  • turnstileToken (optional)
    Turnstile response token for anonymous requests.
    1x00000000000000000000AA

Responses

  • 200Token created successfully.
    {
      "success": true,
      "token": "capable-germinate-disbelief-survival-quantum",
      "user": {
        "email": "user@example.com",
        "tier": "free"
      }
    }
  • 400Missing or invalid Turnstile token for anonymous callers.
    {
      "error": "Please complete the verification"
    }
  • 429Too many tokens generated within the same window.
    {
      "error": "Rate limit exceeded. Try again in 15 minutes."
    }
POST/api/store
Data

Store JSON data

Creates or replaces JSON data associated with a token. Payloads above the per-tier quota are rejected.

Authentication

optional

Rate limit

IP based: 10 writes per minute for anonymous usage. Token based: 20 writes per minute for free tier, higher for paid tiers.

Notes

  • Tokens are hashed before storage; authenticated users have the raw token saved to their account for later reference.
  • Payload size is calculated using UTF-8 byte length. Free tier limit is 100KB.
  • Optional TTL is capped at 30 days (2,592,000 seconds).
  • Each store operation creates a new event in the time-series ledger. The version number increments with each write.
  • Use the version field for optimistic concurrency control with PATCH operations.
  • Data is automatically classified for visualization: numeric values are extracted from recognized patterns (temperature, humidity, pressure, etc.) and made available for time-series charts.
  • Supported classification patterns: temperature/temp/t, humidity/hum/h, pressure/press/p, voltage/v/volts, current/amps/a, battery/bat, rssi/signal, distance/dist/d, speed/velocity, count/counter.
  • The debug.classified_type and debug.numeric_value fields show the extracted data for visualization purposes.

Headers

  • Content-Type
    Must be `application/json`.
    application/json
  • X-KV-Token
    Token returned by `/api/generate`.
    capable-germinate-disbelief-survival-quantum
  • Authorization (optional)
    Optional bearer token. Authenticated requests can view tokens in the dashboard and inherit higher rate limits.
    Bearer eyJhbGciOi...

Request body

JSON payload to store. `data` is required. Optional `ttl` (in seconds) sets an expiration up to 30 days.

{
  "data": {
    "ip": "1.2.3.4",
    "status": "online"
  },
  "ttl": 3600
}

Responses

  • 200Data stored successfully. Response includes automatic data classification results.
    {
      "success": true,
      "message": "Data stored successfully",
      "size": 1234,
      "tier": "free",
      "version": 1,
      "updated_at": "2025-01-10T12:00:00Z",
      "expires_at": null,
      "debug": {
        "classified_type": "temperature",
        "numeric_value": 25.5
      }
    }
  • 400Missing token header or data payload.
    {
      "error": "X-KV-Token header is required"
    }
  • 413Payload exceeds the 100KB free tier limit.
    {
      "error": "Data too large. Max size is 100KB"
    }

Examples

Node.js (fetch)
await fetch('https://key-value.co/api/store', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-KV-Token': token
  },
  body: JSON.stringify({
    data: { status: 'online' },
    ttl: 3600
  })
})
GET/api/retrieve
Data

Retrieve stored data

Fetches the JSON payload associated with a token. Returns metadata about the most recent update.

Authentication

optional

Rate limit

Token based: 100 reads per hour on the free tier. Authenticated paid tiers receive higher quotas.

Notes

  • Expired tokens are removed immediately and return HTTP 410.
  • Retrieves the latest snapshot from the time-series event log.
  • The version field represents the event sequence number and can be used for PATCH operations.

Headers

  • X-KV-Token
    Token returned by `/api/generate`.
    capable-germinate-disbelief-survival-quantum
  • Authorization (optional)
    Optional bearer token. Authenticated requests inherit higher rate limits.
    Bearer eyJhbGciOi...

Responses

  • 200Data found.
    {
      "success": true,
      "data": {
        "status": "online"
      },
      "updated_at": "2025-01-10T12:00:00Z",
      "version": 1,
      "expires_at": null
    }
  • 404Requested token has not stored any data.
    {
      "error": "No data found for this token"
    }
  • 410Data previously existed but the token has expired.
    {
      "error": "Token has expired"
    }

Examples

Python (requests)
response = requests.get(
    'https://key-value.co/api/retrieve',
    headers={'X-KV-Token': token}
)
data = response.json()
DELETE/api/delete
Data

Delete stored data

Removes the JSON payload associated with a token.

Authentication

optional

Rate limit

Shares the write quota: 20 deletes per minute for free tier, higher for paid tiers.

Notes

  • Deletes are idempotent; repeated calls after deletion will return HTTP 404.

Headers

  • X-KV-Token
    Token whose data should be removed.
    capable-germinate-disbelief-survival-quantum
  • Authorization (optional)
    Optional bearer token for elevated rate limits.
    Bearer eyJhbGciOi...

Responses

  • 200Deletion succeeded.
    {
      "success": true,
      "message": "Data deleted successfully"
    }
  • 404Token has no associated data.
    {
      "error": "No data found for this token"
    }
POST/api/user/tokens/reveal
Tokens

Reveal token

Decrypts and returns the original token phrase for an authenticated owner.

Authentication

required

Rate limit

Owner-only endpoint; low daily quota per account.

Notes

  • Reveal attempts are audited and should be gated by re-authentication in the UI.

Headers

  • Authorization
    Bearer token obtained after signing in.
    Bearer eyJhbGciOi...

Request body

Specify the token hash you want to reveal.

{
  "token_hash": "5cb13f8df4aa2fa8cf6c4ac1ec23c4c90d7710dfae4d0c6b67d8b4b5bcc49c23"
}

Responses

  • 200Token revealed.
    {
      "success": true,
      "token": "example-token-phrase"
    }
  • 404Token not found or not owned by caller.
    {
      "error": "Token not found"
    }
POST/api/user/tokens/rotate
Tokens

Rotate token

Generates a new memorable token, re-keys history, and retires the previous token phrase.

Authentication

required

Rate limit

Low daily quota per account (owner only).

Notes

  • All dependent tables (events, snapshots, cohorts) are re-keyed automatically.
  • The response contains the new token only once—clients must store it immediately.

Headers

  • Authorization
    Bearer token obtained after signing in.
    Bearer eyJhbGciOi...

Request body

Specify the token hash you want to rotate.

{
  "token_hash": "5cb13f8df4aa2fa8cf6c4ac1ec23c4c90d7710dfae4d0c6b67d8b4b5bcc49c23"
}

Responses

  • 200Rotation succeeded. The new token is returned once.
    {
      "success": true,
      "token": "example-rotated-token"
    }
  • 404Token not found or not owned by caller.
    {
      "error": "Token not found"
    }
POST/api/cohorts
Cohorts

Create Token Cohort

Creates a new cohort for organizing tokens into hierarchical groups. The creator automatically becomes the owner.

Authentication

required

Rate limit

Standard account limits.

Request body

Cohort details

{
  "name": "Production API Keys",
  "description": "All tokens used in production environments"
}

Responses

  • 200Cohort created successfully.
    {
      "success": true,
      "cohort": {
        "id": "cohort-abc123",
        "name": "Production API Keys",
        "description": "All tokens used in production environments",
        "created_at": "2025-10-18T08:00:00Z",
        "updated_at": "2025-10-18T08:00:00Z"
      }
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
GET/api/cohorts
Cohorts

List Token Cohorts

Lists all cohorts the authenticated user has access to (owner, editor, or viewer).

Authentication

required

Rate limit

Standard account limits.

Responses

  • 200List of accessible cohorts.
    {
      "success": true,
      "cohorts": [
        {
          "id": "cohort-abc123",
          "name": "Production API Keys",
          "description": "All tokens used in production environments",
          "role": "owner",
          "created_at": "2025-10-18T08:00:00Z",
          "token_count": 5
        }
      ]
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
DELETE/api/cohorts
Cohorts

Delete Token Cohort

Deletes a cohort. Only owners can delete cohorts. Tokens in the cohort are NOT deleted, only the grouping is removed.

Authentication

required

Rate limit

Standard account limits.

Notes

  • Deleting a cohort does NOT delete the tokens in it.
  • All child cohorts and member relationships are also removed.

Request body

Cohort to delete

{
  "cohortId": "cohort-abc123"
}

Responses

  • 200Cohort deleted successfully.
    {
      "success": true,
      "message": "Cohort deleted"
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Only cohort owners can delete cohorts.
    {
      "error": "Only cohort owners can delete cohorts"
    }
POST/api/cohorts/[cohortId]/tokens
Cohorts

Add Token to Cohort

Adds a token to a cohort. Tokens can only be added to leaf cohorts (cohorts without child cohorts). Requires owner or editor role.

Authentication

required

Rate limit

Standard account limits.

Notes

  • You can only add tokens you own.
  • Tokens can exist in multiple cohorts simultaneously.
  • Cohorts can contain either tokens OR child cohorts, not both.

Request body

Token hash to add

{
  "token_hash": "abc123def456..."
}

Responses

  • 200Token added to cohort successfully.
    {
      "success": true,
      "message": "Token added to cohort"
    }
  • 400Cannot add tokens to cohorts with child cohorts.
    {
      "error": "Cannot add tokens to a cohort that has child cohorts. Tokens can only be in leaf nodes."
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Insufficient permissions or token not owned by user.
    {
      "error": "Forbidden"
    }
  • 409Token already in cohort.
    {
      "error": "Token already in cohort"
    }
GET/api/cohorts/[cohortId]/tokens
Cohorts

List Tokens in Cohort

Lists all tokens in a cohort. Requires viewer, editor, or owner role.

Authentication

required

Rate limit

Standard account limits.

Responses

  • 200List of tokens in the cohort.
    {
      "success": true,
      "tokens": [
        {
          "token_hash": "abc123def456...",
          "description": "Production API key",
          "created_at": "2025-10-18T08:00:00Z"
        }
      ]
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Insufficient permissions.
    {
      "error": "Forbidden"
    }
DELETE/api/cohorts/[cohortId]/tokens
Cohorts

Remove Token from Cohort

Removes a token from a cohort. The token itself is NOT deleted. Requires owner or editor role.

Authentication

required

Rate limit

Standard account limits.

Notes

  • Removing a token from a cohort does NOT delete the token.
  • The token remains accessible from the dashboard.

Request body

Token hash to remove

{
  "token_hash": "abc123def456..."
}

Responses

  • 200Token removed from cohort successfully.
    {
      "success": true,
      "message": "Token removed from cohort"
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Insufficient permissions.
    {
      "error": "Forbidden"
    }
  • 404Token not found in cohort.
    {
      "error": "Token not found in cohort"
    }
POST/api/cohorts/[cohortId]/cohorts
Cohorts

Add Child Cohort

Makes one cohort a child of another, creating a hierarchy. Parent cohorts cannot contain tokens (only child cohorts). Requires owner role on both cohorts.

Authentication

required

Rate limit

Standard account limits.

Notes

  • You must be the owner of both the parent and child cohort.
  • Cohorts can contain either tokens OR child cohorts, not both.
  • Cycles are prevented (e.g., A cannot be parent of B if B is already parent of A).

Request body

Child cohort ID

{
  "childId": "cohort-child123"
}

Responses

  • 200Child cohort attached successfully.
    {
      "success": true,
      "message": "Cohort attached successfully"
    }
  • 400Cannot add child cohorts to cohorts with tokens, or would create a cycle.
    {
      "error": "Cannot add child cohorts to a cohort that contains tokens. Tokens must be in leaf nodes only."
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Must own both parent and child cohorts.
    {
      "error": "Forbidden"
    }
  • 409Cohort already attached.
    {
      "error": "Cohort already attached"
    }
GET/api/cohorts/[cohortId]/cohorts
Cohorts

List Child Cohorts

Lists all child cohorts of a cohort. Requires viewer, editor, or owner role.

Authentication

required

Rate limit

Standard account limits.

Responses

  • 200List of child cohorts.
    {
      "success": true,
      "cohorts": [
        {
          "id": "cohort-child123",
          "name": "US-East Region",
          "description": "Tokens for US East region",
          "created_at": "2025-10-18T08:00:00Z",
          "added_at": "2025-10-18T09:00:00Z"
        }
      ]
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Insufficient permissions.
    {
      "error": "Forbidden"
    }
DELETE/api/cohorts/[cohortId]/cohorts
Cohorts

Remove Child Cohort

Removes a child cohort relationship. The child cohort itself is NOT deleted. Requires owner role.

Authentication

required

Rate limit

Standard account limits.

Notes

  • Detaching a child cohort does NOT delete the child cohort.
  • The child cohort becomes a root-level cohort again.

Request body

Child cohort ID to detach

{
  "childId": "cohort-child123"
}

Responses

  • 200Child cohort detached successfully.
    {
      "success": true,
      "message": "Cohort detached successfully"
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Insufficient permissions.
    {
      "error": "Forbidden"
    }
  • 404Relation not found.
    {
      "error": "Relation not found"
    }
POST/api/cohorts/[cohortId]/members
Cohorts

Add Member to Cohort

Adds a user to a cohort with a specified role (owner, editor, or viewer). Requires owner role.

Authentication

required

Rate limit

Standard account limits.

Notes

  • owner: Full control (can add/remove members, tokens, child cohorts, delete cohort)
  • editor: Can add/remove tokens but cannot manage members or cohort hierarchy
  • viewer: Read-only access to cohort and its tokens

Request body

Member details

{
  "email": "colleague@example.com",
  "role": "editor"
}

Responses

  • 200Member added successfully.
    {
      "success": true,
      "message": "Member added"
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Only owners can add members.
    {
      "error": "Forbidden"
    }
  • 404User not found.
    {
      "error": "User not found"
    }
GET/api/cohorts/[cohortId]/members
Cohorts

List Cohort Members

Lists all members of a cohort with their roles. Requires viewer, editor, or owner role.

Authentication

required

Rate limit

Standard account limits.

Responses

  • 200List of cohort members.
    {
      "success": true,
      "members": [
        {
          "user_id": "user-123",
          "email": "colleague@example.com",
          "role": "editor",
          "added_at": "2025-10-18T08:00:00Z"
        }
      ]
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Insufficient permissions.
    {
      "error": "Forbidden"
    }
PATCH/api/cohorts/[cohortId]/members
Cohorts

Update Member Role

Updates a member's role in the cohort. Requires owner role.

Authentication

required

Rate limit

Standard account limits.

Request body

Member update details

{
  "userId": "user-123",
  "role": "viewer"
}

Responses

  • 200Member role updated successfully.
    {
      "success": true,
      "message": "Member updated"
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Only owners can update member roles.
    {
      "error": "Forbidden"
    }
  • 404Member not found.
    {
      "error": "Member not found"
    }
DELETE/api/cohorts/[cohortId]/members
Cohorts

Remove Member from Cohort

Removes a member from the cohort. Owners cannot remove themselves. Requires owner role.

Authentication

required

Rate limit

Standard account limits.

Request body

User ID to remove

{
  "userId": "user-123"
}

Responses

  • 200Member removed successfully.
    {
      "success": true,
      "message": "Member removed"
    }
  • 400Owners cannot remove themselves.
    {
      "error": "Owners cannot remove themselves"
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 403Only owners can remove members.
    {
      "error": "Forbidden"
    }
  • 404Member not found.
    {
      "error": "Member not found"
    }
POST/api/user/tokens/history
DataTime-Series

Get Token Event History

Retrieves time-series events for a token, including automatic classification data for visualization. Returns up to 200 events in reverse chronological order.

Authentication

required

Rate limit

Token based: No strict rate limit, designed for dashboard usage.

Notes

  • Events are returned in reverse chronological order (newest first).
  • The numeric_value and classified_type fields enable automatic visualization in dashboards.
  • Pagination is supported via the before parameter (use the seq from the last event).
  • Limit defaults to 20, maximum is 200 events per request.

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...
  • Content-Type
    Must be `application/json`.
    application/json

Request body

Request parameters for filtering event history.

{
  "token_hash": "a1b2c3d4...",
  "limit": 100
}

Responses

  • 200Event history returned successfully.
    {
      "success": true,
      "events": [
        {
          "seq": 5,
          "created_at": "2025-01-10T12:05:00Z",
          "payload": {
            "type": "store",
            "data": {
              "temperature": 25.5,
              "humidity": 60
            }
          },
          "classified_type": "temperature",
          "numeric_value": 25.5,
          "text_value": null,
          "confidence": 0.9,
          "expires_at": null
        },
        {
          "seq": 4,
          "created_at": "2025-01-10T12:04:00Z",
          "payload": {
            "type": "store",
            "data": {
              "temperature": 24.8,
              "humidity": 62
            }
          },
          "classified_type": "temperature",
          "numeric_value": 24.8,
          "text_value": null,
          "confidence": 0.9,
          "expires_at": null
        }
      ]
    }
  • 401Authentication required.
    {
      "error": "Authentication required"
    }
  • 404Token not found or not owned by user.
    {
      "error": "Token not found"
    }
POST/api/dashboards
Visualization

Create Dashboard

Creates a new shareable dashboard for visualizing token data with charts, stats, and tables.

Authentication

required

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...
  • Content-Type
    Must be `application/json`.
    application/json

Request body

Dashboard configuration.

{
  "name": "Temperature Monitor",
  "description": "Real-time temperature and humidity tracking"
}

Responses

  • 200Dashboard created successfully.
    {
      "success": true,
      "dashboard": {
        "id": "abc123",
        "name": "Temperature Monitor",
        "description": "Real-time temperature and humidity tracking",
        "config": {
          "layout": {
            "cols": 12
          },
          "panels": [],
          "refreshInterval": 30000
        },
        "data_sources": [],
        "created_at": "2025-01-10T12:00:00Z"
      }
    }
GET/api/dashboards
Visualization

List Dashboards

Lists all dashboards owned by the authenticated user.

Authentication

required

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...

Responses

  • 200Dashboards retrieved successfully.
    {
      "success": true,
      "dashboards": [
        {
          "id": "abc123",
          "name": "Temperature Monitor",
          "description": "Real-time temperature tracking",
          "created_at": "2025-01-10T12:00:00Z",
          "updated_at": "2025-01-10T12:30:00Z"
        }
      ]
    }
GET/api/dashboards/[id]
Visualization

Get Dashboard

Retrieves a specific dashboard configuration including all panels and data sources.

Authentication

required

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...

Responses

  • 200Dashboard retrieved successfully.
    {
      "success": true,
      "dashboard": {
        "id": "abc123",
        "name": "Temperature Monitor",
        "config": {
          "layout": {
            "cols": 24
          },
          "panels": [
            {
              "id": "1",
              "type": "timeseries",
              "title": "Temperature Over Time",
              "dataSource": "token_hash_123",
              "dataSourceType": "token",
              "x": 0,
              "y": 0,
              "width": 24,
              "height": 12,
              "yAxisLabel": "Temperature (°C)"
            }
          ],
          "refreshInterval": 30000
        },
        "data_sources": [
          {
            "type": "token",
            "tokenHash": "token_hash_123"
          }
        ]
      }
    }
PATCH/api/dashboards/[id]
Visualization

Update Dashboard

Updates a dashboard configuration with new panels, layout, or data sources.

Authentication

required

Notes

  • Panel types: timeseries (line charts), stat (single value display), table (data grid).
  • Uses Grafana-style 24-column grid with explicit positioning.
  • Panel position: x (column 0-23), y (row 0+).
  • Panel size: width (1-24 columns, 24=full width), height (grid rows, each row=30px).
  • Example: x=0, y=0, width=24, height=12 creates a full-width 360px panel at the top.
  • Data sources can be individual tokens or cohorts (multiple tokens).

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...
  • Content-Type
    Must be `application/json`.
    application/json

Request body

Updated dashboard configuration.

{
  "config": {
    "layout": {
      "cols": 24
    },
    "panels": [
      {
        "id": "1",
        "type": "timeseries",
        "title": "Temperature",
        "dataSource": "token_hash",
        "dataSourceType": "token",
        "x": 0,
        "y": 0,
        "width": 16,
        "height": 12
      },
      {
        "id": "2",
        "type": "stat",
        "title": "Current Temperature",
        "dataSource": "token_hash",
        "dataSourceType": "token",
        "x": 16,
        "y": 0,
        "width": 8,
        "height": 6,
        "unit": "°C"
      }
    ]
  },
  "dataSources": [
    {
      "type": "token",
      "tokenHash": "abc123..."
    }
  ]
}

Responses

  • 200Dashboard updated successfully.
    {
      "success": true
    }
DELETE/api/dashboards/[id]
Visualization

Delete Dashboard

Permanently deletes a dashboard and all its share links.

Authentication

required

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...

Responses

  • 200Dashboard deleted successfully.
    {
      "success": true
    }
POST/api/dashboards/[id]/share
VisualizationSharing

Create Share Link

Generates a public shareable link or embed code for a dashboard. Supports password protection.

Authentication

required

Notes

  • Public shares are accessible to anyone with the link.
  • Password-protected shares require password entry before viewing.
  • Embed codes can be used in <iframe> tags on external websites.
  • Share links auto-refresh data every 30 seconds.

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...
  • Content-Type
    Must be `application/json`.
    application/json

Request body

Share configuration.

{
  "accessLevel": "public",
  "name": "Public Temperature Dashboard"
}

Responses

  • 200Share link created successfully.
    {
      "success": true,
      "share": {
        "id": "share123",
        "shareUrl": "https://key-value.co/share/abc123token",
        "embedCode": "<iframe src=\"https://key-value.co/share/abc123token/embed\" width=\"100%\" height=\"600\"></iframe>",
        "access_level": "public",
        "view_count": 0
      }
    }
GET/api/dashboards/[id]/share
VisualizationSharing

List Share Links

Lists all active share links for a dashboard.

Authentication

required

Headers

  • Authorization
    Bearer token from authentication.
    Bearer eyJhbGciOi...

Responses

  • 200Shares retrieved successfully.
    {
      "success": true,
      "shares": [
        {
          "id": "share123",
          "shareUrl": "https://key-value.co/share/abc123",
          "access_level": "public",
          "view_count": 42,
          "created_at": "2025-01-10T12:00:00Z"
        }
      ]
    }
GET/api/health
Monitoring

Health check

Reports the service health and database connectivity status. Intended for monitoring and load balancer checks.

Authentication

none

Rate limit

None. Designed for observability tooling.

Responses

  • 200Service is healthy.
    {
      "status": "healthy",
      "timestamp": "2025-01-10T12:00:00Z",
      "version": "1.0.0",
      "checks": {
        "database": {
          "status": "up",
          "latency_ms": 12
        }
      }
    }
  • 503Service dependencies are unhealthy.
    {
      "status": "unhealthy",
      "timestamp": "2025-01-10T12:00:00Z",
      "checks": {
        "database": {
          "status": "down",
          "error": "Connection failed",
          "latency_ms": 5000
        }
      }
    }

OpenAPI Specification

Programmatic clients can fetch the full OpenAPI document at /api/docs. The same payload is shown below for convenience.

{
  "openapi": "3.1.0",
  "info": {
    "title": "Key-Value API",
    "version": "1.0.0",
    "description": "Secure key-value storage with memorable tokens."
  },
  "servers": [
    {
      "url": "https://key-value.co"
    }
  ],
  "tags": [
    {
      "name": "Tokens",
      "description": "Token generation endpoints."
    },
    {
      "name": "Data",
      "description": "Store, retrieve, and delete JSON data."
    },
    {
      "name": "Monitoring",
      "description": "Operational tooling and status endpoints."
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "parameters": {
      "TokenHeader": {
        "name": "X-KV-Token",
        "in": "header",
        "required": true,
        "description": "Memorable token generated via `/api/generate`.",
        "schema": {
          "type": "string",
          "example": "capable-germinate-disbelief-survival-quantum"
        }
      },
      "AuthorizationHeader": {
        "name": "Authorization",
        "in": "header",
        "required": false,
        "description": "Bearer token emitted after authenticating with the service.",
        "schema": {
          "type": "string",
          "example": "Bearer eyJhbGciOi..."
        }
      }
    },
    "schemas": {
      "TokenResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "token": {
            "type": "string",
            "example": "capable-germinate-disbelief-survival-quantum"
          },
          "user": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "email": {
                "type": "string",
                "example": "user@example.com"
              },
              "tier": {
                "type": "string",
                "enum": [
                  "free",
                  "pro",
                  "enterprise"
                ]
              }
            }
          },
          "error": {
            "type": "string"
          }
        }
      },
      "StoreRequest": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object"
          },
          "ttl": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2592000
          }
        }
      },
      "StoreResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "tier": {
            "type": "string"
          },
          "version": {
            "type": "integer",
            "description": "Event sequence number for optimistic concurrency"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "RetrieveResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "type": "integer",
            "description": "Current event sequence number"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "DeleteResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "type": "string"
          },
          "checks": {
            "type": "object"
          }
        }
      }
    }
  },
  "paths": {
    "/api/generate": {
      "post": {
        "tags": [
          "Tokens"
        ],
        "summary": "Generate a new token",
        "description": "Creates a new 5-word token. Anonymous callers require a Cloudflare Turnstile token when bot protection is enabled.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "turnstileToken": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "turnstileToken": "1x00000000000000000000AA"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing verification token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Please complete the verification"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Rate limit exceeded. Try again in 15 minutes."
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Tokens"
        ],
        "summary": "Generate a new token (GET)",
        "description": "GET variant of the generation endpoint. Anonymous callers must pass the Turnstile token as a query parameter.",
        "parameters": [
          {
            "name": "turnstileToken",
            "in": "query",
            "required": false,
            "description": "Cloudflare Turnstile response token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/AuthorizationHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Token created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing verification token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Please complete the verification"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Rate limit exceeded. Try again in 15 minutes."
                }
              }
            }
          }
        }
      }
    },
    "/api/store": {
      "post": {
        "tags": [
          "Data"
        ],
        "summary": "Store JSON data",
        "description": "Creates or replaces JSON data associated with a token.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TokenHeader"
          },
          {
            "$ref": "#/components/parameters/AuthorizationHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StoreRequest"
              },
              "example": {
                "data": {
                  "status": "online"
                },
                "ttl": 3600
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoreResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing headers or payload.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "X-KV-Token header is required"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Data too large. Max size is 100KB"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Rate limit exceeded. Try again in 60 seconds."
                }
              }
            }
          }
        }
      }
    },
    "/api/retrieve": {
      "get": {
        "tags": [
          "Data"
        ],
        "summary": "Retrieve stored data",
        "description": "Retrieves JSON payload for a token.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TokenHeader"
          },
          {
            "$ref": "#/components/parameters/AuthorizationHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Data returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetrieveResponse"
                }
              }
            }
          },
          "404": {
            "description": "Token has no data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "No data found for this token"
                }
              }
            }
          },
          "410": {
            "description": "Token expired.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Token has expired"
                }
              }
            }
          }
        }
      }
    },
    "/api/delete": {
      "delete": {
        "tags": [
          "Data"
        ],
        "summary": "Delete stored data",
        "description": "Deletes JSON payload associated with a token.",
        "parameters": [
          {
            "$ref": "#/components/parameters/TokenHeader"
          },
          {
            "$ref": "#/components/parameters/AuthorizationHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                }
              }
            }
          },
          "404": {
            "description": "Token has no data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "No data found for this token"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Health check",
        "description": "Returns service health information for monitoring.",
        "responses": {
          "200": {
            "description": "Service healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service unhealthy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    }
  }
}