GET /api/check
The load-bearing endpoint. Look up the most recent attestation for a subject, verify its BIP-322 signature, recompute sats + days from live chain state, return pass/fail against your thresholds. One call, one decision.
GET https://ochk.io/api/check?addr=bc1q...&min_sats=100000&min_days=30
Query parameters
Exactly one of addr, id, or identity is required.
| Param | Required? | Type | Notes |
|---|---|---|---|
addr | one of | string | Bitcoin mainnet singlesig address. |
id | one of | string | Attestation ID — 64 lowercase hex chars. |
identity | one of | string | protocol:identifier, e.g. github:alice. |
min_sats | optional | int | Threshold. Default 0. |
min_days | optional | int | Threshold. Default 0. |
Response — success (200)
{
"ok": true,
"sats": 125000,
"days": 47,
"score": 18.2,
"attestation_id": "a3f5b8c2d1e4f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"identities": [
{ "protocol": "nostr", "identifier": "npub1alice..." },
{ "protocol": "github", "identifier": "alice" }
],
"network": "mainnet"
}
Fields
| Field | Type | Notes |
|---|---|---|
ok | bool | true iff signature valid AND thresholds met. |
sats | int | sats_bonded from chain state. |
days | int | days_unspent from chain state. |
score | number | score_v0 — advisory only. |
attestation_id | string | 64-char hex SHA-256. |
address | string | Bitcoin address of the attestation. |
identities | array | Self-asserted handle claims from the signed message. |
network | string | mainnet / testnet / signet. |
reasons | array | Present when ok: false. |
Response — below threshold (200)
{
"ok": false,
"sats": 50000,
"days": 12,
"score": 14.5,
"attestation_id": "a3f5b8c2…",
"address": "bc1q...",
"identities": [...],
"network": "mainnet",
"reasons": ["below_min_sats", "below_min_days"]
}
Response — not found (404)
{
"ok": false,
"reasons": ["not_found"]
}
Reason codes
| Reason | Meaning |
|---|---|
below_min_sats | Confirmed sats < min_sats. |
below_min_days | Oldest UTXO age < min_days. |
not_found | No published attestation matches the subject. |
sig_invalid | Signature didn't verify. |
bond_insufficient | Declared bond: exceeds confirmed balance. |
expired | expires: extension in the past. |
bond_zero | No confirmed UTXOs. |
Examples
curl
curl "https://ochk.io/api/check?addr=bc1q...&min_sats=100000&min_days=30"
fetch (browser / Node / Deno / Bun)
const r = await fetch(
`https://ochk.io/api/check?addr=${addr}&min_sats=100000&min_days=30`
);
const { ok, sats, days } = await r.json();
@orangecheck/sdk
import { check } from '@orangecheck/sdk';
const r = await check({ addr, minSats: 100_000, minDays: 30 });
if (r.ok) {
// proceed
}
Python
from orangecheck import check
r = check(addr="bc1q...", min_sats=100_000, min_days=30)
if r.ok:
...
Behavior notes
- The hosted verifier discovers the attestation via Nostr, then re-verifies the signature and re-queries chain state. It never trusts Nostr-cached metrics.
- Results cache for 60 seconds. Bond state changes at Bitcoin's block cadence — 60 s of staleness is well below block time.
- Identity bindings are self-asserted. This endpoint does not verify handle ownership. Use
verifyIdentity()for that, or check out-of-band.
Status codes
| HTTP | Meaning |
|---|---|
200 | Decision made; body carries pass/fail + metrics. |
400 | Missing or malformed parameters. |
404 | No attestation found for the subject. |
429 | Rate limited. |
500 | Server error. |
Rate limit
60 req/min per IP on the free tier.
See API overview for the full rate-limit table.