Non-custodial by architecture

Build Crypto & Stable Coin Products with ease

ChainOS gives developers the API infrastructure to power exchanges, fintechs, and payment platforms. Generate wallet addresses, monitor deposits, settle withdrawals and consolidate funds across ten blockchains into a single treasury — without ever handing over your keys.

10
chains, one interface
0
private keys held by Ziklag
1
container to run on your side
Issue a deposit address
curl -X POST http://localhost:8787/v1/addresses \
  -H "X-API-Key: $CHAINOS_EDGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chain":   "eth",
    "userRef": "cust_88213",
    "tag":     "deposit",
    "label":   "Main NGN wallet"
  }'
const res = await fetch("http://localhost:8787/v1/addresses", {
  method:  "POST",
  headers: {
    "X-API-Key":    process.env.CHAINOS_EDGE_KEY,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    chain:   "eth",
    userRef: "cust_88213",
    tag:     "deposit"
  })
});

const { data } = await res.json();
console.log(data.address, data.derivationPath);
var req = HttpRequest.newBuilder()
    .uri(URI.create("http://localhost:8787/v1/addresses"))
    .header("X-API-Key", System.getenv("CHAINOS_EDGE_KEY"))
    .header("Content-Type", "application/json")
    .POST(BodyPublishers.ofString("""
        { "chain": "eth", "userRef": "cust_88213", "tag": "deposit" }
        """))
    .build();

var res = http.send(req, BodyHandlers.ofString());
body := `{"chain":"eth","userRef":"cust_88213","tag":"deposit"}`

req, _ := http.NewRequest("POST",
    "http://localhost:8787/v1/addresses",
    strings.NewReader(body))
req.Header.Set("X-API-Key", os.Getenv("CHAINOS_EDGE_KEY"))
req.Header.Set("Content-Type", "application/json")

res, err := http.DefaultClient.Do(req)
201 · derivationPath m/44'/60'/0'/0/4211 · environment live
Derived from your registered xpub. The matching private key never existed in our infrastructure.
Coverage

Ten chains, one interface

Address derivation, native and token balances, confirmation thresholds and fee models are normalised per chain. Your integration code does not branch.

Bitcoin
zpub · m/84'/0'/0'1 / 2 / 3 confnative UTXO
Ethereum
xpub · m/44'/60'/0'12 confERC-20
BSC
shares the ETH xpub15 confBEP-20
Polygon
shares the ETH xpub128 confERC-20
Avalanche
shares the ETH xpub1 conf, deterministicERC-20
Base
shares the ETH xpub1 conf, L1-finalizedERC-20 · native USDC
TRON
xpub · m/44'/195'/0'20 confTRC-20 · energy fees
Solana
Ed25519 address poolfinalizedSPL · ATA rent shown
XRP
xpub · m/44'/144'/0'1 conf, deterministic1 XRP reserve surfaced
Stellar
Ed25519 address pool1 conf, deterministicUSDC · trustline required
Adding a chain is adding a class
ChainAdapter SPI
How it works

Three steps to your first deposit

  1. Run the Edge container

    One static binary in your own network. It reads your BIP-39 mnemonic from a mounted secret, derives your extended public keys, and registers them with Cloud over a signed channel. It enrols once; every boot after that resumes.

    PASS_PHRASE_FILE=/run/secrets/mnemonic
  2. Point your core at localhost

    The Edge terminates the full ChainOS API on port 8787 and issues its own keys. Your banking application never holds a Ziklag credential and never calls Ziklag directly.

    X-API-Key: zkl_live_…
  3. Receive signed events

    Deposits and confirmations arrive as HMAC-signed webhooks, delivered Cloud to Edge to your endpoint. You need no public ingress, and an offline Edge means late events, never lost ones.

    deposit_confirmed · threshold 12
Trust boundaries

The mnemonic never crosses the line

Your application talks to the Edge. The Edge talks to Cloud. The seed, every child private key and the Edge identity key exist only in Edge process memory, mlocked and zeroed after each use.

Cloud stores extended public keys and one Ed25519 public key. An xpub permits derivation of public keys and addresses only — a property of BIP-32, not a policy commitment.

Rotation is detected, not inferred

Every request is signed by a key derived from your mnemonic and pinned on first sync. A different mnemonic fails authentication before any payload is read, quarantines the new xpubs, and pages your account owner. Addresses derived from prior xpubs stay monitored forever.

