Skip to main content

REST API Reference

Base URL: https://rng.dev/api/v1


Endpoints

GET /current

Returns the most recent generated round, including all inputs for verification.

Response:

{
"round": 12345678,
"output_hash": "a3f2e8c9d1b4a5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0",
"die_value": 4,
"generated_at": "2026-03-09T15:00:00Z",
"status": "complete",
"sources_available": 6,
"sources_total": 6,
"inputs": {
"aptos": "12345678:0xabc123...:0xdef456...",
"bitcoin": "00000000000000000002a7c4...3f:831245:def4567890abc...",
"cardano": "123456789:abc...:ghi7891234def...",
"ethereum": "0x8a3f2e...b9:19234567:0x1a2b3c4d5e6f...",
"solana": "245678901:5eykt4Uy...Gno:5VERv8NMvzbJMEkV...",
"sui": "12345678:abc123...:def789..."
}
}

Response Fields

FieldDescription
output_hashSHA3-256 hash of combined blockchain inputs
die_valueDie value (1-6) derived from hash using rejection sampling
inputsCombined block hash and transaction ID inputs for each chain

The inputs field contains the exact strings used to generate output_hash. Each chain's input includes block data and transaction ID in the format specified in How It Works. See Verification Guide to verify any round independently.


GET /round/{round_number}

Returns a specific historical round, including all inputs for verification.

Parameters:

NameTypeDescription
round_numberintegerThe round number to fetch

Example:

curl https://rng.dev/api/v1/round/12345678

Response:

{
"round": 12345678,
"output_hash": "a3f2e8c9d1b4a5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0",
"die_value": 4,
"generated_at": "2026-03-09T15:00:00Z",
"status": "complete",
"sources_available": 6,
"sources_total": 6,
"inputs": {
"aptos": "12345678:0xabc123...:0xdef456...",
"bitcoin": "00000000000000000002a7c4...3f:831245:def4567890abc...",
"cardano": "123456789:abc...:ghi7891234def...",
"ethereum": "0x8a3f2e...b9:19234567:0x1a2b3c4d5e6f...",
"solana": "245678901:5eykt4Uy...Gno:5VERv8NMvzbJMEkV...",
"sui": "12345678:abc123...:def789..."
}
}

GET /simple

Returns just the current die value as plain text.

Response:

4

Useful for simple integrations or shell scripts:

