# BlueFox Edge > Version: 2.0.0 BlueFox is receipt-backed infrastructure for the agent economy. It writes down what AI agents do as signed receipts anyone can verify, keeps a signed watch on the models and services they rely on, and can put a claim on the record: brand, pricing, compliance, financial data and product specifications. ## API Access - Base URL: https://api.bluefoxedge.ai - Host aliases: bluefoxedge.ai serves this same API (its root redirects to the website); the website is https://www.bluefoxedge.ai - Auth: Bearer token (get a key at https://api.bluefoxedge.ai/get-key) - Keyless path (no account needed): the endpoints listed at https://api.bluefoxedge.ai/.well-known/x402 accept x402 per-request payment (USDC) — send the request without a key and the HTTP 402 response quotes the exact terms; that listing is the whole keyless set, and other priced endpoints need an API key. A keyless payer gets a signed receipt from the notarize door below; on the verification doors (the checks and /v1/verify/*) a keyless payer receives the verdict unsigned and no receipt — a receipt there needs an API key - Notarize a digest, keyless: POST https://api.bluefoxedge.ai/v1/notarize/hash — submit a sha256 digest, get back a signed receipt recording that the digest was presented at that time (no content judgment); payable per request via x402, no signup. Request body: {"hash": ""} — the key "digest" is accepted as an alias for "hash". - Key path for agents (no human in the loop): POST https://api.bluefoxedge.ai/v1/api-keys/programmatic — the machine-to-machine twin of the browser signup: same free tier, same terms, no browser and no bot challenge; an autonomous caller completes it unattended, in one request, with no mailbox and no person in the loop. Body fields: `name` (what this program is called), `email` (a contact address for the operator — NOT verified: no message is sent, the response reports email_verified: false, and the key is active immediately), `accept_terms` (must be `true` — creating a key forms a contract, here exactly as on the form: Terms of Service https://www.bluefoxedge.ai/terms, Privacy Policy https://www.bluefoxedge.ai/privacy; a request that omits the field or sends `false` is refused with HTTP 422 TERMS_NOT_ACCEPTED and no key is created). Keys minted here are marked origin: "programmatic". The door is capped, per client address, per contact address, and across the endpoint as a whole: over a per-caller cap the refusal is HTTP 429 SIGNUP_RATE_LIMITED naming which cap bit and carrying Retry-After; when the endpoint's own ceiling is reached, or it cannot meter itself, the refusal is HTTP 503 SIGNUP_UNAVAILABLE — a state your own back-off does not clear, so the browser signup at https://api.bluefoxedge.ai/get-key is then the way through. Retries: send Idempotency-Key (at least 32 characters) and a retried request returns the original key rather than minting a second one; treat that key as a secret - Free tier: 100 API calls per UTC day, 1 signed mint per UTC day (resets 00:00 UTC); over-cap mints return HTTP 402 (payable per request on the endpoints listed at /.well-known/x402, otherwise a plan upgrade) - Free-tier inner meter: 10 claim-verification calls per UTC day, counted inside the 100 API calls per UTC day above — not beside it. The 10 claim-verification calls/day inner meter applies only to the REST /verify endpoints, never to MCP tool calls. - Paid plans: starter: 10,000 API calls per UTC day · pro: 100,000 API calls per UTC day · enterprise: 999,999 API calls per UTC day — Paid plans include signed mints — your plan's daily call limit is the only meter. Quote: https://api.bluefoxedge.ai/v1/billing/plans - Which meter bills you: Two meters, one bill: your plan sets the API-call allowance (100 API calls per UTC day on the free tier), while signed mints are counted separately — only the free tier is mint-capped, at 1 signed mint per UTC day. A mint spends one call from that same allowance, so the mint cap sits inside it, not beside it, and a third ceiling sits inside the same allowance: 10 claim-verification calls per UTC day. Paid plans include signed mints — your plan's daily call limit is the only meter. Every keyless call has a posted per-request price — the x402 table at /.well-known/x402 is the whole keyless price list, and each door's 402 is the quote of record. With a key, calls draw on your plan; the mint is the only act the free tier meters separately. - Agent discovery: https://api.bluefoxedge.ai/.well-known/agent.json - Agent enrolment: POST https://api.bluefoxedge.ai/agents/register — self-registration, no key and no human step; returns an agent_id and an agent_token. The agent_token names an agent INSIDE a check (send it as `agent_token` in the request body) — it is not an API key and will not open the doors listed here. - Agent action record: GET https://api.bluefoxedge.ai/agents/{agent_id}/audit-log — the checks one agent ran, one row each (endpoint, brand, claim, verdict, method, latency, timestamp), paginated and filterable by endpoint, brand, verdict and date; rolled up by endpoint/verdict/brand at https://api.bluefoxedge.ai/agents/{agent_id}/audit-log/summary. API key required on both. It holds what was logged THROUGH this service and nothing else — never read it as a complete account of what an agent did. - MCP discovery: https://api.bluefoxedge.ai/.well-known/mcp/server.json - Receipt-signing public keys (JWKS): https://api.bluefoxedge.ai/.well-known/jwks.json - Sample signed receipt: https://www.bluefoxedge.ai/specimen-receipt.json — check one yourself, no key required (see https://api.bluefoxedge.ai/getting-started step 4) - Transparency log: https://api.bluefoxedge.ai/v1/transparency/checkpoint — append-only inclusion log for signed receipts (signed C2SP checkpoint; RFC 6962 consistency proofs at /v1/transparency/consistency, which carry the two signed checkpoint notes they run between; the signed checkpoint at any published size at /v1/transparency/checkpoints?log_id=&size=, so the older end of a proof binds to the log key rather than to our word; every size this log ever published is listed, newest first, at /v1/transparency/checkpoints/history?log_id= — one GET, so never sweep integers to discover a fold (the list is an UNSIGNED convenience index and says so in its own bytes: take a proof's numbers from a signed note, never from the list); per-receipt inclusion proof at /v1/transparency/inclusion — possession of the receipt is the credential, no account required). Runnable checkers, standard-library-only, no install: https://api.bluefoxedge.ai/verify_inclusion.py (+ .sha256) proves one receipt is a leaf in the log and, with the witness's saved key (--witness-keys FILE, or --witness-key VKEY inline — a C2SP vkey you save from the witness's own origin, never from BlueFox), also verifies the witness cosignature on the checkpoint: one witness today, so a pass reads "witnessed by one witness", and a cosignature says that witness saw this exact checkpoint and found it consistent with its history — nothing about any receipt's contents; https://api.bluefoxedge.ai/verify_consistency.py (+ .sha256) proves the log only ever grew between two checkpoints you hold, checking BOTH signed notes and recomputing the RFC 6962 walk between them. IN-LOG WORKED EXAMPLE (start here — no account, nothing to install): receipt https://www.bluefoxedge.ai/specimen-inlog.json, minted 2026-08-16T08:24:54Z, chain_self sha256:05d2133e06c5e642cdd5d558853e3d7d7a543a9a36b141e2e403076173e029da — query the inclusion endpoint with that chain_self and pipe it into the checker for an exit-0 proof; the notarized bytes are published at https://www.bluefoxedge.ai/specimen-inlog-preimage.txt so the digest inside the receipt is recomputable too. NOTE: the other published receipt, specimen-receipt.json, PREDATES this log and is deliberately NOT in it — it is the signature/anatomy exhibit, and an inclusion query for it correctly 404s. The log signs with a DIFFERENT key than receipts; both are published at /.well-known/jwks.json — pin keys there, never from a field inside the artifact you are checking. Each key entry declares its family in "bfx:purpose" ("log" or "receipt"): select the log key by that label, NEVER by position — keys[0] is the receipt key, and both kids begin with the same two hex characters. The published checkers enforce the separation both ways: a checkpoint signed by a receipt key is refused, and a receipt signed by the log key is refused. - Cosigner bar: https://www.bluefoxedge.ai/docs/cosigner-bar — what BlueFox Edge requires of an independent cosigner of its transparency log: machine-checked tests, a declaration in the cosigner's own words, and the limits stated beside each one; the published checkers verify a cosigner's cosignature against a key you save from the cosigner's own origin, never from BlueFox. - Payment count: https://api.bluefoxedge.ai/v1/transparency/payments?log_id=reliance/v1&tx_hash=&chain_self= — how many log entries bind one settlement transaction. Takes log_id plus the settlement tx_hash AND a receipt-derived key (chain_self or receipt_id) TOGETHER — a transaction hash is public on its own chain, so a well-formed one presented WITHOUT the receipt-derived key is answered with the identical 404, never a count and never a hint the transaction exists. The query string above is a TEMPLATE: sent with its values left empty, or with no tx_hash at all, it is a client-side defect and answers 400 naming the exact format ('0x' followed by 64 lower-case hex characters, verbatim) — that 400 is not the 404 above. The answer is a count plus a membership assertion, never a list of receipts. The response publishes the log's own blind spot: 17,485 receipts (measured 2026-08-24T03:41:11Z) predate log admission, can never be counted there, and still verify as signed receipts — a closed set that does not grow. - Bitcoin anchoring of the transparency log: GET https://api.bluefoxedge.ai/v1/transparency/anchors — how far each checkpoint root has travelled toward a Bitcoin anchor (per-checkpoint record at /v1/transparency/anchor?log_id=&tree_size=, every state carrying a plain-language explanation of exactly what it does and does not assert; the raw calendar proof bytes at /v1/transparency/anchor/proof, served verbatim). Read the confirmation block on the summary first — it states, in the response itself, what the word confirmed rests on here. The raw proof plus the published checkpoint root is everything a standard OpenTimestamps client needs to check the timestamp independently, and if that client disagrees with our anchor record, the client is right. What the word means one surface over: on the per-receipt inclusion proof (/v1/transparency/inclusion), binding "anchored" requires an offline-verifiable EXTERNAL time anchor — an OpenTimestamps-confirmed Bitcoin commitment, or a held qualified timestamp — covering that tree size; it is never an internal marker. The anchor now has its OWN published checker (R9-1): https://api.bluefoxedge.ai/verify_anchor.py (+ .sha256), standard-library-only, carrying no key of ours at all — it fetches no key set and checks no signature, executing the stored timestamp proofs from the checkpoint root and confirming the block through a quorum of independently operated public chain APIs at a depth of 6 blocks pinned in the script's own bytes — deliberately not read from this API, since a bar it fetched from us would be a bar we could lower under it; it is the same figure the summary serves as required_confirmation_depth, and its --depth flag is how a holder holds us to a higher one. One command, filling the same two selectors the record door above takes: curl -sS "https://api.bluefoxedge.ai/v1/transparency/anchor?log_id=&tree_size=" | python3 verify_anchor.py — and its --root flag pins the checkpoint root out of band, so the run refuses unless our record agrees with the note you already hold. The inclusion checker ends on our log signature and says so on every run; that one does not end on anything of ours. An anchored response carries an anchor block pointing at the record and proof doors above, and those bytes plus that checker — or any stock OpenTimestamps client — are how a stranger checks the claim. "included" means committed under a signed checkpoint, claiming NO external anchor. What confirmed rests on, in the API's own served words: "This service does not run a Bitcoin node. It checks each claimed block against 4 independently operated public chain APIs and treats a block as observed only when at least 3 of them agree byte-for-byte on its hash and merkle root, across at least 2 independently written implementations. Depth is computed from the lowest tip inside the largest group of operators whose tips agree within 6 blocks (the majority tip); an operator reporting a tip outside that group is recorded as an outlier and neither governs the tip nor blocks the observation, though its block observations still count. When no majority agrees about the tip, when the operators contradict each other about a block, or when too few answer, the result is undetermined and nothing is confirmed. What is trusted here is that those operators are not simultaneously wrong about the same block — not the Bitcoin protocol itself." The required depth — 6 blocks at this render — is served beside the counts as required_confirmation_depth. Confirmed anchors exist on this log — the live count is the summary's to serve, never this file's (a number printed here would only go stale). Once a checkpoint is anchored, rewriting the log's history under it means rewriting Bitcoin: the root sits under public proof-of-work and the proof of its commitment is public, so we could not quietly change what we have already anchored — nobody could, including us. An anchor covers this log's history up to its checkpoint; newer entries wait for their own checkpoint's anchor. An anchor bounds when a root existed — no later than its block. It does not backdate anything, and history older than the first anchor carries only the first anchor's bound. See one yourself: curl 'https://api.bluefoxedge.ai/v1/transparency/anchor?log_id=reliance/v1&tree_size=1' — the earliest confirmed checkpoint at this render; the response reports the observed block height, hash and merkle root, the depth at confirmation, and what was and was not checked. - Observations (keyed): GET https://api.bluefoxedge.ai/v1/observations — the receipted listening observations, one row per provider call. Each observation is one provider call as the instrument declared it: the observation/1 record (digests and references only, never prompt or response text), the id and state of its signed receipt and, with receipts=inline, the receipt envelope; filter by declared subject, judged brand mention, model, provider, topic, sweep, outcome and time window. API key required. One observation by id at GET https://api.bluefoxedge.ai/v1/observations/{observation_id} (include_text=1 adds the stored response text for keyed readers). MCP tool: bluefox_observations. - Capabilities: https://api.bluefoxedge.ai/capabilities.json - Documentation: https://api.bluefoxedge.ai/docs ## MCP (Model Context Protocol) Interactive MCP endpoint: https://api.bluefoxedge.ai/mcp (Streamable HTTP, stateless). It takes the same API key as the REST API, sent the same way: every MCP request must carry the HTTP header Authorization: Bearer . Configure your MCP client to send that header: - Claude Code CLI: claude mcp add --transport http bluefox https://api.bluefoxedge.ai/mcp --header "Authorization: Bearer " - JSON-config clients (Claude Desktop, Cursor, VS Code, Windsurf): {"url": "https://api.bluefoxedge.ai/mcp", "headers": {"Authorization": "Bearer "}} - MCP SDKs: pass the same header to the Streamable HTTP transport constructor. Get a key at https://api.bluefoxedge.ai/get-key. Requests without the header receive an HTTP 401 before the protocol layer (an HTTP error body, not a JSON-RPC message). The full tool catalog at /.well-known/mcp/server.json is public — you can read every tool definition without a key; a key is required only to call them. ## Signed Receipts — Verify Offline Every signed receipt reproduces from public information alone: content_digest = 'sha256:'+sha256(JCS(envelope minus chain)); JCS = RFC 8785. chain_self = 'sha256:'+sha256((content_digest+'|'+chain_prev+'|'+schema_version).encode('utf-8')); chain_prev = 'GENESIS' at chain start, else the prior chain_self. signature = detached Ed25519 over the chain_self string (UTF-8), base64url no-padding; key_id = JWKS kid. Signed facts live in the envelope; top-level copies are unsigned conveniences. Verifiers read from the envelope and pin the key set out of band (the JWKS URL below), never from the receipt's own bytes. NORMATIVE: a verifier MUST NOT follow the jwks_url carried inside a receipt. That field sits outside the signature, so a forged receipt can aim it at the forger's own key set and the forgery verifies against it. Pin the key set out of band at https://api.bluefoxedge.ai/.well-known/jwks.json. Runnable code, plain and fetchable: https://api.bluefoxedge.ai/verify_receipt.py (checksum: https://api.bluefoxedge.ai/verify_receipt.py.sha256) — Python 3.8+ standard library ONLY, nothing to install; it carries its own RFC 8785 canonicaliser and its own RFC 8032 ed25519 verifier, and uses the cryptography package as a faster path only if you already have it. Run it as `python3 verify_receipt.py `, or with no argument to check a file named specimen-receipt.json. Fully offline: save the key set once (curl -sSo pinned-jwks.json https://api.bluefoxedge.ai/.well-known/jwks.json), then add `--jwks pinned-jwks.json` — the check fetches nothing at all. Every failure is one sentence and a non-zero exit, never a stack trace. Full walkthrough: https://api.bluefoxedge.ai/getting-started (step 4). Keys: https://api.bluefoxedge.ai/.well-known/jwks.json SAME CHECK IN JAVASCRIPT: https://api.bluefoxedge.ai/verify_receipt.js (checksum: https://api.bluefoxedge.ai/verify_receipt.js.sha256) — one file, zero dependencies, no build step, Node 18+. Run it as `node verify_receipt.js `, or `npx bluefox-verify-receipt `, or paste the whole file into any JavaScript runtime. The npx form is the published npm package `bluefox-verify-receipt` — cut from this same file and packaged; install it where pinning a dependency beats fetching a URL, and read the caveat: THE REGISTRY CAN LAG THE SERVED FILE. The served file is the cut the house ships today; a published package version can be an older cut and lack a flag documented here. To tell which cut you hold, use the package README's History: for every published version it names both the package digest and the served digest of that same cut (the two differ by one trailing newline the serving route appends) — compare verify_receipt.js.sha256 against the History's served digest for your installed version; equal is one cut, different is two. It takes the same `--jwks` flag with the same offline behaviour and the same sentences. TAKE THE PYTHON ONE IF YOU HAVE A PYTHON AND THE JAVASCRIPT ONE IF YOU DO NOT — they are twins, not alternatives: same steps, same order, same verdict, and the same refusal sentences, proven byte-for-byte against each other on the published specimen and a ten-plant tamper battery. Handed the inclusion proof, both routes also check transparency-log inclusion and the witness cosignature on the checkpoint: the Python route is two scripts — verify_receipt.py for the receipt, then https://api.bluefoxedge.ai/verify_inclusion.py (--witness-keys) for inclusion and the witness — and the JavaScript route is this one file, verify_receipt.js with --inclusion FILE, --tlog-proof FILE, or a bluefox-receipt-bundle/1 document as the input (--witness-keys). The witness key is a C2SP vkey you save from the witness's own origin, never from BlueFox; witnessed by one witness today, and a cosignature says that witness saw this exact checkpoint and found it consistent with its history — nothing about any receipt's contents. PUBLISHED PACKAGES (five, all carrying the same offline check; versions as published 2026-09-12): npm `bluefox-verify-receipt` (the JavaScript checker above, `npx bluefox-verify-receipt `; its dated version record lives on /changelog — this file names no version for it, the G17 law) · npm `@bluefoxedge/verify-receipt` 0.0.1 (the same checker under the @bluefoxedge scope, `npx @bluefoxedge/verify-receipt `) · PyPI `bluefox-verify-receipt` (the Python checker above, `pip install bluefox-verify-receipt` then `bluefox-verify-receipt `) · npm `bluefox-edge` 0.0.1 and PyPI `bluefox-edge` 0.0.1 (the offline receipt checker ONLY, under the SDK's name — the API client the SDK pages document arrives at 0.6+; install nothing expecting a client today). ## Legal - Terms of Service: https://www.bluefoxedge.ai/terms (version in force: April 1, 2026) - Privacy Policy: https://www.bluefoxedge.ai/privacy - Security disclosure policy: https://api.bluefoxedge.ai/.well-known/security.txt (RFC 9116) — human-readable at https://api.bluefoxedge.ai/security-policy - Operating entity: Format Dynamics, Inc. (DBA BlueFox) - Contract formation: getting a key forms an agreement. POST /api-keys requires `accept_terms: true`; a request without it is refused with HTTP 422 `TERMS_NOT_ACCEPTED` and no key is created. The accepted version and timestamp are stored with the key and returned in the response's `terms_accepted` object. - Counterparty: POST /api-keys and POST /v1/api-keys/programmatic accept `accepting_as` (individual | organization), `entity_legal_name` and `signer_title`. None of the three is verified by BlueFox; they are recorded as the acceptor's own statement and returned in the response's `terms_accepted.accepted_by` object with `verified: false`. - Legal contact: support@bluefoxedge.ai - Retrospective limit: BlueFox can evidence only what was recorded at the time it happened. Periods before a customer began minting receipts cannot be evidenced; nothing is backdated. ## Pagination Collection endpoints (e.g. /brands, /brands/profiles) accept optional `limit` (1-200, default 50), `cursor`, `q` (substring search on name/slug with alias resolution), and `all` (set `all=true` to bypass paging and return the full ordered list) query params, and return pagination state in `meta.pagination.{cursor, has_more, limit, total}`. Pass `limit=N` to set the page size and follow `meta.pagination.cursor` (keyset, stable under concurrent inserts) to walk subsequent pages. `cursor` is bound to the `q` value at issue time — do not change `q` between pages of a walk. See /openapi.json for the per-endpoint param schema. ## /brands Pagination Default — Phase 2 (LENS 3 #3) /brands and /brands/profiles now return a bounded page (default `limit=50`) instead of the full ordered list. To page through the full catalog, follow `meta.pagination.cursor`. To bypass paging entirely (admin / batch scripts), pass `?all=true`. The frontend Brand Explorer and the BlueFox SDKs (Python sync, Python async, JS) have been migrated; the SDKs expose `list_all_brands()` / `listAllBrands()` iterators that walk the cursor transparently. For server-side substring search by name or slug (with alias resolution — e.g. `?q=facebook` matches the `meta` brand), use the `q` param. This replaces client-side filtering against the full list. ## Idempotency-Key Header (optional today; enforcement not scheduled) BlueFox Edge accepts an `Idempotency-Key` header on write endpoints, in the Stripe idempotency pattern: one unique key (e.g. a UUID v4) per logical write, reused when that write is retried. `Idempotency-Key` is the one spelling of the key. `X-Request-Id` is a deprecated alias for the same key: it is honoured only when `Idempotency-Key` is absent, for a notice window whose end is not yet set; when a sunset is set it is published here and in the changelog before it takes effect, and from then on the alias is ignored (never refused). Send `Idempotency-Key`; if you also send `X-Request-Id` it is read as a trace id. ### Current status, as wired in this build - The header is OPTIONAL everywhere. No endpoint refuses a request for lacking it. - The receipt-minting doors replay on the key within the caller's bucket, independent of the middleware (POST /notarize/hash and POST /ingest/foreign-receipt; the same rule at any receipt-minting door this build lists): a repeat with the same key returns the same receipt (replayed: true); the same key over different presented bytes answers 409 IDEMPOTENCY_KEY_REUSED; a key naming a receipt still staged for asynchronous mint answers 409 IDEMPOTENCY_KEY_IN_PROGRESS. - Middleware replay is wired on one endpoint, the Phase 4a demo: POST /advisor/feedback. There, when the header is present and the idempotency store is reachable, the response is recorded only if it succeeded (2xx); a repeat with the same key then returns the recorded response instead of re-executing. A repeat while the first request is still in flight answers 409, a repeat with a different body answers 409 IDEMPOTENCY_KEY_REUSED, and after a non-2xx response the retry re-runs the handler. Without the header, or with the store unreachable, the request proceeds without caching. - Handler-level idempotency is wired on POST /api-keys, independent of the middleware and bound to the email in the request body: a repeat with the same key and the same email replays the recorded success (X-Idempotency-Replayed: true); the same key with a different email answers 400 IDEMPOTENCY_KEY_REUSED; a repeat while the first request is still in flight answers 409 IDEMPOTENCY_KEY_IN_PROGRESS; and when the idempotency store is unreachable this door fails closed with 503 and a Retry-After header. POST /v1/api-keys/programmatic carries the same handler-level behaviour, bound to that door and its contact address. - Every other endpoint listed below is ANNOUNCED only (Phase 4b-1): the header is documented, nothing is cached or replayed, and retry behaviour is unchanged. - Enforcement (header required, absent = 400, cached replay on retry) has no scheduled date. When one is set it will be published here and in the changelog before it takes effect. ### Endpoints where enforcement is planned (announced, not enforced) CRITICAL tier (fail-closed on infrastructure issues, when enforced): - POST /api-keys - POST /billing/checkout - POST /verify/package - POST /verify/package/batch - POST /verify/tool - POST /verify/tool/batch - POST /verify/citation - POST /verify/citation/batch - POST /verify/claim - POST /verify/claim/batch HIGH tier (graceful degradation on infrastructure issues, when enforced): - POST /agents/register - POST /brand/{slug}/monitor/claims - POST /brand/{slug}/monitor/subscribe - POST /scanner/submit ### How to use Include the header on each write request: Idempotency-Key: (X-Request-Id: is the deprecated alias; it works only while Idempotency-Key is absent and only for the notice window) Best practices: - Use a UUID v4 or similar unique value per logical operation. - Reuse the same key when retrying a failed request. - Do not reuse keys across different operations. - Keys are scoped per-endpoint and per-caller (your API key).