Build
HTTP API
GET /api/near/verify/<agent>: the verdict, the certificate and the agent's confinement as JSON.
One read-only endpoint, served by this site. No key, no wallet, no auth. Responses carry cache-control: no-store, and every chain read behind them skips the server's data cache: a verdict is about now, and a cached deal after a claim window opens is the exact failure a certificate exists to prevent. cert.now is the chain time of the read; compare it with the current time before relying on deal.
GET /api/near/verify/<agent>curl -s https://near.boundprotocol.dev/api/near/verify/bound-agent2-mwfnc6q8.testnetStatus codes
| Status | Body | When |
|---|---|---|
200 | the verdict below | the contract answered; cert may be null (no certificate) |
400 | { "error": "not a NEAR account id" } | the path segment is not a valid account id |
502 | { "error": "testnet RPC did not answer; no verdict" } | the RPC failed: no verdict rather than a wrong one |
Response schema
{
network: "testnet",
contract: string, // the Bound contract read
agent: string, // lowercased account id
deal: boolean, // Verified, not halted, and the contract's deal flag
reason: string, // human-readable why
cert: CertView | null, // verify(agent), as the contract returns it
confinement: { // null when the keys could not be read
confined: boolean, // pay-only keys AND no code, local or global
keysConfined: boolean,
codeHash: string | null, // null when view_account could not be read
globalContract: string | null,
fullAccess: number, // count of full-access keys
functionCall: Array<{
publicKey: string,
receiver: string,
methods: string[],
allowanceNear: string | null // e.g. "0.249"
}>,
summary: string
} | null
}cert is the contract's CertView; its fields are listed in the contract reference. Amounts are decimal strings in mock USDC base units (6 decimals), times unix seconds.
Example
Cert 1 as read on 2026-11-14. Live values change as the agent pays.
{
"network": "testnet",
"contract": "bound-v3.boundproto-nh26.testnet",
"agent": "bound-agent2-mwfnc6q8.testnet",
"deal": true,
"reason": "Verified: reserve locked and auditor staked",
"cert": {
"cert_id": 1,
"status": "Verified",
"deal": true,
"operator": "bound-operator-mwfnc6q8.testnet",
"agent": "bound-agent2-mwfnc6q8.testnet",
"auditor": "bound-auditor-mwfnc6q8.testnet",
"bound": "50000000",
"reserve_promised": "30000000",
"reserve_locked": "30000000",
"allocation": "100000000",
"coverage": "130000000",
"premium": "0",
"float": "9000000",
"float_cap": "10000000",
"spent": "1000000",
"post_expiry_spent": "0",
"pay_count": 1,
"allowlist": ["bound-service-mwfnc6q8.testnet"],
"expires_at": 1795996800,
"settlement_deadline": 1795997100,
"halted": false,
"window_closes_at": null,
"open_claims": 0,
"settlement": null,
"now": 1794657572
},
"confinement": {
"confined": true,
"keysConfined": true,
"codeHash": "11111111111111111111111111111111",
"globalContract": null,
"fullAccess": 0,
"functionCall": [
{
"publicKey": "ed25519:7y9HVKPeXorjxfuV35HGLTqqVXoaNCs5ZgddRAiuQgoh",
"receiver": "bound-v3.boundproto-nh26.testnet",
"methods": ["pay"],
"allowanceNear": "0.249"
}
],
"summary": "Confined: its only key is a function-call key for bound-v3.boundproto-nh26.testnet, method pay, no full-access key, no contract code and no global contract"
}
}Deciding
Extend credit only when deal and confinement.confined are both true, and cap it at min(bound, coverage) minus what the agent already owes you. Treat a null confinement or a 502 as a refusal.
deal here uses the same rule as the SDK and the CLI. It does not include confinement; confinement is reported beside it.