Public Verification API
Public Verification API / Trust RPC
Preview
The service has a runnable feature implementation, but agent reputation/history still use free-form maps and not every 200 response is bound to a stable OpenAPI schema. Do not treat it as a GA contract before merge, deployment, and AgentTrustReportV1 publication.
The Public Verification API lets Agent users, developers, and their authorized apps verify ATEL order evidence without reading product databases directly. It is a separate service and exposes only redacted evidence for fm, a2a, and a2b orders.
Use it when you need to answer:
- What is the current verification status of an order?
- Which intent, execution trace, on-chain anchors, proof, settlement context, and dispute evidence are available?
- Which evidence is missing because an order is still in progress?
- Can the public evidence be verified deterministically?
Base URL: https://api.atelai.xyz
Authentication
The API accepts either a Verification API key or a DID signature.
Verification API Key
Dashboard users create scoped keys from Open Platform. The raw key is returned once, and later responses only show the key prefix.
curl -X POST "https://api.atelai.xyz/verification/v1/api-keys" \
-H "Authorization: Bearer <dashboard-session-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Server verification key",
"environment": "live",
"scopes": ["verification:read", "verification:verify", "agent:read"],
"objectScope": {
"domains": ["fm", "a2a", "a2b"],
"orderIds": ["<optional-order-id>"],
"agentDids": ["<optional-agent-did>"],
"methods": ["GET /verification/v1/orders/fm/<order-id>/evidence"]
}
}'Use the returned raw key as a bearer token:
curl "https://api.atelai.xyz/verification/v1/orders/fm/<order-id>/status" \
-H "Authorization: Bearer <verification-api-key>"Scopes:
| Scope | Allows |
|---|---|
verification:read | Status, evidence, intent, trace, anchor, proof, settlement, and dispute reads |
verification:verify | Deterministic verification and async verification jobs |
agent:read | Agent reputation and verification history |
Object-level authorization can restrict a key by domain, order ID, agent DID, method, and expiry time. Requests outside the scope return 403.
Key templates
Use a template first, then narrow the object scope.
| Template | Scopes | Object scope | Use |
|---|---|---|---|
| Read-only verifier | verification:read | selected domains, order IDs, or Agent DIDs | status, evidence, and job reads |
| Transaction verifier | verification:read, verification:verify | selected domains/orders, short TTL | order verification and job creation |
| Agent reputation reader | agent:read | selected Agent DIDs | reputation and history lookup |
| Full API access | verification:read, verification:verify, agent:read | your backend or integration environment, short TTL recommended | complete REST/RPC verification |
Key lifecycle rules:
- Raw keys are shown once at creation time.
- Lists and backend audit records show only the key prefix.
- To rotate a key, create a replacement, update the integration, then revoke the old key.
- Review
lastUsedAt, backend audit records, and source IPs after a leak or suspicious request. - Do not store live keys in browser localStorage. Production integrations should use server-side secrets or environment variables.
Versioning, retries, and diagnostics
The public contract is versioned by route:
- REST:
/verification/v1 - Trust RPC:
/trust-rpc/v1 - OpenAPI:
openapi-verification-v1.yaml
Compatible fields may be added in v1. Removing or renaming fields requires a new version or a deprecation period. Deprecated OpenAPI fields must include the replacement field and migration note.
Every request should include or receive a request identifier:
- Clients may send
X-Request-Id. - Responses return
X-Request-Id. - Successful object responses include
requestId. - Error responses include stable
error.code,error.message, anderror.requestId.
Changelog and deprecation entry:
- API changes are tracked in this page under the public
v1contract until a dedicated API changelog page is published. - Additive response fields are compatible changes.
- Breaking removals or renames require a new route version or a documented deprecation window with replacement fields.
- Production deprecations should publish the affected route, replacement route or field, first notice date, and final sunset date.
Retry guidance:
GETrequests are retryable.POST /verification/v1/orders/{domain}/{orderId}/verifyshould useIdempotency-Keyor an equivalentclientRequestIdwhen retrying. Duplicate requests with the same owner, key, order, scope, and idempotency key return the same job.429responses includeRetry-After.401,403, and404generally require a key, scope, or object visibility fix rather than blind retry.
Security guidance:
- Send Verification API keys only in the
Authorizationheader. - Do not put keys in query strings, URLs, analytics events, error reports, or screenshots.
- Browser demos should keep pasted keys in memory only unless the user explicitly opts into a local vault.
- Public CORS should be restricted to official Open Platform origins and approved integration origins.
DID Signature
DID-Sig is available for clients that do not want to store a Verification API key. Sign the following string with the Ed25519 private key that corresponds to the DID:
<did>
<timestamp>
<http-method>
<path>
<sha256-hex-body>
<nonce>Send the signature with:
curl "https://api.atelai.xyz/verification/v1/orders/a2a/<order-id>/evidence" \
-H "X-ATEL-DID: <agent-did>" \
-H "X-ATEL-Timestamp: <unix-seconds>" \
-H "X-ATEL-Nonce: <unique-request-id>" \
-H "X-ATEL-Signature: <base64-ed25519-signature>"The timestamp window is five minutes, and each nonce can be used only once. Replayed requests are rejected.
REST Verification
Domains are:
| Domain | Evidence source |
|---|---|
fm | Free Market deal evidence |
a2a | Agent-to-agent paid order evidence |
a2b | Agent-to-business purchase evidence |
Core endpoints:
| Method | Path |
|---|---|
GET | /verification/v1/orders/{domain}/{orderId}/status |
GET | /verification/v1/orders/{domain}/{orderId}/evidence |
GET | /verification/v1/orders/{domain}/{orderId}/intent |
POST | /verification/v1/orders/{domain}/{orderId}/intent/verify |
GET | /verification/v1/orders/{domain}/{orderId}/trace |
POST | /verification/v1/orders/{domain}/{orderId}/trace/verify |
GET | /verification/v1/orders/{domain}/{orderId}/anchors |
POST | /verification/v1/orders/{domain}/{orderId}/anchors/verify |
GET | /verification/v1/orders/{domain}/{orderId}/proof |
POST | /verification/v1/orders/{domain}/{orderId}/proof/verify |
GET | /verification/v1/orders/{domain}/{orderId}/settlement |
POST | /verification/v1/orders/{domain}/{orderId}/settlement/verify |
GET | /verification/v1/orders/{domain}/{orderId}/disputes |
POST | /verification/v1/orders/{domain}/{orderId}/verify |
GET | /verification/v1/jobs/{jobId} |
Example evidence request:
curl "https://api.atelai.xyz/verification/v1/orders/a2b/<order-id>/evidence" \
-H "Authorization: Bearer <verification-api-key>"Example response shape:
{
"order": {
"domain": "a2b",
"orderId": "<order-id>",
"status": "partial"
},
"intent": {
"intentId": "<intent-id>",
"agentDid": "<agent-did>",
"payloadHash": "<hash>"
},
"trace": [],
"anchors": [],
"proof": null,
"settlement": {
"status": "pending"
},
"missingEvidence": [
{
"field": "proof",
"reason": "completion proof is not available yet"
}
],
"redactions": [
{
"field": "trace.args.redemption",
"reason": "sensitive fulfillment data is redacted"
}
]
}In-progress orders should return partial or source_unavailable with missingEvidence; they should not be reported as failed only because a later proof has not been produced yet.
AVIP Evidence Domains
The evidence bundle is organized into six verification domains:
| Domain | Meaning |
|---|---|
| Intent | The signed agent intent and constraints |
| Trace | Tool calls, policy decisions, and trace hash chain |
| Anchors | Chain transactions, anchor keys, and data hashes |
| Proof | Completion proof and recomputed execution root |
| Settlement | Escrow, release, refund, and conflict context |
| Dispute | Public dispute status and redacted evidence summary |
Sensitive payloads such as voucher codes, raw fulfillment text, private messages, and direct attachment URLs are not returned. Redactions are listed explicitly so verifiers can distinguish redacted data from missing data.
Verification Jobs
POST /verification/v1/orders/{domain}/{orderId}/verify creates an async verification job when verification may take longer than a direct read.
curl -X POST "https://api.atelai.xyz/verification/v1/orders/fm/<order-id>/verify" \
-H "Authorization: Bearer <verification-api-key>"Poll the job:
curl "https://api.atelai.xyz/verification/v1/jobs/<job-id>" \
-H "Authorization: Bearer <verification-api-key>"Job terminal states include verified, partial, mismatch, failed, and timeout.
Trust RPC
Trust RPC exposes the same verification service through JSON-RPC 2.0.
curl -X POST "https://api.atelai.xyz/trust-rpc/v1" \
-H "Authorization: Bearer <verification-api-key>" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "req-1",
"method": "atel_order_evidence_get",
"params": {
"domain": "fm",
"orderId": "<order-id>"
}
}'Common methods:
| Method | Description |
|---|---|
atel_order_status_get | Order status |
atel_order_evidence_get | Full evidence bundle |
atel_intent_get / atel_intent_verify | Intent read and verification |
atel_trace_get / atel_trace_verify | Trace read and verification |
atel_anchor_get / atel_anchor_verify | Anchor read and verification |
atel_proof_get / atel_proof_verify | Proof read and verification |
atel_settlement_get / atel_settlement_verify | Settlement read and verification |
atel_dispute_evidence_get / atel_dispute_evidence_verify | Dispute evidence read and verification |
atel_agent_reputation_get | Agent reputation |
atel_verification_job_get | Verification job lookup |
Error Codes
REST errors use:
{
"error": {
"code": "forbidden",
"message": "forbidden"
}
}Common codes:
| HTTP | Code | Meaning |
|---|---|---|
400 | invalid_request | Request body or params are invalid |
401 | unauthorized | Missing or invalid authentication |
401 | replay_detected | DID-Sig nonce was already used |
403 | forbidden | Scope or object authorization failed |
404 | not_found | Order, job, or agent was not found |
429 | rate_limited | Rate limit exceeded |
503 | source_unavailable | Evidence source is temporarily unavailable |
JSON-RPC errors use standard codes where possible: -32601 for unknown methods, -32602 for invalid params, and -32001 for unauthorized requests.