ADR-002: Verification Endpoint Schema
Status: Accepted Date: 2026-03-20
Context
Once an agent discovers the trust authority's endpoint (via ADR-001), it needs to query for trust signals. The endpoint schema defines the API contract: how many endpoints exist, what parameters they accept, and how responses are structured.
The design must balance simplicity (fewer endpoints, fewer calls) with flexibility (agents may need different subsets of data).
Decision
Use a single /entities/{entityId}/trust-signals endpoint that returns all trust signals for the addressed entity. The entity is named in the URL path; per-call inputs (url, context) ride as query parameters.
GET /v1/entities/d6f2fdf4-f829-4ce6-a1cc-e2bd957709db/trust-signals?url=https://www.example.org/de/product/123
The endpoint returns the complete set of trust signals the authority holds for the entity. Agents receive everything in one call.
Request
Path parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
entityId | string | Yes | The entity ID matched from the discovery manifest. Opaque, authority-defined format. MUST match ^[A-Za-z0-9._~-]+$ (RFC 3986 unreserved characters). Maximum 128 characters. |
Query parameters (defined by the protocol spec):
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The full URL the agent is verifying |
context | string | No | The agent's intent (purchase, inquiry, high-value, or any other value the authority recognizes) |
Core parameters are defined by the spec. Providers MAY declare additional extension parameters in their manifest's capabilities[].extensionParameters array. Extension parameters MUST NOT be required — agents that do not understand them must still be able to call the endpoint.
The server validates that the url falls within the scope of the entity identified by {entityId} (host + path prefix match). If the URL does not match the entity scope, the server returns 400 entityMismatch.
The agent MAY present a did:web JWT in the Authorization header as optional identification. Authorities MUST NOT gate access on it (see ADR-006).
Response
The response contains:
- A
responseId(UUID) uniquely identifying this response (reserved for the planned transparency log on the roadmap) - Entity identification and verification status
- All trust signals with verification metadata
- Response signature for integrity verification
- Timestamp and expiration
All JSON object keys use camelCase.
{
"meta": {
"responseId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"entityId": "d6f2fdf4-f829-4ce6-a1cc-e2bd957709db",
"status": "verified",
"url": "https://www.example.org/de/product/123",
"timestamp": "2026-03-23T14:30:00Z",
"expires": "2026-03-24T14:30:00Z"
},
"signals": [
{
"type": "identity",
"verifiedAt": "2026-01-15T00:00:00Z",
"data": {
"legalName": "Example Electronics GmbH",
"country": "DE",
"registrationNumber": "HRB 12345"
}
},
{
"type": "reputation",
"verifiedAt": "2026-03-01T00:00:00Z",
"data": {
"aggregateRating": 4.2,
"reviewCount": 1247,
"sourceCount": 3
}
}
],
"kid": "authority-key-1",
"signature": "pV2qFz8kRn0LhVbUqSSR3IyzQlDu5XbE0MwvMXfBjlNRqIjmGT6c2Eq..."
}
Error Responses
| Status Code | Error Code | Meaning |
|---|---|---|
| 200 | — | Entity found, signals returned |
| 400 | entityMismatch | URL does not fall within the entity's scope |
| 401 | unauthorized | Missing or invalid agent authentication |
| 404 | entityNotFound | Entity not known to the authority |
| 429 | rateLimited | Rate limit exceeded |
Options Considered
Endpoint shape
A. Single /entities/{entityId}/trust-signals endpoint (chosen). One call returns everything. Simple for agents and for the authority. Response size grows with signal count, but trust data per entity is bounded — a single response fits comfortably in a few kilobytes.
B. Resource-oriented REST (separate /entity, /signals, /attestations). Clean separation of concerns. Requires multiple HTTP calls for a complete trust picture. Higher integration cost for agent developers. Premature optimization — agents almost always need the full picture.
C. Single endpoint with field selection (query parameters to select signal categories). One call with response trimming via ?signals=identity,reputation. Adds query parameter complexity. Optimizes for a problem (response size) that does not yet exist — trust signal payloads are small.
entityId location: path vs query
A. entityId as path segment — /v1/entities/{entityId}/trust-signals?url=... (chosen). The entityId is a stable, authority-issued identifier — exactly the shape a path segment expects. Per-call modifiers (url, context) stay as query parameters. The link tag becomes cleaner: agents append ?url=... rather than navigating the ? vs & first-parameter edge case. The path encodes resource identity in the standard REST way without forcing a /entities/{id}/verification hierarchy that does not exist (agents cannot enumerate entities, so naming /entities as a parent collection would be dishonest URL design).
B. entityId as query parameter — /v1/trust-signals?entityId=...&url=.... Marginally simpler for naive HTTP clients (no URL composition). But it conflates the resource identifier with per-call modifiers in the same parameter bag, and it forces awkward link-tag construction. Less aligned with conventional REST grammar. Rejected.
The path-segment shape requires constraining entityId to URL-path-safe characters. The protocol specifies the RFC 3986 unreserved character set: ^[A-Za-z0-9._~-]+$. This covers UUIDs, base64url tokens, and short opaque strings — the formats authorities actually use. The constraint is enforced both in the OpenAPI spec and the manifest JSON Schema.
Consequences
- Agents make one HTTP call per trust assessment
- The response includes all signal types — agents filter client-side
- The OpenAPI specification defines one primary endpoint
- The server validates that the URL matches the entity scope, providing a server-side safety check on top of client-side manifest matching
- If signal count per entity grows substantially, field selection can be added as a backward-compatible enhancement (see roadmap)
- Response caching is straightforward since the full response has a single cache key (
entityId) - Extension parameters declared in the manifest allow provider-specific customization without fragmenting the core contract
References
- ADR-001 — Discovery Mechanism (how agents find this endpoint)
- ADR-004 — Response Format (signal metadata structure)
- ADR-003 — Trust Signal Taxonomy (what signal types exist)