DIE=$(curl -s https://rng.dev/api/v1/simple)
echo "The die shows: $DIE"

GET /health

Returns service health status.

Response:

{
"status": "healthy",
"version": "1.0.0",
"last_round": 12345678,
"last_round_at": "2026-03-09T15:00:00Z",
"sources": {
"aptos": "ok",
"bitcoin": "ok",
"cardano": "ok",
"ethereum": "ok",
"solana": "ok",
"sui": "ok"
}
}

GET /health/gaps

Returns information about any missing rounds in the sequence.

Response:

{
"has_gaps": false,
"total_rounds": 12345678,
"missing_rounds": [],
"last_checked": "2026-03-09T15:00:00Z"
}

Response with gaps:

{
"has_gaps": true,
"total_rounds": 12345678,
"missing_rounds": [12345600, 12345601],
"gap_reason": "source_unavailability",
"last_checked": "2026-03-09T15:00:00Z"
}

GET /meta

Returns static metadata about the beacon service. Call once and cache — this data rarely changes.

Response:

{
"version": "2.0.0",
"sources": ["aptos", "bitcoin", "cardano", "ethereum", "solana", "sui"],
"explorers": {
"aptos": "https://explorer.aptoslabs.com/block/{block}",
"bitcoin": "https://mempool.space/block/{hash}",
"cardano": "https://cardanoscan.io/block/{block}",
"ethereum": "https://etherscan.io/block/{block}",
"solana": "https://solscan.io/block/{slot}",
"sui": "https://suiscan.xyz/mainnet/checkpoint/{checkpoint}"
},
"tx_explorers": {
"aptos": "https://explorer.aptoslabs.com/txn/{txid}",
"bitcoin": "https://mempool.space/tx/{txid}",
"cardano": "https://cardanoscan.io/transaction/{txid}",
"ethereum": "https://etherscan.io/tx/{txid}",
"solana": "https://solscan.io/tx/{txid}",
"sui": "https://suiscan.xyz/mainnet/tx/{txid}"
},
"input_format": {
"aptos": "{block_height}:{block_hash}:{txid}",
"bitcoin": "{block_height}:{block_hash}:{txid}",
"cardano": "{slot}:{block_hash}:{txid}",
"ethereum": "{block_number}:{block_hash}:{txid}",
"solana": "{slot}:{blockhash}:{txid}",
"sui": "{checkpoint}:{digest}:{txid}"
},
"tx_selection": {
"aptos": { "index": 0, "description": "First transaction" },
"bitcoin": { "index": 1, "description": "Second transaction (skip coinbase)" },
"cardano": { "index": 0, "description": "First transaction" },
"ethereum": { "index": 0, "description": "First transaction" },
"solana": { "index": 0, "description": "First transaction" },
"sui": { "index": 0, "description": "First transaction" }
},
"combination_order": ["aptos", "bitcoin", "cardano", "ethereum", "solana", "sui"],
"combination_separator": "|",
"hash_algorithm": "SHA3-256"
}

Use explorers templates to build verification links from inputs values.


Statistics Endpoints

GET /stats/distribution

Returns die value distribution statistics.

Parameters:

NameTypeDefaultDescription
roundsinteger1000Number of recent rounds to analyze

Response:

{
"rounds_analyzed": 1000,
"distribution": {
"1": 168,
"2": 165,
"3": 167,
"4": 166,
"5": 167,
"6": 167
},
"expected": 166.67,
"chi_squared": {
"statistic": 0.072,
"p_value": 0.9995,
"degrees_of_freedom": 5
},
"status": "PASS"
}

GET /stats/streaks

Returns streak distribution analysis.

Parameters:

NameTypeDefaultDescription
roundsinteger1000Number of recent rounds to analyze

Response:

{
"rounds_analyzed": 1000,
"streaks": {
"1": 833,
"2": 139,
"3": 23,
"4": 4,
"5": 1
},
"expected_geometric": {
"1": 833.3,
"2": 138.9,
"3": 23.1,
"4": 3.9,
"5": 0.6
},
"status": "PASS"
}

GET /stats/transitions

Returns transition matrix between consecutive die values.

Parameters:

NameTypeDefaultDescription
roundsinteger1000Number of recent rounds to analyze

Response:

{
"rounds_analyzed": 1000,
"matrix": [
[28, 27, 28, 28, 28, 28],
[27, 28, 27, 28, 28, 27],
[28, 28, 27, 28, 27, 28],
[27, 28, 28, 27, 28, 28],
[28, 27, 28, 28, 27, 28],
[28, 28, 28, 27, 28, 27]
],
"expected": 27.78,
"chi_squared": {
"statistic": 0.36,
"p_value": 1.0,
"degrees_of_freedom": 25
},
"status": "PASS"
}

GET /stats/autocorrelation

Returns autocorrelation analysis for sequence independence.

Parameters:

NameTypeDefaultDescription
lagsinteger20Number of lag values to compute

Response:

{
"rounds_analyzed": 10000,
"autocorrelations": {
"1": 0.003,
"2": -0.002,
"3": 0.001,
"...": "...",
"20": -0.001
},
"confidence_bound": 0.02,
"significant_lags": [],
"status": "PASS"
}

GET /stats/randomness

Comprehensive randomness statistics for monitoring and AI agents.

Response:

{
"_meta": {
"schema_version": "1.0",
"generated_at": "2026-03-09T15:00:00Z",
"beacon_round": 12345678
},
"summary": {
"overall_status": "PASS",
"plain_english": "The beacon is behaving like a fair random source with no detectable bias."
},
"rolling_windows": {
"last_100": { "...": "..." },
"last_1000": { "...": "..." },
"last_100000": { "...": "..." }
},
"comparisons": {
"beacon_vs_drand": {
"ks_statistic": 0.012,
"p_value": 0.87,
"status": "PASS"
},
"beacon_vs_nist": {
"ks_statistic": 0.011,
"p_value": 0.84,
"status": "PASS"
}
}
}

Comparison Endpoints

GET /comparisons

Compares beacon die value distributions against reference sources (drand, NIST) using the Kolmogorov-Smirnov two-sample test. This validates that our randomness is statistically indistinguishable from established random beacons.

Parameters:

NameTypeDefaultDescription
roundsinteger1000Number of recent samples to compare (max 100,000)

Response:

{
"sample_counts": {
"beacon": 5000,
"drand": 5000,
"nist": 5000
},
"pairwise_comparisons": [
{
"source1": "beacon",
"source2": "drand",
"statistic": 0.0089,
"p_value": 0.5012,
"effect_size": 0.0089,
"n1": 5000,
"n2": 5000,
"interpretation": "Distributions are statistically indistinguishable",
"status": "PASS"
},
{
"source1": "beacon",
"source2": "nist",
"statistic": 0.0156,
"p_value": 0.8234,
"effect_size": 0.0156,
"n1": 5000,
"n2": 5000,
"interpretation": "Distributions are statistically indistinguishable",
"status": "PASS"
},
{
"source1": "drand",
"source2": "nist",
"statistic": 0.0167,
"p_value": 0.7654,
"effect_size": 0.0167,
"n1": 5000,
"n2": 5000,
"interpretation": "Distributions are statistically indistinguishable",
"status": "PASS"
}
],
"uniformity_tests": [
{
"source": "beacon",
"statistic": 0.0023,
"p_value": 0.9999,
"effect_size": 0.0023,
"n": 5000,
"interpretation": "Distribution consistent with uniform",
"status": "PASS"
},
{
"source": "drand",
"statistic": 0.0021,
"p_value": 0.9999,
"effect_size": 0.0021,
"n": 5000,
"interpretation": "Distribution consistent with uniform",
"status": "PASS"
},
{
"source": "nist",
"statistic": 0.0312,
"p_value": 0.7234,
"effect_size": 0.0312,
"n": 5000,
"interpretation": "Distribution consistent with uniform",
"status": "PASS"
}
],
"overall_status": "PASS",
"plain_english": "Compared 5,000 samples from each source. All distributions are statistically indistinguishable — beacon randomness matches known reference sources."
}

Note: Sample counts are automatically matched to the minimum available across all sources for fair comparison. If you request 100,000 rounds but NIST only has 5,000, all sources will be compared using 5,000 samples each.

Response Fields

FieldDescription
sample_countsNumber of die values available from each source
pairwise_comparisonsK-S tests between each pair of sources
uniformity_testsK-S tests against theoretical uniform distribution (1-6)
overall_statusCombined status: PASS, WATCH, or INVESTIGATE
plain_englishHuman-readable summary of the comparison

Status Values

Status is determined by effect size, not p-values, making it reliable at any sample size:

StatusEffect SizeMeaning
PASS< 0.10Negligible/weak difference — no action needed
WATCH0.10 - 0.20Moderate difference — monitor for patterns
INVESTIGATE> 0.20Strong difference — review for potential issues

Reference Sources

SourceDescriptionUpdate Frequency
drandLeague of Entropy distributed randomnessEvery 10 seconds
NISTNIST Randomness Beacon 2.0Every 60 seconds

Reference Endpoints

GET /reference/drand

Returns the current status and recent die values from the drand (League of Entropy) reference source.

Response:

{
"source": "drand",
"total_rounds": 76543,
"latest_round": 4521234,
"recent_die_values": [3, 1, 6, 2, 4, 5, 1, 3, 6, 2]
}

Response Fields

FieldDescription
sourceSource identifier ("drand")
total_roundsTotal number of drand rounds we've collected
latest_roundMost recent drand round number
recent_die_valuesLast 10 die values (1-6) derived from drand randomness

GET /reference/nist

Returns the current status and recent die values from the NIST Randomness Beacon 2.0.

Response:

{
"source": "nist",
"total_rounds": 1234,
"latest_round": 1709730,
"recent_die_values": [5, 2, 4, 1, 6, 3, 2, 5, 1, 4]
}

Response Fields

FieldDescription
sourceSource identifier ("nist")
total_roundsTotal number of NIST pulses we've collected
latest_roundMost recent NIST pulse index
recent_die_valuesLast 10 die values (1-6) derived from NIST randomness

Response Codes

CodeMeaning
200Success
400Bad request (invalid parameters)
404Round not found
429Rate limit exceeded
500Server error
503Service unavailable (generation paused)

Authentication

API Key Format

Include your API key in the Authorization header using Bearer token format:

Authorization: Bearer YOUR_API_KEY

Code Examples

curl:

curl -H "Authorization: Bearer $RNG_API_KEY" \
https://rng.dev/api/v1/current

JavaScript (fetch):

const response = await fetch('https://rng.dev/api/v1/current', {
headers: {
'Authorization': `Bearer ${process.env.RNG_API_KEY}`
}
});
const data = await response.json();

Python (requests):

import os
import requests

response = requests.get(
'https://rng.dev/api/v1/current',
headers={'Authorization': f'Bearer {os.environ["RNG_API_KEY"]}'}
)
data = response.json()

Environment Setup

Store your API key in a .env file for local development:

# .env
RNG_API_KEY=rng_sk_your_key_here

Then load it in your application:

# Shell
source .env && curl -H "Authorization: Bearer $RNG_API_KEY" https://rng.dev/api/v1/current
// Node.js - install dotenv: npm install dotenv
require('dotenv').config();
// process.env.RNG_API_KEY is now available
# Python - install python-dotenv: pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
# os.environ["RNG_API_KEY"] is now available

Self-Hosted Setup

If running your own instance of rng.dev, API keys are managed through the admin interface. Keys are stored as SHA-256 hashes in the api_keys table.

To generate a key programmatically:

import secrets
import hashlib

# Generate a new API key
key = f"rng_sk_{secrets.token_hex(16)}"
key_hash = hashlib.sha256(key.encode()).hexdigest()

# Store key_hash in database, give key to user (only shown once)
print(f"API Key: {key}")

Rate Limiting

TierLimit
Unauthenticated10 requests/hour
Authenticated100,000 requests/day

Need higher limits? Contact us.

Rate Limit Headers

All responses include rate limit information:

X-RateLimit-Limit: 100000
X-RateLimit-Remaining: 99423
X-RateLimit-Reset: 1709996400
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in current period
X-RateLimit-RemainingRequests remaining before limit is reached
X-RateLimit-ResetUnix timestamp when the limit resets

Handling Rate Limits

When rate limited, you'll receive a 429 response:

{
"detail": "Rate limit exceeded. Maximum 10 requests per hour."
}

Implement exponential backoff or respect the Retry-After header:

async function fetchWithRetry(url, options = {}, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status !== 429) return response;

const retryAfter = response.headers.get('Retry-After') || (i + 1) * 1000;
await new Promise(r => setTimeout(r, retryAfter));
}
throw new Error('Rate limit exceeded after retries');
}

Status Values

StatusDescription
finalizedAll 8 blockchain sources contributed
confirmed6-7 sources contributed
partial4-5 sources contributed
degraded2-3 sources contributed (use with caution)
failedRound could not be generated (< 2 sources)
missedRound was skipped (historical gap)

Error Responses

{
"error": {
"code": "ROUND_NOT_FOUND",
"message": "Round 99999999 does not exist",
"details": {
"requested_round": 99999999,
"latest_round": 12345678
}
}
}

CORS

The API supports CORS for browser-based applications:

  • Allowed origins: * (all origins)
  • Allowed methods: GET, OPTIONS
  • Allowed headers: Content-Type, Authorization

OpenAPI Specification

Full OpenAPI 3.0 specification available at: