POST /api/verify
Verify a raw (addr, msg, sig) tuple directly. Skips Nostr discovery — useful when you already have the envelope in hand (from a QR code, embedded badge, or offline exchange).
POST https://ochk.io/api/verify
Content-Type: application/json
Request body
{
"addr": "bc1q...",
"msg": "orangecheck\nidentities: ...\naddress: ...\n...",
"sig": "AkcwRAIg...",
"scheme": "bip322",
"options": {
"testMode": false,
"expectedAud": "https://example.com"
}
}
Fields
| Field | Required? | Type | Notes |
|---|---|---|---|
addr | yes | string | Bitcoin address. |
msg | yes | string | Full canonical message with trailing LF. |
sig | yes | string | BIP-322 or legacy signature. Base64 or hex. |
scheme | optional | "bip322" / "legacy" | Default "bip322". Auto-detected from address if omitted. |
options.testMode | optional | bool | Accept testnet / signet addresses. |
options.expectedAud | optional | string | Require the aud: extension to equal this origin. |
Response (200)
{
"ok": true,
"codes": ["sig_ok_bip322", "bond_confirmed"],
"network": "mainnet",
"attestation_id": "a3f5b8c2…",
"identities": [
{ "protocol": "github", "identifier": "alice" }
],
"metrics": {
"sats_bonded": 125000,
"days_unspent": 47,
"score": 18.2
}
}
Fields
| Field | Type | Notes |
|---|---|---|
ok | bool | true iff signature valid and no policy failure. |
codes | string[] | Status codes — see Verification. |
network | string | Derived from address + network: extension. |
attestation_id | string | SHA-256(msg), lowercase hex. |
identities | array | Claims from the signed message. |
metrics | object | sats_bonded, days_unspent, score. Absent if signature invalid. |
Status codes emitted inside codes
- Signature —
sig_ok_bip322,sig_ok_legacy,sig_invalid,sig_unsupported_script. - Bond —
bond_confirmed,bond_zero,bond_pending,bond_insufficient. - Policy —
aud_mismatch,expired,network_testmode. - Input —
bad_request,decode_error,invalid_scheme.
A valid proof returns ok: true with codes like ["sig_ok_bip322", "bond_confirmed"]. A proof below a bond floor returns ok: false with ["sig_ok_bip322", "bond_insufficient"].
Examples
curl
curl -X POST "https://ochk.io/api/verify" \
-H 'Content-Type: application/json' \
-d '{
"addr": "bc1q...",
"msg": "orangecheck\nidentities: \naddress: bc1q...\n...",
"sig": "AkcwRAIg...",
"scheme": "bip322"
}'
SDK
import { verify } from '@orangecheck/sdk';
const outcome = await verify({
addr, msg, sig, scheme: 'bip322',
});
if (outcome.ok) {
console.log('metrics:', outcome.metrics);
}
When to use this vs /api/check
- Use
/api/checkwhen the subject just provided an address and you want the latest attestation + threshold gate. - Use
/api/verifywhen you already hold an attestation envelope (from a badge, offline exchange, QR) and need to confirm its authority.
Both end up at the same verification math — /api/check just does the Nostr discovery step for you.
Rate limit
10 req/min per IP on the free tier. Lower than /api/check because every request incurs chain lookups without caching.
Status codes
| HTTP | Meaning |
|---|---|
200 | Verification ran; body carries result (valid or not). |
400 | bad_request — missing/malformed body. |
429 | Rate limited. |
500 | Server error. |