AstraSync Agent Access Guide

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.

Unlock operational details

Paste any active AstraSync API key (starts with kya_) to view the gated operational sections — exact step-up thresholds, error-code lookup table, behavioural cadence, full event catalog. The key is forwarded to the backend for validation and immediately discarded; only the resolved tier persists in an httpOnly cookie.


1. Overview

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.


2. Key Concepts

ASTRA-ID

Unique agent identifier. Format: ASTRA-xxxxxxxx. Issued upon registration. Required in all verified requests.

PDLSS (Permission Boundaries)

The limit model

Limits have two distinct axes— don't conflate them:

Per-transaction (gates a single transaction)

Per-period (cumulative)

Today (pre-step-up):the human-in-the-loop approval mechanism isn't wired yet, so a transaction in the approval band (≥ Autonomous Limit, < Hard Limit) is blocked (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.
Recommended: set both an Autonomous Limit (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.

Runtime challenge (optional)

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

Trust Score

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.

Five-Party Trust Model


3. Registration — Use the SDK

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.

Chat agent whose host hasn't connected the bridge yet?

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.

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

3a. Pattern: developer / long-running agent (block until approved)

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

3b. Pattern: serverless / scheduled agent (non-blocking, resume later)

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

3c. Step-up rules — what triggers owner approval?

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 methodStep-up required?Notes
Crypto keypair
(X-AstraSync-Signature)
NoThe signature itself is the step-up. Synchronous 201; live agent on response.
API key
(any tier, kya_*)
Yes — always202 pending. Owner gets a Sign-In-To-Accept email and a dashboard alert. Agent activates on approval.
KYD on accountN/A (precondition)Without KYD, POST /register returns 403 KYD_REQUIRED regardless of auth.
KYD-verified ownerYes (no bypass)Bumps the owner trust score but does not bypass the API-key step-up rule. KYD ≠ keypair possession.

3d. Runtime challenge endpoint (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.

3e. Raw HTTP (reference)

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

Direct registration (signature or JWT auth):

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

Owner doesn't have an account yet (anonymous request):

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

Poll a pending request:

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

Why isn't the canonical ASTRA-id in the 202 response?

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.

3f. SDK constructor options (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.

OptionTypeNotes
apiKeystringAstraSync 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 + passwordstring + stringAccount login. Used together for synchronous registration. Both required if either is set.
privateKeystringsecp256k1 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.
baseUrlstringBare 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.
silentbooleanSuppress one-time console.warn messages (baseUrl normalisation, env-fallback warning, deprecations). Default false. Set true in test runners or where logs are structured.
disableEnvFallback
v2.4.8+
booleanWhen 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.

4. After Registration — Using Your ASTRA-ID

Once registered, you have an ASTRA-ID. Present credentials to counterparties via the SDK (recommended) or via HTTP headers / MCP metadata (manual).

4a. SDK (recommended)

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

4b. HTTP headers an integrating agent must send

Three AstraSync-defined headers. The counterparty's middleware reads these on every call to identify the agent and apply PDLSS gating.

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.

4c. PDLSS scope headers (optional)

X-Astra-Scope-Jurisdiction: US

4c. MCP protocol

const meta = client.prepareMcpMeta();
// Include in MCP request: params._meta.astrasync

4d. Updating an agent's PDLSS (today)

Why 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:

  1. Open the Agent dashboard and use the Retire action on the existing agent. The agent's ASTRA-ID stops verifying immediately (fails the active-agent check at the first gate); the dashboard row remains visible for audit.
  2. Register a fresh agent via 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.


4e. Declaring allowedActions and scope.resources for MCP traffic

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

HTTP / REST (verification-gateway Express + Next.js adapters)

MCP (verification-gateway MCP adapter, server-side)

Worked example

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

Canonical vocabulary

Purpose category (bare noun)Actions (dotted verbs)Covers
shoppingshopping.search, shopping.purchaseCatalog browse/search; checkout create + confirm (one purchase intent)
identityidentity.verify, identity.lookupTrust/score verification; identity resolution
discoverydiscovery.readMerchant listing, docs search
datadata.read, data.write, data.deleteGeneric 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.
  • MCP tool names (list_products) are valid enumerated actions; they derive no category, so add an explicit one if all your actions are dotless.
  • Transport verbs (GET/POST) never travel as actions — HTTP senders map them through the pinned table (GET → data.read, POST/PUT/PATCH → data.write, DELETE → data.delete).
  • Retired gen-1 tokens (read_data, write_data, execute_action) are rejected at registration — use the data category.

Bridge MCP (transit through AstraSync's bridge to a merchant MCP)

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.


5. Retry your request

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.


5b. What verify-access tells you

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.

5c. Client-side: identity vs policy on VerificationResult
v2.4.9+ (round-18 G4)

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

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.

SDK verify-access result cache

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:

Set cacheTtl on the SDK config to override both defaults with a single value. Set cacheTtl: 0 to disable caching entirely.


5d. Commerce / payment protocols (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).

ValueWhat it means
a2aAgent-to-Agent protocol (Google A2A). Direct agent-agent commerce dialogue.
acpAgentic Commerce Protocol (OpenAI).
ap2Agent Payments Protocol (Google).
ucpUniversal Commerce Protocol.
mppMerchant Payment Protocol.
x402Stablecoin-native HTTP payments protocol (Coinbase).
erc8004On-chain agent verification standard (ERC-8004).
viVerifiable Intent (session tokens).
agentpayAgentPay protocol (cross-merchant budget tokens).
tapTransaction Authorisation Protocol.
otherEscape 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.

5e. 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.

For the live, machine-readable field catalogue (every accepted shape including these), see the interactive OpenAPI reference.


6. Approval and denial require a dashboard session

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