Skip to main content

Fetch cTRNG Without the SDK

This guide shows how to get cosmic random numbers using only curl, fetch, or any HTTP client -- no SDK or dependencies required. It covers two methods: the authenticated Orbitport API and the public IPFS beacon.

Part 1: Direct API (authenticated)

The Orbitport API returns signed cTRNG values from satellites. It requires OAuth2 credentials.

Step 1: Get credentials

Request a client ID and secret by filling out the SpaceComputer access form.

Step 2: Set environment variables

OP_AUTH_DOMAIN=auth.spacecomputer.io
OP_AUTH_AUDIENCE=https://op.spacecomputer.io/api
OP_CLIENT_ID=<your-client-id>
OP_CLIENT_SECRET=<your-client-secret>

Step 3: Get an access token

ACCESS_TOKEN=$(curl --silent --request POST \
--url "https://${OP_AUTH_DOMAIN}/oauth/token" \
--header 'content-type: application/json' \
--data '{"client_id":"'"${OP_CLIENT_ID}"'","client_secret":"'"${OP_CLIENT_SECRET}"'","audience":"'"${OP_AUTH_AUDIENCE}"'","grant_type":"client_credentials"}' \
| jq -r '.access_token')

Step 4: Fetch a cTRNG value

curl --request GET \
--url https://op.spacecomputer.io/api/v1/services/trng \
--header "authorization: Bearer ${ACCESS_TOKEN}"

Example response

{
"service": "trng",
"src": "aptosorbital",
"data": "0a4c2ea21557418bbc1d57120142ad83e8fa6e030ad35125fe225b97929d2526",
"signature": {
"value": "3046022100da9e9dfbe4167da1bd7b824ab46e57506cfbebc50395fdf0bb3d3407c1d92451022100e33601c04b402fc57d8ffd22d41b01ec5315d4e1a1d2be97bf71323cc5cc3838",
"pk": ""
}
}

Choose a randomness source

Use the src query parameter to specify which source(s) the gateway should try, in order:

curl --request GET \
--url "https://op.spacecomputer.io/api/v1/services/trng?src=aptosorbital&src=derived" \
--header "authorization: Bearer ${ACCESS_TOKEN}"

Available sources:

SourceDescription
aptosorbitalSpace-based randomness from cEDGE or Crypto2 satellites.
derivedRandomness derived from a cosmic seed via BIP32 key derivation. Used as a fallback when satellites are not responsive.

The default is [aptosorbital, derived].


Part 2: IPFS beacon (no auth required)

The IPFS beacon publishes cTRNG values to a public IPNS address every 60 seconds. No credentials are needed.

Beacon URL

https://ipfs.io/ipns/k2k4r8lvomw737sajfnpav0dpeernugnryng50uheyk1k39lursmn09f

Fetch with curl

curl https://ipfs.io/ipns/k2k4r8lvomw737sajfnpav0dpeernugnryng50uheyk1k39lursmn09f

Fetch with JavaScript/TypeScript

async function fetchCTRNGFromIPFS() {
const response = await fetch(
"https://ipfs.io/ipns/k2k4r8lvomw737sajfnpav0dpeernugnryng50uheyk1k39lursmn09f"
);
const data = await response.json();

console.log("Sequence:", data.data.sequence);
console.log("Timestamp:", data.data.timestamp);
console.log("cTRNG values:", data.data.ctrng);

return data.data.ctrng[0]; // First value
}

Data structure

{
"previous": "/ipfs/bafkreial7oeangta7hakknhzsjzja4k2sehnsykx2u7bm6wdz46ug42me4",
"data": {
"sequence": 87963,
"timestamp": 1769179239,
"ctrng": [
"88943046891c6c971f185c7cd69a350d850fca480facf549777efc4602ec94a6",
"802a5afa3b09c360ec56cbe67cb615e038f307c905d199993e28ce38c21e9108",
"dbbe94501ed32c55acb4ad4512da0c3871f497930c4d2d9061bbe7bd634458fc"
]
}
}
FieldDescription
previousCID of the previous block. Follow this link to traverse history.
data.sequenceSequence number of this block.
data.timestampUnix timestamp when the block was created.
data.ctrngArray of cTRNG hex strings. Currently 3 values; may grow in the future.

Traverse historical blocks

Each block's previous field points to the prior block, forming a chain. Follow the chain to access older values:

async function traverseBlocks(count: number) {
let response = await fetch(
"https://ipfs.io/ipns/k2k4r8lvomw737sajfnpav0dpeernugnryng50uheyk1k39lursmn09f"
);
let current = await response.json();
const history = [current];

for (let i = 0; i < count && current.previous; i++) {
const cid = current.previous.replace("/ipfs/", "");
response = await fetch(`https://ipfs.io/ipfs/${cid}`);
current = await response.json();
history.push(current);
}

return history;
}

Update frequency

The beacon publishes a new block every 60 seconds. Data you fetch may be up to 60 seconds old. For lower-latency access, use the authenticated API or the SDK.


Part 3: API reference (OpenAPI)

OrbitPort OpenAPI specification (YAML)
openapi: 3.0.0
info:
title: OrbitPort API
version: 0.2.0
description: |
Orbitport is a gateway to orbital services such as `cTRNG` (cosmic True Random Number Generator) or `spaceTEE`.
paths:
/api/v1/services/trng:
get:
summary: Cosmic True Random Number Generator
description: The cosmic True Random Number Generation (cTRNG) provides true random numbers harvested from hardware on satellites, or uses a cTRNG seed to derive random numbers.
parameters:
- in: query
name: src
schema:
type: array
items:
type: string
enum: [aptosorbital, derived]
default: [aptosorbital, derived]
description: |
The gateway supports multiple sources of randomness:
1. **aptosorbital**: Space-based randomness provided by `cEDGE` or `Crypto2` satellites.
2. **derived**: Randomness derived from a cosmic TRNG (master seed) that is fetched continuously. The seed is used to generate more random numbers when satellites are not responsive, by using it as a seed for a BIP32 master key and deriving keys from it.
responses:
'200':
description: A cTRNG response
content:
application/json:
schema:
type: object
properties:
data:
type: string
description: A 32 byte chunk of random data as a hexadecimal string.
signature:
type: object
description: The signature provided by the satellite.
properties:
value:
type: string
description: The signature value.
pk:
type: string
description: The public key used for the signature.
example:
service: "trng"
src: "aptosorbital"
data: "a1b2c3d4e5f67890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890"
signature:
value: "3046022100a1b2c3d4e5f67890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890022100a1b2c3d4e5f67890abcdef1234567890"
pk: ""
'500':
description: Internal Server Error
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: Error message
example:
message: "Internal Server Error"

Next steps