Download

Integration Guide

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

Build on Veris

Everything you need to issue AI Passports, embed them in agents, and verify them — online or offline.

Introduction

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.

Route paths and the aegis_ key prefix retain the protocol's original codename for backwards compatibility. They will not change.

Base URL: https://verisaegis.com/api/public/aegis

Quickstart

Issue and verify an agent in about five minutes.

  1. Step 1

    Create an organization and an API key in the Veris Console. Keys are prefixed aegis_ and shown once.

  2. Step 2

    Install the SDK (published on npm as v0.1.0):

    npm install @verisaegis/sdk
  3. Step 3

    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_...
  4. Step 4

    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);

Authentication

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.

Issuing passports

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..."
}

Copy-paste examples

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.

Verifying agents

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
  }
}

Copy-paste examples

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.

Signed passports & offline verification

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"
  }
}

Why it matters

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.

How the signature is produced (ES256)

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);

Verifying a signed passport

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);
Signature verification proves the passport was issued by Veris and has not been tampered with. It does not check revocation status. For a live trust decision including revocation, current trust score, and policy evaluation, call POST /verify.

End-to-end ES256 example

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.

Step 1 — Generate the keypair

# 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)"

Step 2 — Set the environment variables

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.

Step 3 — Issue a signed passport

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..."
# }

Step 4 — Sample JWKS response

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"
    }
  ]
}

Step 5 — Full verification command sequence

# 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", ... }

Policies

Organizations can define rules that are evaluated on every verification. Policies are configured in the Veris Console.

Policies can only restrict, never grant. There is no ALLOW effect. A policy can deny an action, force human review, or raise the required trust score. It can never grant a capability an agent's passport does not already carry, and it can never override an explicit denial. The capability scope check always runs first and is absolute.
EffectBehavior
DENYBlocks the action outright
REVIEWForces a REVIEW decision requiring human approval
REQUIRE_SCORERaises the minimum trust score for matching actions

Conditions

All condition fields are optional and AND-combined; an empty field matches anything.

  • • Capabilities — supports verb:* wildcards
  • • Risk levels
  • • Deployment environments
  • • Jurisdictions
  • • Agent name substring
  • • Relying parties
  • • Optional UTC time window

Matching policies are returned in the verify response as matchedPolicies.

Trust evidence & scoring

Veris standardizes the trust evidence. The scoring model is a reference implementation you can replace.

ComponentWhat it measures
identityCertificate validity, key storage, rotation age, revocation freshness
behavioralDeviation from the declared behavioral baseline
compliancePolicy checkpoint adherence, human-approval compliance
historicalTime-decayed incident and attestation history (90-day half-life)
environmentalDeployment context, jurisdiction, request risk level

Reference scoring model

trustScore =
  0.30 × identity +
  0.25 × behavioral +
  0.20 × compliance +
  0.15 × historical +
  0.10 × environmental

TRUSTED ≥ 850 · ELEVATED ≥ 650 · STANDARD ≥ 400 · LOW ≥ 200
The protocol standardizes the components and how each is measured. It does not mandate how a relying party weighs them. Every verification response returns the raw 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.

Standardized

  • • The five components and their measurement
  • • Signed passport format and verification
  • • Capability scope model and precedence
  • • Audit event format and hash chain
  • • Request/response contract

Your choice

  • • The weight of each signal
  • • Tier thresholds
  • • Policies layered on top
  • • Whether to use the composite at all

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.

Audit trail

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": "…"
  }]
}

Revocation & attestations

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"
}

API reference

Base URL https://verisaegis.com/api/public/aegis. Route paths retain the protocol's original codename for backwards compatibility.

EndpointAuthPurpose
POST /issueAPI keyRegister an agent and issue a signed passport
POST /verifyAPI keyLive trust decision with revocation and policies
POST /revokeAPI keyRevoke a passport
POST /attestAPI keyRecord an attestation or incident
GET /auditAPI keyRead hash-chained audit events
GET /passportsAPI keyList passports for the organization
GET /.well-known/jwks.jsonNonePublic signing keys in JWK Set format
POST /verify-passportNoneVerify a passport JWT signature and expiry

GET /api/public/aegis/.well-known/jwks.json

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.

POST /api/public/aegis/verify-passport

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" }
This endpoint does not check revocation. Use POST /verify for a live trust decision.

SDKs

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 GitHub

Security posture

Signed 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.