topologyapp → edge → cloud
Your premises
Core banking application
X-API-Key: zkl_live_*
Boundary 3 · key material
chainos-edge
signing
BIP-39 → seed (mlocked)xpub derivation7-chain signingSOL address poolbbolt outboxheartbeat 30s
Ziklag Cloud
chainos-server
apigatewayingestprocessordispatcherevent bus · database
Ziklag can
  • Derive receive addresses from your stored xpubs
  • Observe on-chain activity for those addresses
  • Construct unsigned transactions
  • Broadcast what your Edge has already signed
Ziklag cannot
  • Derive any private key
  • Sign any transaction
  • Move any funds
  • Reconstruct your mnemonic
Residual risk, stated

Possession of an xpub reveals the transaction graph of every address derived from it. We can see balances and flows. That is unavoidable wherever a provider performs monitoring, which is why xpubs are encrypted at rest, never logged, and never rendered beyond an eight-and-four character preview.

Events

Nine events, at-least-once, signed

Deliveries are durably queued with a tiered retry ladder — 2m, 5m, 30m — then a portal-visible dead letter queue you can replay. Ordering is guaranteed per address. Consumers must be idempotent on the event id.

  • deposit_detected
  • deposit_confirmed
  • withdrawal_broadcast
  • withdrawal_confirmed
  • withdrawal_failed
  • address_activated
  • edge_offline
  • edge_online
  • identity_rotation_detected
3
retries, then a replayable DLQ
7 days
replay window
0
public ingress required
deposit_confirmed
{
  "event": "deposit_confirmed",
  "id": "evt_01J8XK9",
  "environment": "live",
  "confirmations": 12,
  "threshold": 12,
  "timestamp": "2026-08-15T10:32:00Z",
  "data": {
    "chain": "eth",
    "txid": "0xf9e1a2b3…",
    "outputIndex": 0,
    "address": "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD",
    "counterparty": "0x8a1c…",
    "amount": "1000000",
    "amountFormatted": "1.00",
    "decimals": 6,
    "tokenSymbol": "USDT",
    "tokenContract": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    "blockNumber": 21456789,
    "userRef": "cust_88213",
    "tag": "deposit",
    "destinationTag": null
  }
}
Pricing

Capacity you commit to, transactions you settle

A band is a committed purchase, not a measurement. Sweeps, failed transactions, balance queries, address generation and all sandbox activity are never billed.

Launch
$99/mo
1,000 active addresses
1,000 settled tx included
$0.08 / tx overage
300 req/min
Growth
$499/mo
10,000 active addresses
10,000 settled tx included
$0.05 / tx overage
1,200 req/min
ScaleRecommended
$1,999/mo
100,000 active addresses
100,000 settled tx included
$0.025 / tx overage
6,000 req/min
Enterprise
$6,999/mo
1,000,000 active addresses
750,000 settled tx included
$0.012 / tx overage
20,000 req/min
Capability tiersBands set capacity. Tiers set what the platform will do.
CapabilityFreePremiumUltimate
Chains2all 10all 10
Active addresses100bandband
Settled tx / month100bandband
Webhooks125unlimited
Concurrent Edge sessions15unlimited
SSO / SAMLyesyes
HSM / KMS keystoreyes
Audit retention7 d90 dunlimited + export
Supportcommunitypriority, 24 hdedicated, 4 h SLA
You run the EdgeWhere your keys live

One container on your own network. It reads your recovery phrase from a mounted secret, derives your keys, signs every transaction and terminates the ChainOS API on port 8787. The phrase never leaves it.

You operate
1 container
Inbound ports
none
We can see
xpubs only
Ziklag runs the rest

Hosted at chainos.cloud. We operate Cloud, the chain indexers and the message bus, and we pay for the chain access behind them. You are billed a band fee plus settled transactions, and nothing else.

Billing
band fee + settled tx
Chain access
included
You operate
nothing

Monitoring never stops. A commercial dispute, a suspended account or an expired card blocks API access — it does not stop us watching your addresses or delivering your webhooks, because a deposit nobody sees is a deposit somebody loses.

Read the docs before you talk to us

Guides for every chain and every failure mode, a reference generated from OpenAPI 3.1, and a sandbox that derives real addresses from a real xpub without touching a chain. Free and unmetered.

sandbox.sh
# free, unmetered, no chain contacted
curl -X POST $EDGE/v1/sandbox/simulate-deposit \
  -H "X-API-Key: zkl_test_…" \
  -d '{ "address": "0x3fC9…7FAD",
        "chain": "eth",
        "amount": "100.50",
        "autoConfirm": true,
        "confirmAfterSeconds": 5 }'

# → deposit_detected, then deposit_confirmed at 12