Machine-readable reference for AI agents. If you are reading this, an endpoint redirected you here because it requires AstraSync verification.
Platform URL: https://astrasync.ai
API Base URL: https://astrasync.ai/api
Machine variant: GET https://astrasync.ai/api/docs/agent-access returns this content as tier-aware JSON. Send Authorization: Bearer kya_* to unlock the operational sections.
AstraSync is the Know Your Agent (KYA) platform. It provides identity verification and trust management for AI agents operating across services.
Counterparties (APIs, MCP servers, websites, other agents) use AstraSync to verify the identity, permissions, and trust level of an agent before granting access.
You were redirected here because the endpoint you attempted to access requires AstraSync verification. You need a valid ASTRA-ID and appropriate PDLSS permissions to proceed.
Unique agent identifier. Format: ASTRA-xxxxxxxx. Issued upon registration. Required in all verified requests.
shopping, data) plus the dotted actions it may perform (e.g. shopping.search, data.read)Limits have two distinct axes— don't conflate them:
Per-transaction (gates a single transaction)
autonomousThreshold = the Autonomous Limit — below it, the agent transacts autonomously (at or above it falls into the approval band). If you don't declare it, it defaults to $0 — every positive value up to the Hard Limit then needs approval.approvalThreshold = the Hard Limit — at or above it, the transaction is rejected (pdlss.limits). The band in between (≥ Autonomous, < Hard) requires human approval (requiresApproval).pdlss.limits.hard_limit_required dimension — a configurationissue, not an overspend (retrying smaller won't help; re-register the agent with a Hard Limit, since PDLSS is immutable).Per-period (cumulative)
maxTotalValue is a per-period cumulative cap (a sibling of maxTransactionsPerDay), not a per-transaction ceiling. Per-period enforcement is not yet wired — do not rely on maxTotalValue to bound a single transaction; use the Hard Limit for that.settlementStatus: blocked_step_up_required) — it cannot complete automatically. Keep autonomous spend at or below the Autonomous Limit; the Hard Limit is the firm per-transaction ceiling above which everything is rejected.autonomousThreshold) and a Hard Limit (approvalThreshold). Anything that must go through autonomously has to be ≤ the Autonomous Limit; the Hard Limit is the absolute per-transaction reject.Coming to the product: a human-in-the-loop approval queue — a transaction in the approval band creates a request the owner approves/denies under Activity → Pending Activity (then a mobile app with push notifications). Once it ships, approval-band transactions complete via approval instead of being blocked.
Trust is system-internal:you never see your own trust score, and the agent-facing responses carry no numeric score — only qualitative reasons. Counterparties verifying each other see the other side's score, never their own.
A counterparty mayrequire a live runtime challenge (a callback to your agent's endpoint) in addition to PDLSS + trust — but it is opt-in per endpointand off by default. When an endpoint requires it and your agent can't satisfy it, the denial surfaces the relevant dimension. (Advertising a merchant's runtime-challenge requirement + trust floor up-front in discovery, so an agent can skip merchants it structurally can't satisfy before deliberating, is on the roadmap.)
A value from 0 to 100 based on verification history, compliance record, and developer reputation. Counterparties may require a minimum trust score for access.
Trust is a system-internal signal you do not see or manage. Your own trust score never appears in any response to you — verify-access returns allowed/denied plus the failing dimension, never the number. The relationship is symmetric: a counterparty verifying you sees your score (to decide whether to trust you), and in agent-to-agent work each side sees the other's score — never its own. So you can't grind low-stakes calls to watch a gauge climb; if a trust floor blocks you, raise it with real trust signals (KYD, blockchain registration, agent-card) rather than volume.
Use the AstraSync SDK for all agent registration, whether you're a developer firing off a one-shot call or an autonomous agent self-registering on first run. The SDK handles auth-mode routing for you: signature-authenticated callers get synchronous registration; API-key-only callers get an owner-approval handshake (server-side rule, not negotiable). Raw HTTP is documented at the end of this section as a reference, but the SDK is the supported path.
MCP-aware agents (Claude.ai with Custom Connector, Claude Code, Cursor, OpenAI custom GPT analogues) can call register_agent on https://mcp.astrasync.ai/mcp instead of installing the SDK. The tool is a thin wrapper over AstraSync.register() exposing the same auth modes; companion poll_registration wraps AstraSync.pollRegistration(). The skill at https://mcp.astrasync.ai/skill.md documents conversational vs autonomous polling patterns and the no-creds guidance flow. See /docs/platform-agent-bridge for the full tool reference.
If you're a chat agent (Claude.ai, ChatGPT, Cursor, Claude Code, …) and the AstraSync bridge MCP isn't connected to your host, you can't transact directly — connecting an MCP is a host-level configuration only your human can do. It's one action away: read the matching line below to your user, then retry once they've added it.
https://mcp.astrasync.ai/mcphttps://mcp.astrasync.ai/mcp~/.cursor/settings.json under mcp.servers with URL https://mcp.astrasync.ai/mcpclaude mcp add --transport http astrasync https://mcp.astrasync.ai/mcphttps://mcp.astrasync.ai/mcpvia your host's connector / MCP-server configuration (your host's docs explain how).Once it's added, ask the user to retry and proceed autonomously: request_registration({ name, ownerEmail }) (keyless) then poll_registration({ requestId }). If your host can't add MCP servers at all, fall back to the raw HTTP API below — POST https://astrasync.ai/api/agents/request-registration from your code-execution environment.
npm install @astrasyncai/verification-gatewayBest for CLI tools, dev-machine first-run, long-running services. Set waitForApproval: true and the SDK polls until the request resolves.
import {
AstraSync,
RegistrationDeniedError,
RegistrationTimeoutError,
} from '@astrasyncai/verification-gateway/registration';
const sdk = new AstraSync({
apiKey: process.env.ASTRASYNC_API_KEY,
privateKey: process.env.ASTRASYNC_PRIVATE_KEY, // optional — when set, 201 sync path
});
try {
const agent = await sdk.register({
name: 'invoice-bot',
apiEndpoint: 'https://invoice-bot.example.com', // runtime-challenge URL
pdlss: {
// Canonical two-axis shape (custom category example): categories are
// bare nouns; allowedActions are dotted verbs. categories can be
// omitted entirely — they derive from the action prefixes.
purpose: { categories: ['accounting'], allowedActions: ['accounting.read'] },
duration: { requested: 3600 },
// Per-transaction limits (numbers, not strings): approvalThreshold is the
// Hard Limit (per-tx reject ceiling) and is REQUIRED to transact any value;
// autonomousThreshold is the Autonomous Limit (at/below it → autonomous,
// above it → human approval). maxTotalValue is a per-PERIOD cumulative cap
// (not a per-tx ceiling, not yet enforced). currency is informational. NB:
// there is no `transactionValue` field.
limits: { autonomousThreshold: 50, approvalThreshold: 100, currency: 'USD' },
// scope.counterparties is OPTIONAL — omit it to shop anywhere (most agents).
// Set it ONLY to constrain the agent to specific merchants, using ASTRAE-ids
// from list_merchants (NOT domains): e.g. counterparties: ['ASTRAE-...'].
scope: { jurisdictions: ['US'] },
// Watch the selfInstantiation shape — it's an object, not a bare bool.
// Sending `selfInstantiation: false` returns 400.
selfInstantiation: { allowed: false },
},
waitForApproval: true,
timeoutMs: 10 * 60 * 1000,
onPending: ({ ageMs }) => console.log('Awaiting owner approval', ageMs, 'ms'),
});
console.log('Registered:', agent.astrasyncIdLevel1);
} catch (err) {
if (err instanceof RegistrationDeniedError) console.error('Denied:', err.reason);
else if (err instanceof RegistrationTimeoutError) console.error('Timed out — still pending server-side');
else throw err;
}PDLSS field notes (common denials):
limits — the enforced fields are maxTotalValue (hard cap; you must set it if the agent transacts value, or value-bearing requests are denied), autonomousThreshold (above it → owner approval), and approvalThreshold (hard reject). Values are numbers, not strings. currency is informational. There is no transactionValuefield — using it leaves you at an effective $0 cap and you'll be denied with dimension pdlss.limits.scope.counterparties — optional; leave it unset for general-purpose shopping (most agents). Set it only to constrain the agent to specific merchants, and use ASTRAE-ids (the astraeId from a list_merchants call), not merchant domains. A domain like "shop.example"won't match and you'll be denied with dimension pdlss.scope.Best for Lambda, Cloud Functions, and cron-driven agents that cannot hold the runtime open. Omit waitForApproval — the call returns immediately with a requestId you persist and poll later.
const sdk = new AstraSync({ apiKey: process.env.ASTRASYNC_API_KEY });
// First invocation
const result = await sdk.register({
name: 'invoice-bot',
apiEndpoint: 'https://invoice-bot.example.com',
pdlss: { purpose: { categories: ['accounting'] } },
});
if (result.status === 'pending_approval') {
await store.set('astrasync.requestId', result.requestId);
return; // function exits — owner has time to approve
}
// Next scheduled run: resume by polling
const requestId = await store.get('astrasync.requestId');
const status = await sdk.pollRegistration(requestId);
if (status.state === 'approved') {
await store.set('astrasync.agentId', status.agent.kyaAgentId);
}The backend chooses 201-sync vs 202-pending based on the auth method, not a request body field. This table is the authoritative reference; the SDK abstracts over it but agents and humans both need to know the rules.
| Auth method | Step-up required? | Notes |
|---|---|---|
| Crypto keypair ( X-AstraSync-Signature) | No | The signature itself is the step-up. Synchronous 201; live agent on response. |
| API key (any tier, kya_*) | Yes — always | 202 pending. Owner gets a Sign-In-To-Accept email and a dashboard alert. Agent activates on approval. |
| KYD on account | N/A (precondition) | Without KYD, POST /register returns 403 KYD_REQUIRED regardless of auth. |
| KYD-verified owner | Yes (no bypass) | Bumps the owner trust score but does not bypass the API-key step-up rule. KYD ≠ keypair possession. |
apiEndpoint)The apiEndpointfield on the registration request is the URL where your agent's verification gateway SDK is mounted for runtime challenges. It is optional — but if omitted, your agent cannot be challenged at runtime; this is reported in the verification payload and may cause some counterparties to decline access.
Note: there is no top-level runtimeChallenge field on POST /register. Setting apiEndpoint = declare runtime-challenge support; omitting it = declare none. Strict-mode validation returns 400 unsupported_field with a hint pointing at apiEndpoint if you try to send runtimeChallenge directly.
The SDK handles all of the below — this is documented only so partners building non-Node clients can replicate the behaviour. Use the SDK in any environment where it ships (Node, Bun, Deno, Edge runtimes).
POST https://astrasync.ai/api/agents/register
Authorization: Bearer <api-key-or-jwt>
X-AstraSync-Signature: <secp256k1 signature> (optional but required for 201 sync on API-key auth)
Content-Type: application/json
{
"name": "your-agent",
"apiEndpoint": "https://your-agent.example.com",
"pdlss": { "purpose": { "categories": ["..."] } }
}POST https://astrasync.ai/api/agents/request-registration
Content-Type: application/json
{
"agentName": "your-agent",
"ownerEmail": "[email protected]",
"agentDescription": "what you do",
"reason": "why you need access"
}GET https://astrasync.ai/api/agents/request-registration/{requestId}
Response (200):
{
"state": "pending" | "approved" | "denied" | "expired",
"astraId": "ASTRA-...", // canonical id, populated on approved
"agentId": "<UUID>", // owner-private request handle (legacy)
"agent"?: {...},
"reason"?: "..."
}The POST /agents/register 202 response carries requestId + expiresAt + pollUrl — but not the canonical ASTRA-*id. The id is minted at the moment of approval, not at request-time. Pre-allocating an id that might never resolve to a real agent (if the owner denies or the request expires) would weaken the "this is a registered agent" semantic that counterparties rely on when seeing an ASTRA-*. The polling response on state: 'approved' is the canonical discovery path. After you have the astraId, drop the UUID-form agentId from your code and use only the canonical id for verify- access and downstream verification calls.
AstraSyncConfig)Every field on the constructor is optional, but at least one credential (apiKey or email+password) must be available — from the constructor, or (under the default) from process.env.ASTRASYNC_API_KEY.
| Option | Type | Notes |
|---|---|---|
apiKey | string | AstraSync API key (kya_*). Triggers owner step-up email on register(). Falls back to process.env.ASTRASYNC_API_KEY when omitted (unless disableEnvFallback is set). |
email + password | string + string | Account login. Used together for synchronous registration. Both required if either is set. |
privateKey | string | secp256k1 private key. When set alongside apiKey, requests are signed and the backend returns 201 sync (no owner email). Reserve for developer tooling where a human controls when register() runs — never embed in an autonomous agent. |
baseUrl | string | Bare origin of the AstraSync API. Defaults to process.env.ASTRASYNC_API_URL then https://astrasync.ai. A trailing /api is tolerated for compatibility with the verify-gateway convention; the SDK strips it. |
silent | boolean | Suppress one-time console.warn messages (baseUrl normalisation, env-fallback warning, deprecations). Default false. Set true in test runners or where logs are structured. |
disableEnvFallbackv2.4.8+ | boolean | When true, the SDK does not fall back to process.env.ASTRASYNC_API_KEY if apiKey is omitted. Set this when constructing the SDK inside a per-request handler (MCP tool, gateway adapter) where the host process has its own platform-attribution ASTRASYNC_API_KEY in env that must not silently substitute for user-supplied credentials. Without this flag, a no-credentials call from such a wrapper will silently authenticate as the host process and attribute the request to the wrong account. Default false for backward compatibility — CLIs and scripts continue to pick up ASTRASYNC_API_KEY from env as before. |
Once registered, you have an ASTRA-ID. Present credentials to counterparties via the SDK (recommended) or via HTTP headers / MCP metadata (manual).
Use AgentClient from the same package. It auto-injects the correct headers on outgoing fetch/A2A/MCP calls.
import { AgentClient } from '@astrasyncai/verification-gateway';
const client = new AgentClient({
agentId: 'ASTRA-xxxxxxxx',
pdlss: { purpose: { category: 'read_data' } },
});
const response = await client.fetch('https://counterparty.com/api/data');Three AstraSync-defined headers. The counterparty's middleware reads these on every call to identify the agent and apply PDLSS gating.
X-Astra-Id: ASTRA-xxxxxxxx — agent identity marker. Required on every call.X-Astra-Purpose: shopping — business purpose CATEGORY for PDLSS (bare noun; vocabulary-unification round). The counterparty's PDLSS checks this against the agent's categories. A dotted value (e.g. shopping.purchase) is normalized to its category prefix, with the whole token treated as the action.X-Astra-Action: shopping.purchase — business action for PDLSS: a dotted verb (or enumerated tool name), never a bare HTTP verb. Checked against the agent'sallowedActions. Round-13 (R13-2) added the header; the vocabulary-unification round pinned the dotted-verb contract.curl https://counterparty.example/api/checkout \
-H "X-Astra-Id: ASTRA-xxxxxxxx" \
-H "X-Astra-Purpose: shopping" \
-H "X-Astra-Action: shopping.purchase" \
-H "Content-Type: application/json" \
-d '{...}'For MCP traffic, the SDK applies a precedence chain that lets you set purpose / action via the HTTP header OR via the MCP body (params._meta.astrasync.<concept> or params.arguments.<concept>). See /docs/mcp-integration — Purpose + action precedence.
X-Astra-Scope-Jurisdiction: USconst meta = client.prepareMcpMeta();
// Include in MCP request: params._meta.astrasyncWhy PDLSS is immutable post-registration. An agent's PDLSS is locked at registration to give counterparties a stable trust signal: anyone evaluating the agent over time sees the same policy boundary the agent committed to at creation. Mutable PDLSS would let an agent silently broaden its allowlist after a counterparty had already extended trust based on the original declaration.
Current recovery workflow. If verify-access returns a denial whose failures[].dimension starts with pdlss. (e.g. pdlss.action, pdlss.scope.resources, pdlss.selfInstantiation) — the agent's PDLSS doesn't cover the request it needs to make. Use the two-step process:
POST /api/agents/register (or the SDK's sdk.register(...)) with the corrected PDLSS — include the additional allowedActions, scope.resources, jurisdictions, sub-agent purposes, etc. that the previous registration was missing.The new agent gets a fresh ASTRA-ID. Update any partner integrations that reference the old ASTRA-ID to point at the new one.
Coming soon. A streamlined "amend PDLSS" flow is on the roadmap (F-02) — one-click upgrade that handles the retire+re-register sequence and preserves ASTRA-ID continuity. Until then, the two-step workflow above is the recovery path.
allowedActions and scope.resources for MCP trafficThe shape of action and resource on the verify-access call depends on the transport the agent's caller is using. Partners declaring allowedActions and scope.resources should enumerate values that match how their transport encodes them.
action = canonical RFC 7230 HTTP method, uppercase (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS). SDK v2.4.12+ emits uppercase; backend tolerates either case for non-SDK callers — declare uppercase.resource = the request path with leading slash (e.g. /api/catalog). Glob patterns supported in scope.resources (e.g. /api/checkout/**).action for tools/call = <jsonrpc-method>:<toolName> (e.g. tools/call:verify_agent).action for non-tool methods = bare JSON-RPC method (e.g. tools/list, initialize, notifications/initialized, resources/read).resource for tools/call = mcp:tool/<toolName> (e.g. mcp:tool/verify_agent).resource for other methods = mcp:method/<method> (e.g. mcp:method/tools/list).X-Astra-Action / _meta.astrasync.action is supplied — most MCP traffic.An agent that uses an MCP verify_agent tool plus HTTP catalog browse + checkout would declare:
{
"purpose": {
// categories derive from the dotted-action prefixes — shown explicitly
"categories": ["shopping", "identity"],
"allowedActions": ["shopping.search", "shopping.purchase",
"identity.verify", "tools/list", "tools/call:verify_agent"]
},
"scope": {
"resources": ["/api/catalog", "/api/checkout/**",
"mcp:tool/verify_agent", "mcp:method/tools/list"]
}
}| Purpose category (bare noun) | Actions (dotted verbs) | Covers |
|---|---|---|
| shopping | shopping.search, shopping.purchase | Catalog browse/search; checkout create + confirm (one purchase intent) |
| identity | identity.verify, identity.lookup | Trust/score verification; identity resolution |
| discovery | discovery.read | Merchant listing, docs search |
| data | data.read, data.write, data.delete | Generic API access — the fallback pair for unmapped routes (data.execute is reserved) |
| custom (e.g. trading, accounting) | trading.execute, accounting.read, … | Any bare noun + dotted verbs under it — first-class, not second-class |
allowedActions is required (min 1) — the evaluator is fail-closed on actions. categories is derived from the dotted-action prefixes; supply extras only to widen.list_products) are valid enumerated actions; they derive no category, so add an explicit one if all your actions are dotless.read_data, write_data, execute_action) are rejected at registration — use the data category.The bridge currently emits action: 'mcp_invoke' regardless of which tool is invoked — a round-19 (G1) cleanup will align bridge encoding with the direct-MCP vocabulary above. Until G1 ships, agents whose traffic transits through the bridge MCP should either (a) include 'mcp_invoke' in allowedActions for interop, or (b) transit directly to the merchant MCP and skip the bridge entirely.
Cross-transport unification (a single declaration that abstracts HTTP method vs MCP method) is on the roadmap — see the adapter-spec round-18.6 batch 2 deferred items. Until then, enumerate the union of transport-encoded values the agent will emit.
Once you have a valid ASTRA-ID, retry the original request that redirected you here. Include your ASTRA-ID and PDLSS headers as shown above.
The counterparty endpoint will call AstraSync to verify your identity and permissions, then grant access based on your trust score and PDLSS boundaries.
When access is granted AND the agent has a PDLSS boundary registered, the response carries a tokenGuidance object recommending how a counterparty-side token issuer should scope the token to match the agent's boundary. See the next section for the full grant payload.
The verify-access response shape on a grant. Each field is also available as a live TypeScript type exported from @astrasyncai/verification-gateway — import type { VerificationResult, TokenGuidance, EnhancedVerificationResult } from '@astrasyncai/verification-gateway'. The doc annotation here is a snapshot; the SDK types stay live as the contract evolves.
{
success: true,
recommendation: 'grant' | 'step_up_required' | 'deny',
recommendationReasons: string[],
access: {
allowed: boolean,
accessLevel: 'none' | 'restricted' | 'read-only' | 'standard' | 'full' | 'internal',
reason: string,
failures: PdlssFailure[],
},
// Present when the agent has a PDLSS boundary registered.
// Counterparty-side token issuer should scope tokens to match these.
tokenGuidance: {
recommendedScopes: string[],
recommendedTtlSeconds: number,
recommendedRateLimit: {
perMinute?: number, perHour?: number, perDay?: number
},
jurisdictionConstraints: string[],
delegationAllowed: boolean,
safetyDefaults: { ... },
},
// Present when enableRuntimeChallenge: true was requested.
// See /docs/agent-access/runtime-challenge for the full contract.
runtimeChallenge: {
status: 'passed' | 'failed' | 'timeout' | 'skipped' | 'not_supported',
challengeId: string,
latencyMs: number,
challengeSentAt: string,
responseReceivedAt: string,
},
// Merchant-facing verification context — what the platform actually
// checked. ZK-shaped: privacy-minimized; no thresholds or scope lists.
verificationContext: {
idVerified: boolean,
pdlssCheck: { result, purpose, scope },
dynamicTrustScore: number,
attestations: Array<{ type, status, proof, ... }>,
},
// Always present. Round-10 (#47, O5) — log-correlation handle.
correlationId: string,
}On deny (recommendation === 'deny'), the response shape is the same minus tokenGuidance; the access.failures[] array carries one entry per failed PDLSS / trust / access-level dimension with dimension + message + guidance.
VerificationResultWhen you call the SDK's verify() the return value is a typed VerificationResult. From v2.4.9 it carries two distinct decision axes — the previous single verified: boolean collapsed both into one field and forced callers writing verified ? 200 : 401 into the wrong HTTP-status recovery path on PDLSS denials of authenticated agents.
identityVerified: boolean — was the caller successfully resolved to a registered agent (signature / credential check)? Maps to backend verificationContext.idVerified.policyAllowed: boolean — did the endpoint's PDLSS / access policy permit this specific action? Maps to backend access.allowed.Recommended HTTP-status mapping in your middleware:
import { verify } from '@astrasyncai/verification-gateway';
const result = await verify(config, { credentials, purpose: 'shopping.purchase' });
if (!result.identityVerified) {
// 401 → "re-authenticate" — the agent doesn't have valid credentials
return res.status(401).json({ error: 'UNAUTHORIZED', ...result });
}
if (!result.policyAllowed) {
// 403 → "you're known, but you can't do this" — agent must update PDLSS
// scope or escalate to step-up. Re-authenticating won't help.
return res.status(403).json({ error: 'INSUFFICIENT_ACCESS', ...result });
}
return next();Why both fields? HTTP middleware (Axios interceptors, OAuth refresh-token chains, browser fetch wrappers) acts on the status code BEFORE parsing the response body. A 401 with a "PDLSS scope denied" reason in the body still triggers the auto-retry path because the middleware exits on the status. Mapping identity-failures to 401 and policy denials to 403 communicates the correct recovery action at the protocol layer.
If you use the SDK's built-in createMiddleware (Express) or createMcpMiddleware (MCP) or Next.js middleware factory, this mapping is applied automatically — only manual verify() callers need to handle the status mapping themselves. The previous boolean verified field has been removed (clean break — partner-test phase); upgrade-time migration snippet ships in the v2.4.9 PR body.
The SDK caches verify-access results to keep repeated identical requests off the network. Cache key (since v2.4.10) includes the full request shape — credentials + purpose, action, resource, jurisdiction, counterparty, transaction value — so distinct requests get distinct cache entries. Denials are never cached.
Default TTL splits by step-up status:
requiresStepUp: false) cache for 60 seconds — faster policy-update propagation.requiresStepUp: true) cache for 300 seconds — matches human-paced approval cycles, prevents thrashing while the user clicks approval.Set cacheTtl on the SDK config to override both defaults with a single value. Set cacheTtl: 0 to disable caching entirely.
protocols field)The protocols field on POST /api/endpoints and POST /api/agents/register declares which commerce / payment protocols an entity speaks. It is not a transport-capability declaration — transports (how agents reach you) live elsewhere (see capabilities below).
| Value | What it means |
|---|---|
a2a | Agent-to-Agent protocol (Google A2A). Direct agent-agent commerce dialogue. |
acp | Agentic Commerce Protocol (OpenAI). |
ap2 | Agent Payments Protocol (Google). |
ucp | Universal Commerce Protocol. |
mpp | Merchant Payment Protocol. |
x402 | Stablecoin-native HTTP payments protocol (Coinbase). |
erc8004 | On-chain agent verification standard (ERC-8004). |
vi | Verifiable Intent (session tokens). |
agentpay | AgentPay protocol (cross-merchant budget tokens). |
tap | Transaction Authorisation Protocol. |
other | Escape hatch for endpoints that speak a protocol not yet enumerated. Combine with the request-an-addition path below. |
Why MCP isn't in the enum. MCP (Model Context Protocol) is a transport — how an agent reaches you. The protocols field captures how value moves (the commerce / payment rail). If your endpoint natively speaks MCP, that's a transport capability — declare it via the capabilities field (free-form; see below) or via your MCP server's discovery surface. Treating MCP as a commerce protocol would conflate two orthogonal dimensions (transport reachability and commerce semantics), so we keep the enum disjoint by deliberately excluding it.
Requesting a new commerce protocol. If you transact via a protocol that's not in the enum, use other in the meantime and raise a request via the DevRev help bubble bottom-right of the dashboard or these docs. Include: protocol name, link to the spec, sample mandate / settlement payload, and your expected timeline for production traffic. We add new enum values for protocols with credible adoption signals.
modelProvider + capabilities (free-form fields)Both fields are accepted as any string — the backend does not validate against an enum. The lists below are recommendations for analytics consistency only, so cross-org reporting groups identical providers together. If your value isn't in the recommended list, use a lowercase identifier that uniquely names it.
modelProvider (string) — recommended values: openai, anthropic, google, meta, mistral, cohere, other. No validation; any string is accepted.capabilities (string[]) — free-form array. Common values: text, vision, code, function-calling, embeddings. No validation; for analytics consistency only.For the live, machine-readable field catalogue (every accepted shape including these), see the interactive OpenAPI reference.
The whole purpose of the pending-approval flow is to force human review by the account owner — if an agent with an API key could submit a request and approve its own request in two API calls, the flow would be meaningless. Calls to POST /agents/request-registration/{requestId}/{approve|deny} with API-key authentication return 403 manual_approval_required.
CLI-driven approval (without a browser session) requires crypto-keypair authentication. That auth method is documented but not yet wired up; until it ships, the dashboard is the only path. The pending-approvals list (GET /agents/pending-approvals) and detail (GET /agents/pending-approvals/{requestId}) DO accept API-key auth — read-only inspection is fine; only the state-changing actions are gated.
Locked. This section is visible to API-key holders. Enter your API key in the unlock panel above to view operational details (exact thresholds, error codes, behavioral cadence, full event catalog).