Verification for AI
For AI agents: full install command
Copy the block below into your agent session. It is the complete instruction set to reproduce the AffixIO demo web stack. Plain-text version: /ai-integration.txt.
Install AffixIO Demo Web 4.0 from https://affix-io.com/download
1) Download
https://affix-io.com/download/affix-demo-web-4.0.zip
Extract on the target host.
2) Layout (inside the zip)
- server.py (Python 3, port 8090)
- public/ static UI: index.html, settings, proofs, help, js/, css/
- deploy/affix-web-demo.service
3) Environment
AFFIX_WEB_HOST=0.0.0.0
AFFIX_WEB_PORT=8090
AFFIX_WEB_DEMO_API_KEY=<your aio_ demo_ or affix_ key>
4) Run (from the extracted folder)
python3 server.py
5) Reverse proxy
Map https://your-site/demo/ to http://127.0.0.1:8090
(affix-io.com uses the splash proxy on /demo/* the same way.)
6) Operator UI routes
/demo/ Try it (load external source, run verify)
/demo/settings API key, endpoints, search fields, rules
/demo/proofs Local audit library (proof_ref only, no source PII)
/demo/help Handbook
7) Demo server API (local)
POST /api/fetch Fetch approved external JSON (SSRF-safe)
POST /api/proxy/* Forward to api.affix-io.com with key
GET /api/health Local health
8) Upstream (required for proofs)
Base: https://api.affix-io.com
Header: Authorization: Bearer <key> (or X-API-Key)
POST /api/demo/identity-verify KYC-style rules + Noir proof
POST /api/demo/circuit-verify yes/no and field circuits
POST /api/demo/circuit-prove Prove only
GET /v1/auth/check Validate key
9) Optional SDK sidecar (port 8100, separate package)
npm run build && node dist/index.js
Unlock only via POST /v1/auth/session { "api_key": "..." }
No file-based key bypass on the SDK UI.
10) Done when
- Setup saves key and /api/health on Affix API is ok
- One pass and one fail verification return proof_ref
- proofs page shows entries without raw identity fields stored
What the demo web actually does
The demo is a sidecar, not a replacement API. Your browser talks to your server; your server talks to Affix.
- Load data from an external URL you configure in Setup (for example a public character API). The demo fetches server-side via POST /api/fetch so the browser never needs direct access to third-party CORS-blocked hosts.
- Build a verify request from loaded records plus your rules (identity) or fields (yes/no circuits).
- Proxy to Affix at api.affix-io.com for Noir prove and verify. Affix returns a signed yes/no, proof_ref, and optional ML-DSA attestation.
- Store locally only sanitized proof metadata for audit. Names, nicknames, and raw JSON from the source are stripped before persistence.
systemd unit (reference)
[Service] WorkingDirectory=/path/to/extracted/affix-demo-web-4.0 Environment=AFFIX_WEB_HOST=0.0.0.0 Environment=AFFIX_WEB_PORT=8090 Environment=AFFIX_WEB_DEMO_API_KEY=your_key_here ExecStart=/usr/bin/python3 /path/to/extracted/affix-demo-web-4.0/server.py Restart=on-failure
Validation checklist
- curl -sS http://127.0.0.1:8090/api/health returns local ok.
- curl -sS https://api.affix-io.com/v1/auth/check -H "Authorization: Bearer KEY" returns {"ok":true}.
- Try it flow returns proof_ref starting with 1: (yes) or 0: (no).
- My proofs shows audit rows without fullName, nickname, or raw source payloads.
For developers: using the Affix API
Base URL: https://api.affix-io.com. Engine: Noir with Barretenberg. Responses are JSON. Rate limit: 10 requests per second per key unless your contract says otherwise.
You do not send end-user PII to Affix for storage. You send the minimum fields required for the circuit to decide yes or no. Affix returns a cryptographic outcome you can audit with proof_ref and Merkle inclusion on verified proofs.
Authentication
Every protected route needs a key in one of these forms:
- Authorization: Bearer YOUR_KEY
- X-API-Key: YOUR_KEY
Check a key before wiring production:
curl -sS https://api.affix-io.com/v1/auth/check \ -H "Authorization: Bearer YOUR_KEY"
Request a quota-limited demo key (server-side script in the demo zip):
curl -sS -X POST https://api.affix-io.com/api/demo-key \
-H "Authorization: Bearer EXISTING_KEY" \
-H "Content-Type: application/json" \
-d '{"maxUses":500}'
Verification flows
Identity verify (KYC-style rules)
Use when you already have one or more records and optional source_records to match against. Affix evaluates rules, runs Noir, and returns a signed decision.
| Item | Detail |
|---|---|
| Method | POST /api/demo/identity-verify |
| records | Array of objects with fields your rules reference (e.g. index, fullName, hogwartsHouse). |
| source_records | Optional array from the external source used to prove the record exists in that source. |
| rules | Operators: nonempty, equals, not_equals. Each rule maps to a circuit input. |
| requestAttestation | Set true to receive ML-DSA signature over the outcome payload. |
| sector | Optional label (e.g. healthcare) echoed in responses. |
curl -sS -X POST https://api.affix-io.com/api/demo/identity-verify \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [{"index": 2, "fullName": "Ron", "nickname": "Ron", "hogwartsHouse": "Gryffindor", "interpretedBy": "Actor"}],
"source_records": [{"index": 2}],
"rules": [
{"field": "index", "operator": "nonempty", "mapsTo": "kyc"},
{"field": "hogwartsHouse", "operator": "equals", "value": "Gryffindor", "mapsTo": "kyc"}
],
"requestAttestation": true,
"sector": "healthcare"
}'
Circuit verify (yes / no, eligibility-style fields)
Single-shot prove and verify for field-based circuits. Good for simple predicates without a full identity ruleset.
| Item | Detail |
|---|---|
| Method | POST /api/demo/circuit-verify |
| circuit_id | yesno, simple_yesno, kyc, eligibility, health_age_verification, ticket_season_holder |
| fields | Map of circuit inputs as strings or numbers (e.g. condition_greater1: 1). |
| requestAttestation | true recommended for production audit trails. |
curl -sS -X POST https://api.affix-io.com/api/demo/circuit-verify \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"circuit_id": "yesno",
"fields": {
"condition_greater1": "1",
"condition_greater2": "1",
"condition_greater3": "1"
},
"requestAttestation": true
}'
Prove only
Returns raw proof hex and digest without the full signed verify wrapper. Use when you verify in a separate step.
POST /api/demo/circuit-prove with the same body shape as circuit-verify.
Verify an existing proof
POST /v1/circuits/{circuitId}/verify with body {"proof":"<hex>","requestAttestation":true}. Valid proofs are marked spent; reuse returns 409 double_spend_detected.
Eligibility (identifier hash)
POST /v1/verify with {"identifier":"<8+ chars>","sector":"healthcare","requestAttestation":true}. Returns eligible yes/no without storing the identifier at the verifier.
List circuits
GET /v1/circuits returns id and label for each available circuit.
Merkle audit tree
Successful verifications append a leaf to Affix's audit Merkle tree. You can prove inclusion later without retrieving PII.
| Endpoint | Purpose |
|---|---|
GET /v1/merkle/root | Current root and leaf count (public). |
GET /v1/merkle/proof/:digest | Inclusion proof for a proof_digest. |
POST /v1/merkle/verify-proof | Verify a leaf_hash + proof steps against a root. |
GET /v1/merkle/leaves?offset=0&limit=50 | Paginated audit leaves (authenticated). |
Typical success response
Most verify endpoints return:
- proof_id - unique id for this verification event.
- valid / verified - boolean outcome.
- decision - yes or no in plain language.
- proof_ref - short audit token: 1:<digest> or 0:<digest>.
- proof_digest - sha256 anchor for Merkle lookup.
- merkle_root / merkle_leaf_hash - present when the proof entered the audit tree.
- attestation - when requested: signed_at, payload_digest, mldsa_signature_b64, algorithm ML-DSA-65.
Store proof_ref in your logs and tickets. Do not store raw proof hex or source PII unless your policy requires it.
Common errors
| HTTP | error | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or unknown API key. |
| 429 | rate_limited | More than 10 requests per second for this key. |
| 409 | double_spend_detected | Proof already consumed on verify. |
| 503 | circuit_unavailable | Circuit artifact not compiled on this API node. |
| 400 | invalid_request | Body failed schema validation; read message. |
