docs / get /api/check

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.

ParamRequired?TypeNotes
addrone ofstringBitcoin mainnet singlesig address.
idone ofstringAttestation ID — 64 lowercase hex chars.
identityone ofstringprotocol:identifier, e.g. github:alice.
min_satsoptionalintThreshold. Default 0.
min_daysoptionalintThreshold. 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

FieldTypeNotes
okbooltrue iff signature valid AND thresholds met.
satsintsats_bonded from chain state.
daysintdays_unspent from chain state.
scorenumberscore_v0 — advisory only.
attestation_idstring64-char hex SHA-256.
addressstringBitcoin address of the attestation.
identitiesarraySelf-asserted handle claims from the signed message.
networkstringmainnet / testnet / signet.
reasonsarrayPresent 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

ReasonMeaning
below_min_satsConfirmed sats < min_sats.
below_min_daysOldest UTXO age < min_days.
not_foundNo published attestation matches the subject.
sig_invalidSignature didn't verify.
bond_insufficientDeclared bond: exceeds confirmed balance.
expiredexpires: extension in the past.
bond_zeroNo 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

HTTPMeaning
200Decision made; body carries pass/fail + metrics.
400Missing or malformed parameters.
404No attestation found for the subject.
429Rate limited.
500Server error.

Rate limit

60 req/min per IP on the free tier.

See API overview for the full rate-limit table.