Bound

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.

http
GET /api/near/verify/<agent>
sh
curl -s https://near.boundprotocol.dev/api/near/verify/bound-agent2-mwfnc6q8.testnet

Status codes

StatusBodyWhen
200the verdict belowthe 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

200 body
{
  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.

json
{
  "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.