Protocol Reference
This page defines every ANIP endpoint, request/response schema, and data type. It is the implementation reference — use it alongside the concept pages (Capabilities, Delegation, Failures, Trust) which explain the why.
Endpoints
An ANIP HTTP service exposes 9 standard endpoints:
| Endpoint | Method | Auth | Section |
|---|---|---|---|
/.well-known/anip | GET | None | Discovery |
/.well-known/jwks.json | GET | None | JWKS |
/anip/manifest | GET | None | Manifest |
/anip/tokens | POST | Bearer | Token Issuance |
/anip/permissions | POST | Bearer | Permission Discovery |
/anip/invoke/{capability} | POST | Bearer | Invocation |
/anip/audit | POST | Bearer | Audit |
/anip/checkpoints | GET | None | Checkpoints |
/anip/checkpoints/{id} | GET | None | Checkpoint Detail |
Discovery
GET /.well-known/anip
No authentication required. This is the entry point for any agent discovering the service.
Response
{
"anip_discovery": {
"version": "0.11.0",
"service_id": "travel-service",
"endpoints": {
"manifest": "/anip/manifest",
"tokens": "/anip/tokens",
"permissions": "/anip/permissions",
"invoke": "/anip/invoke/{capability}",
"audit": "/anip/audit",
"checkpoints": "/anip/checkpoints"
},
"capabilities": {
"search_flights": {
"description": "Search available flights",
"side_effect": { "type": "read" },
"minimum_scope": ["travel.search"],
"financial": false
},
"book_flight": {
"description": "Book a flight reservation",
"side_effect": { "type": "irreversible" },
"minimum_scope": ["travel.book"],
"financial": true
}
},
"trust": {
"level": "signed",
"anchoring": { "cadence": "hourly" }
},
"metadata_disclosure": {
"caller_class": "all",
"failure_detail": "full"
}
}
}
Fields
| Field | Type | Required | Description |
|---|---|---|---|
version | string | Yes | Protocol version (e.g., "0.11.0") |
service_id | string | Yes | Unique service identifier |
endpoints | object | Yes | Map of operation names to URL paths |
capabilities | object | Yes | Lightweight capability summaries (name → metadata) |
trust | object | Yes | Trust posture: level (declarative, signed, anchored) and optional anchoring cadence |
metadata_disclosure | object | No | Controls what metadata is disclosed to different caller classes |
Each capability summary in discovery includes description, side_effect.type, minimum_scope[], and financial (boolean). The full declarations are in the manifest.
JWKS
GET /.well-known/jwks.json
No authentication required. Returns the service's public signing keys in standard JWKS format.
Response
{
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"x": "dGhpcyBpcyBhIHB1YmxpYyBrZXk...",
"kid": "primary-signing-key",
"use": "sig"
}
]
}
Used to verify: manifest signatures (X-ANIP-Signature header), delegation token JWTs, and checkpoint signatures.
Manifest
GET /anip/manifest
No authentication required. Returns the full capability declarations with a cryptographic signature.
Response headers
X-ANIP-Signature: eyJhbGciOiJFZERTQSJ9...
Response body
{
"manifest_metadata": {
"version": "0.11.0",
"sha256": "a1b2c3d4...",
"issued_at": "2026-03-28T10:00:00Z",
"expires_at": "2026-03-29T10:00:00Z"
},
"service_identity": {
"id": "travel-service",
"jwks_uri": "/.well-known/jwks.json",
"issuer_mode": "self"
},
"trust": {
"level": "signed",
"anchoring": { "cadence": "hourly" }
},
"capabilities": {
"search_flights": {
"description": "Search available flights between airports",
"contract_version": "1.0",
"inputs": [
{
"name": "origin",
"type": "airport_code",
"required": true,
"description": "Departure airport (IATA code)"
},
{
"name": "destination",
"type": "airport_code",
"required": true,
"description": "Arrival airport (IATA code)"
},
{
"name": "date",
"type": "date",
"required": false,
"description": "Travel date (ISO 8601)"
}
],
"output": {
"type": "flight_list",
"fields": ["flight_number", "origin", "destination", "price"]
},
"side_effect": {
"type": "read"
},
"minimum_scope": ["travel.search"],
"cost": { "certainty": "fixed" },
"response_modes": ["unary"],
"observability": {
"logged": true,
"retention": "90d"
}
},
"book_flight": {
"description": "Book a flight reservation",
"contract_version": "1.0",
"inputs": [
{ "name": "flight_number", "type": "string", "required": true },
{ "name": "passengers", "type": "integer", "required": true, "default": 1 }
],
"output": {
"type": "booking_confirmation",
"fields": ["booking_id", "status", "total_cost"]
},
"side_effect": {
"type": "irreversible"
},
"minimum_scope": ["travel.book"],
"cost": {
"certainty": "estimated",
"financial": {
"currency": "USD",
"range_min": 200,
"range_max": 800,
"typical": 420
}
},
"requires": [
{ "capability": "search_flights", "reason": "must verify flight exists" }
],
"response_modes": ["unary"],
"observability": {
"logged": true,
"retention": "365d",
"fields_logged": ["flight_number", "passengers"]
}
}
}
}
Capability declaration fields
| Field | Type | Required | Description |
|---|---|---|---|
description | string | Yes | Human-readable description |
contract_version | string | Yes | Semantic version of this capability's contract |
inputs | array | Yes | Input parameter declarations (see below) |
output | object | Yes | Output shape: type and fields[] |
side_effect | object | Yes | Side-effect declaration (see below) |
minimum_scope | string[] | Yes | Required scope strings for delegation |
cost | object | No | Cost declaration (see below) |
requires | array | No | Prerequisite capabilities |
response_modes | string[] | No | ["unary"], ["streaming"], or ["unary", "streaming"]. Default: ["unary"] |
observability | object | No | Logging and retention posture |
Input field
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Parameter name |
type | string | Yes | Semantic type hint (e.g., "string", "airport_code", "integer") |
required | boolean | No | Default: true |
default | any | No | Default value if not provided |
description | string | No | Human-readable description |
Side-effect types
| Value | Meaning |
|---|---|
read | No state change. Safe to call speculatively. |
write | Reversible state change. |
transactional | State change with a rollback window. Has optional rollback_window (duration) and compensation (capability name). |
irreversible | Permanent state change. Cannot be undone. |
Cost declaration
| Field | Type | Description |
|---|---|---|
certainty | string | "fixed", "estimated", or "variable" |
financial | object | Optional: currency, range_min, range_max, typical |
compute | object | Optional: expected_duration, resource hints |
determined_by | string | Optional: what determines the cost (e.g., "passenger_count") |
Token Issuance
POST /anip/tokens
Authentication: Bearer token (API key for bootstrap, existing JWT for delegation).
Request
{
"scope": ["travel.search", "travel.book"],
"capability": "book_flight",
"subject": "agent-007",
"purpose_parameters": {
"task_id": "trip-planning-2026",
"budget_usd": 500
},
"ttl_hours": 2
}
| Field | Type | Required | Description |
|---|---|---|---|
scope | string[] | Yes | Requested scope strings |
capability | string | No | Specific capability this token is for |
subject | string | Yes (bootstrap) | Subject identifier for the delegated principal |
purpose_parameters | object | No | Opaque purpose constraints (budget, task context) |
ttl_hours | number | No | Token lifetime in hours. Default: 2 |
Response
{
"issued": true,
"token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"scope": ["travel.search", "travel.book"],
"capability": "book_flight",
"expires_at": "2026-03-28T12:00:00Z"
}
Delegation rules
- Scope can only narrow, never widen. A delegated token cannot have scope the parent doesn't have.
- Budget constraints in scope strings (e.g.,
travel.book:max_$500) are enforced at invocation time. - The service signs tokens with its Ed25519 key pair. Any replica with the same key material can verify them.
Permission Discovery
POST /anip/permissions
Authentication: Bearer JWT delegation token.
Request
{}
Response
{
"available": [
{
"capability": "search_flights",
"scope_match": "travel.search",
"constraints": {}
}
],
"restricted": [
{
"capability": "book_flight",
"reason": "missing scope: travel.book",
"grantable_by": "human:[email protected]"
}
],
"denied": [
{
"capability": "admin_reset",
"reason": "requires admin principal class"
}
]
}
Three-bucket model
| Bucket | Meaning |
|---|---|
available | Token has sufficient scope. Fields: capability, scope_match, constraints |
restricted | Missing a grantable scope. Fields: capability, reason, grantable_by |
denied | Structurally impossible (wrong principal class). Fields: capability, reason |
Invocation
POST /anip/invoke/{capability}
Authentication: Bearer JWT delegation token.
Request
{
"parameters": {
"origin": "SEA",
"destination": "SFO"
},
"client_reference_id": "task:abc/step-3",
"stream": false
}
| Field | Type | Required | Description |
|---|---|---|---|
parameters | object | Yes | Capability input parameters |
client_reference_id | string | No | Caller-supplied correlation ID (max 256 chars), echoed in response |
stream | boolean | No | Request streaming response (SSE). Default: false |
Success response (HTTP 200)
{
"success": true,
"invocation_id": "inv_7f3a2b4c5d6e",
"client_reference_id": "task:abc/step-3",
"result": {
"flights": [
{ "flight_number": "AA100", "price": 420 },
{ "flight_number": "DL310", "price": 280 }
]
},
"cost_actual": {
"currency": "USD",
"amount": 0
}
}
Failure response (HTTP 4xx)
{
"success": false,
"invocation_id": "inv_8b2f4a7c9d0e",
"client_reference_id": "task:abc/step-3",
"failure": {
"type": "budget_exceeded",
"detail": "Requested booking costs $487.00 which exceeds the delegated budget of $200.00",
"retry": false,
"resolution": {
"action": "request_budget_increase",
"requires": "higher_budget_delegation",
"grantable_by": "human:[email protected]",
"estimated_availability": "immediate"
}
}
}
Response fields
| Field | Type | Always present | Description |
|---|---|---|---|
success | boolean | Yes | Whether the invocation succeeded |
invocation_id | string | Yes | Server-generated unique ID (inv_{hex12}) |
client_reference_id | string | If provided in request | Echoed caller correlation ID |
result | object | On success | Capability-specific result data |
cost_actual | object | If capability has financial cost | currency and amount |
failure | object | On failure | Structured failure (see below) |
ANIPFailure schema
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Machine-readable failure category (e.g., scope_insufficient, budget_exceeded, rate_limited) |
detail | string | Yes | Human-readable explanation |
retry | boolean | Yes | Whether retrying the same call might succeed. Default: true |
resolution | object | Yes | Recovery guidance (see below) |
Resolution schema
| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | What to do (e.g., request_scope, request_budget_increase, wait) |
requires | string | No | What's needed to resolve |
grantable_by | string | No | Who can grant what's needed (principal identifier) |
estimated_availability | string | No | How soon resolution is possible (e.g., immediate, 24h) |
Audit
POST /anip/audit
Authentication: Bearer token. Results are scoped to the root principal of the caller's delegation chain — a principal can only see its own audit trail.
Request (query parameters)
| Parameter | Type | Description |
|---|---|---|
capability | string | Filter by capability name |
since | string | ISO 8601 timestamp — entries after this time |
invocation_id | string | Filter by specific invocation |
client_reference_id | string | Filter by caller correlation ID |
limit | integer | Maximum entries to return |
Response
{
"entries": [
{
"invocation_id": "inv_7f3a2b4c5d6e",
"capability": "search_flights",
"actor_key": "agent:booking-bot",
"root_principal": "human:[email protected]",
"event_class": "low_risk_success",
"success": true,
"client_reference_id": "task:abc/step-3",
"timestamp": "2026-03-28T10:30:00Z"
}
]
}
Event classification
| Class | When used |
|---|---|
low_risk_success | Read capability succeeded |
high_risk_success | Write/irreversible/financial capability succeeded |
low_risk_failure | Read capability failed |
high_risk_failure | Write/irreversible/financial capability failed |
Checkpoints
GET /anip/checkpoints
No authentication required.
Query parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum checkpoints to return. Default: 20 |
Response
{
"checkpoints": [
{
"checkpoint_id": "cp_a1b2c3",
"sequence": 42,
"merkle_root": "sha256:7d3f8a...",
"entry_count": 150,
"created_at": "2026-03-28T11:00:00Z",
"signature": "eyJhbGciOi..."
}
]
}
Checkpoint Detail
GET /anip/checkpoints/{id}
Returns a single checkpoint with optional consistency proof fields.
Response
{
"checkpoint_id": "cp_a1b2c3",
"sequence": 42,
"merkle_root": "sha256:7d3f8a...",
"entry_count": 150,
"created_at": "2026-03-28T11:00:00Z",
"signature": "eyJhbGciOi...",
"tree_size": 150,
"tree_head": "sha256:7d3f8a..."
}
JSON Schema
Machine-readable JSON Schema definitions are maintained alongside the spec:
schema/anip.schema.json— All ANIP types:DelegationToken,CapabilityDeclaration,PermissionResponse,InvokeRequest,InvokeResponse,CostActual,ANIPFailure,ResponseMode,StreamSummaryschema/discovery.schema.json— Discovery document schema
The spec (SPEC.md) is authoritative for semantics. The schemas are authoritative for structure.