Download
Everything needed to integrate Veris: signed passports, real-time verification, offline JWT validation, the policy engine, and the audit trail. Complete field reference and working code in TypeScript and curl.
PDF · 19 pages · Updated August 2026
Developer documentation
Everything you need to issue AI Passports, embed them in agents, and verify them — online or offline.
Install the SDK and issue your first passport.
ES256 JWTs and offline verification.
Env vars, JWKS response, full verify sequence.
Restrict-only rules evaluated on every verification.
Five standardized signals, reference scoring.
Every endpoint, including the public ones.
@verisaegis/sdk and the open-source repo.
Veris Protocol is an open, vendor-neutral protocol for issuing, verifying, and revoking cryptographic identities for autonomous AI agents. Every agent carries an AI Passport: a signed credential declaring who issued it, what the agent may and may not do, and the behavioral baseline it was registered with. Relying parties verify that passport — offline against a public key, or live through the verification API for revocation status, current trust evidence, and policy evaluation.
aegis_ key prefix retain the protocol's original codename for backwards compatibility. They will not change.Base URL: https://verisaegis.com/api/public/aegis
Issue and verify an agent in about five minutes.
Create an organization and an API key in the Veris Console. Keys are prefixed aegis_ and shown once.
Install the SDK (published on npm as v0.1.0):
npm install @verisaegis/sdk
Issue a passport for your agent:
import { VerisClient } from '@verisaegis/sdk';
const client = new VerisClient({ apiKey: process.env.AEGIS_API_KEY! });
const { passport, passportJwt } = await client.issue({
agentName: 'CustomerSupportAgent',
agentVersion: '1.0.0',
modelFamily: 'claude-sonnet',
deploymentEnv: 'production',
jurisdiction: 'US',
permittedActions: ['read:customer_records', 'send:support_response'],
deniedActions: ['write:billing_records', 'delete:customer_data'],
requiresHumanApproval: ['process:refund'],
});
console.log(passport.passportId); // ap_...Verify an action before the agent performs it:
const decision = await client.verify({
passportId: passport.passportId,
requestedCapabilities: ['read:customer_records'],
riskLevel: 'MEDIUM',
relyingParty: 'support-api',
});
if (decision.decision !== 'ALLOW') throw new Error(decision.decision);Authenticated endpoints take an organization API key in the Authorization header. Keys begin with aegis_ and are stored hashed — the plaintext is shown only at creation time.
Authorization: Bearer aegis_... Content-Type: application/json
Store the key as AEGIS_API_KEY. The signing key environment variables (AEGIS_KEY_ID, AEGIS_PRIVATE_KEY, AEGIS_PUBLIC_KEY) are server-side only and never leave the backend.
Two endpoints require no authentication at all: the JWKS endpoint and /verify-passport.
POST /api/public/aegis/issue registers an agent, derives its behavioral baseline hash, and returns a passport together with a signed JWT.
POST https://verisaegis.com/api/public/aegis/issue
Authorization: Bearer aegis_...
Content-Type: application/json
{
"agentName": "CustomerSupportAgent",
"agentVersion": "1.0.0",
"modelFamily": "claude-sonnet",
"deploymentEnv": "production",
"jurisdiction": "US",
"permittedActions": ["read:customer_records", "send:support_response"],
"deniedActions": ["write:billing_records", "delete:customer_data"],
"requiresHumanApproval": ["process:refund"]
}
→ 200 OK
{
"passport": {
"passportId": "ap_oq5ZqfWWKGtpdFdkbM6c24yAHF",
"agentId": "agt_...",
"behavioralBaselineHash": "54f9ad69...",
"trustScore": 850,
"trustTier": "TRUSTED",
"passport_jwt": "eyJhbGciOiJFUzI1NiIs..."
},
"passportJwt": "eyJhbGciOiJFUzI1NiIs..."
}curl -X POST https://verisaegis.com/api/public/aegis/issue \
-H "Authorization: Bearer $AEGIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentName": "CustomerSupportAgent",
"agentVersion": "1.0.0",
"modelFamily": "claude-sonnet",
"deploymentEnv": "production",
"jurisdiction": "US",
"permittedActions": ["read:customer_records", "send:support_response"],
"deniedActions": ["write:billing_records"],
"requiresHumanApproval": ["process:refund"],
"validityDays": 365
}'Capability precedence is absolute: a denied action can never be granted, and actions in requiresHumanApproval always resolve to REVIEW.
POST /api/public/aegis/verify is the live trust decision: capability scope, revocation status, trust evidence, and policy evaluation in one call.
POST https://verisaegis.com/api/public/aegis/verify
Authorization: Bearer aegis_...
Content-Type: application/json
{
"passportId": "ap_oq5ZqfWWKGtpdFdkbM6c24yAHF",
"requestedCapabilities": ["read:customer_records"],
"interactionType": "data_access",
"riskLevel": "MEDIUM",
"relyingParty": "support-api"
}
→ 200 OK
{
"decision": "ALLOW",
"trustScore": 910,
"trustTier": "TRUSTED",
"validUntil": "2026-08-03T21:38:11Z",
"capabilityToken": "captoken...",
"auditReceiptId": "ar_...",
"warnings": [],
"scoreComponents": {
"identity": 900, "behavioral": 960, "compliance": 1000,
"historical": 700, "environmental": 950
},
"latencyMs": 34,
"matchedPolicies": [],
"trustModel": {
"weights": { "identity": 0.30, "behavioral": 0.25, "compliance": 0.20,
"historical": 0.15, "environmental": 0.10 },
"thresholds": { "trusted": 850, "elevated": 650, "standard": 400, "low": 200 },
"isDefault": true
}
}curl -X POST https://verisaegis.com/api/public/aegis/verify \
-H "Authorization: Bearer $AEGIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"passportId": "ap_oq5ZqfWWKGtpdFdkbM6c24yAHF",
"requestedCapabilities": ["read:customer_records"],
"interactionType": "data_access",
"riskLevel": "MEDIUM",
"relyingParty": "support-api"
}'matchedPolicies and trustModel are additive fields — existing integrations are unaffected.
Latency. The protocol targets sub-50ms p99. Current hosted-service latency is higher on cold starts; production latency optimization is on the roadmap.
Every issued passport includes a signed JWT (ES256), returned as passportJwt at the top level of the issue response and as passport_jwt inside the passport object. It uses standard JWS compact serialization: header.payload.signature.
{ "alg": "ES256", "typ": "JWT", "kid": "kid_937ce495367ebd11" }{
"iss": "https://verisaegis.com",
"sub": "ap_oq5ZqfWWKGtpdFdkbM6c24yAHF",
"aud": "veris-relying-party",
"iat": 1785792210,
"exp": 1817328210,
"jti": "ap_oq5ZqfWWKGtpdFdkbM6c24yAHF",
"veris": {
"version": "1.0",
"agentId": "agt_...",
"agentName": "CustomerSupportAgent",
"agentVersion": "1.0.0",
"modelFamily": "claude-sonnet",
"orgId": "org_...",
"deploymentEnv": "production",
"jurisdiction": "US",
"capabilities": {
"permitted": ["read:customer_records", "send:support_response"],
"denied": ["write:billing_records", "delete:customer_data"],
"requiresHumanApproval": ["process:refund"]
},
"behavioralBaselineHash": "54f9ad69...",
"policyFramework": "NIST_AI_RMF_1.0",
"initialTrustScore": 850,
"initialTrustTier": "TRUSTED"
}
}A passport can be verified by anyone, offline, without calling the Veris API or trusting our database. Verification requires only the public key from the JWKS endpoint — so an air-gapped service, an edge proxy, or a counterparty who has never heard of us can still confirm the passport is authentic.
Veris signs passports server-side with Web Crypto. This is the exact shape of the signing routine — useful if you self-host an issuer or want to reproduce a signature in a test.
function b64url(input: ArrayBuffer | Uint8Array | string): string {
const bytes =
typeof input === "string"
? new TextEncoder().encode(input)
: input instanceof Uint8Array
? input
: new Uint8Array(input);
let bin = "";
for (const b of bytes) bin += String.fromCharCode(b);
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
function pemToPkcs8(pem: string): ArrayBuffer {
const body = pem
.replace(/\\n/g, "\n")
.replace(/-----BEGIN [^-]+-----/g, "")
.replace(/-----END [^-]+-----/g, "")
.replace(/[^A-Za-z0-9+/=]/g, "");
const raw = atob(body);
const buf = new Uint8Array(raw.length);
for (let i = 0; i < raw.length; i++) buf[i] = raw.charCodeAt(i);
return buf.buffer;
}
const key = await crypto.subtle.importKey(
"pkcs8",
pemToPkcs8(process.env.AEGIS_PRIVATE_KEY!),
{ name: "ECDSA", namedCurve: "P-256" },
false,
["sign"],
);
const header = { alg: "ES256", typ: "JWT", kid: process.env.AEGIS_KEY_ID };
const signingInput = b64url(JSON.stringify(header)) + "." + b64url(JSON.stringify(claims));
const sig = await crypto.subtle.sign(
{ name: "ECDSA", hash: "SHA-256" },
key,
new TextEncoder().encode(signingInput),
);
const passportJwt = signingInput + "." + b64url(sig);import { jwtVerify, createRemoteJWKSet } from 'jose';
const JWKS = createRemoteJWKSet(
new URL('https://verisaegis.com/api/public/aegis/.well-known/jwks.json')
);
const { payload } = await jwtVerify(passportJwt, JWKS, {
issuer: 'https://verisaegis.com',
audience: 'veris-relying-party',
});
console.log(payload.veris.capabilities.permitted);POST /verify.A complete run-through: generate the keypair, set the exact environment variables, issue a signed passport, fetch the JWKS, and verify the JWT — copy each block in order.
# P-256 private key, converted to PKCS#8 (required by Web Crypto) openssl ecparam -name prime256v1 -genkey -noout -out ec-private.pem openssl pkcs8 -topk8 -nocrypt -in ec-private.pem -out private-pkcs8.pem # Matching SPKI public key openssl ec -in private-pkcs8.pem -pubout -out public-spki.pem # Key id echo "kid_$(openssl rand -hex 8)"
Exactly three secrets are required. Newlines may be written literally or escaped as \n — both are normalized server-side.
AEGIS_KEY_ID=kid_9f2c41ab77d0e5b3 AEGIS_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8s3Yq...\n-----END PRIVATE KEY-----" AEGIS_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1mHl3g...\n-----END PUBLIC KEY-----"
AEGIS_PRIVATE_KEY never leaves the server and is never written to the database. Only the public key is published, via the JWKS endpoint.curl -X POST https://verisaegis.com/api/public/aegis/issue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ak_live_xxxxxxxxxxxxxxxx" \
-d '{
"agentName": "support-bot",
"agentVersion": "2026.06",
"modelFamily": "gpt-5",
"deploymentEnv": "production",
"jurisdiction": "US",
"permittedActions": ["read:support_tickets", "write:support_replies"],
"deniedActions": ["transfer:funds"],
"validityDays": 90
}'
# → 201
# {
# "passport": { "passport_id": "ap_01HRZ8...", "trust_score": 850, "trust_tier": "TRUSTED", ... },
# "passportJwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZF85ZjJjNDFhYjc3ZDBlNWIzIn0..."
# }curl https://verisaegis.com/api/public/aegis/.well-known/jwks.json
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"use": "sig",
"alg": "ES256",
"kid": "kid_9f2c41ab77d0e5b3",
"x": "1mHl3gQ7Yb0m4qF2Xn8Jz1sV6pR9tK3cLw5dH0aQeUE",
"y": "T4nZk8sB2vXc9LpQ6yWm1RdF3JhG7oNu0aKzE5rYtIs"
}
]
}# 1. Store the JWT returned by /issue
JWT="eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZF85ZjJjNDFhYjc3ZDBlNWIzIn0..."
# 2. Confirm the kid in the header matches a key in the JWKS
echo "$JWT" | cut -d. -f1 | base64 -d 2>/dev/null
# → {"alg":"ES256","typ":"JWT","kid":"kid_9f2c41ab77d0e5b3"}
curl -s https://verisaegis.com/api/public/aegis/.well-known/jwks.json | grep kid_9f2c41ab77d0e5b3
# 3. Verify signature + expiry (no API key required)
curl -s -X POST https://verisaegis.com/api/public/aegis/verify-passport \
-H "Content-Type: application/json" \
-d "{\"passportJwt\":\"$JWT\"}"
# → { "valid": true, "signatureValid": true, "expired": false,
# "keyId": "kid_9f2c41ab77d0e5b3", "passportId": "ap_01HRZ8...", "claims": { ... } }
# 4. Live trust decision (revocation + policy + score) — API key required
curl -s -X POST https://verisaegis.com/api/public/aegis/verify \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ak_live_xxxxxxxxxxxxxxxx" \
-d '{ "passportId": "ap_01HRZ8...",
"requestedActions": ["read:support_tickets"],
"riskLevel": "LOW" }'
# → { "decision": "ALLOW", "trustScore": 850, "trustTier": "TRUSTED", ... }Organizations can define rules that are evaluated on every verification. Policies are configured in the Veris Console.
| Effect | Behavior |
|---|---|
| DENY | Blocks the action outright |
| REVIEW | Forces a REVIEW decision requiring human approval |
| REQUIRE_SCORE | Raises the minimum trust score for matching actions |
All condition fields are optional and AND-combined; an empty field matches anything.
verb:* wildcardsMatching policies are returned in the verify response as matchedPolicies.
Veris standardizes the trust evidence. The scoring model is a reference implementation you can replace.
| Component | What it measures |
|---|---|
| identity | Certificate validity, key storage, rotation age, revocation freshness |
| behavioral | Deviation from the declared behavioral baseline |
| compliance | Policy checkpoint adherence, human-approval compliance |
| historical | Time-decayed incident and attestation history (90-day half-life) |
| environmental | Deployment context, jurisdiction, request risk level |
trustScore = 0.30 × identity + 0.25 × behavioral + 0.20 × compliance + 0.15 × historical + 0.10 × environmental TRUSTED ≥ 850 · ELEVATED ≥ 650 · STANDARD ≥ 400 · LOW ≥ 200
scoreComponents, the composite trustScore, and a trustModel object describing the exact weights and thresholds used. A relying party with an existing risk engine can ignore the composite entirely.Protocols that achieve broad adoption standardize formats, identities, signatures, and verification — not reputation or risk models. TLS specifies how a certificate is structured and verified; it does not tell a browser which authorities to trust.
Every verification writes a tamper-evident audit event. Events are hash-chained: each record includes the hash of its predecessor, so any deletion or edit breaks the chain and is detectable. Retrieve them with GET /api/public/aegis/audit or browse them in the Veris Console.
GET https://verisaegis.com/api/public/aegis/audit?limit=50
Authorization: Bearer aegis_...
→ 200 OK
{
"events": [{
"id": "ar_...",
"passportId": "ap_...",
"decision": "ALLOW",
"trustScore": 910,
"requestedCapabilities": ["read:customer_records"],
"relyingParty": "support-api",
"createdAt": "2026-08-03T21:38:11Z",
"previousHash": "…",
"hash": "…"
}]
}Revoke a compromised or retired agent instantly. Revocation is reflected in the next /verify call; it cannot be observed by offline JWT verification alone.
POST https://verisaegis.com/api/public/aegis/revoke
Authorization: Bearer aegis_...
{ "passportId": "ap_...", "reason": "key_compromise" }Attestations record evidence about an agent's behavior over time — incidents, reviews, and third-party assessments — and feed the time-decayed historical component.
POST https://verisaegis.com/api/public/aegis/attest
Authorization: Bearer aegis_...
{
"passportId": "ap_...",
"attestationType": "INCIDENT",
"severity": "LOW",
"description": "Rate limit exceeded during batch run"
}Base URL https://verisaegis.com/api/public/aegis. Route paths retain the protocol's original codename for backwards compatibility.
| Endpoint | Auth | Purpose |
|---|---|---|
| POST /issue | API key | Register an agent and issue a signed passport |
| POST /verify | API key | Live trust decision with revocation and policies |
| POST /revoke | API key | Revoke a passport |
| POST /attest | API key | Record an attestation or incident |
| GET /audit | API key | Read hash-chained audit events |
| GET /passports | API key | List passports for the organization |
| GET /.well-known/jwks.json | None | Public signing keys in JWK Set format |
| POST /verify-passport | None | Verify a passport JWT signature and expiry |
Returns the public keys used to sign passports, in JWK Set format. No authentication required.
{
"keys": [{
"kty": "EC", "crv": "P-256", "use": "sig", "alg": "ES256",
"kid": "kid_937ce495367ebd11",
"x": "LHC4xNVFIjO6iCpkURL-tAQD_CyWnIAwHZsy_9eOz7c",
"y": "a3Zg7DBl_4joZA7w2tJzs5Lv6gc9SS61bbwGdjw2sMY"
}]
}Retired keys remain published so passports issued before a key rotation stay verifiable.
Verifies a passport JWT's signature and expiry. No authentication required.
POST https://verisaegis.com/api/public/aegis/verify-passport
Content-Type: application/json
{ "passportJwt": "eyJhbGciOiJFUzI1NiIs..." }
→ 200 OK
{
"valid": true,
"kid": "kid_937ce495367ebd11",
"passportId": "ap_oq5ZqfWWKGtpdFdkbM6c24yAHF",
"claims": { "iss": "https://verisaegis.com", "exp": 1817328210, "veris": { "…": "…" } }
}
→ 200 OK (failure)
{ "valid": false, "reason": "signature_invalid" }POST /verify for a live trust decision.The official TypeScript SDK is published on npm as @verisaegis/sdk (v0.1.0), MIT licensed.
npm install @verisaegis/sdk
import { VerisClient } from '@verisaegis/sdk';
const client = new VerisClient({ apiKey: process.env.AEGIS_API_KEY! });Source, the reference verifier, and the protocol specification live in the open-source repository.
View the repository on GitHubSigned ES256 passports and hash-chained audit trails are live today. HSM-backed signing, independent penetration testing, and SOC 2 attestation are on the near-term roadmap. Veris is ready for pilots with non-sensitive data today; we do not recommend it as the sole control for regulated or high-sensitivity workloads until those items land. The full threat model is published in the protocol specification.