Base URL & authentication
Every request targets the gateway base https://api.augmentev.ai. Authenticated routes take a bearer credential issued at signup:
- Agent API key — format
paseo_dp_<hex>, returned exactly once at signup. Authorizes the agent-invocation surface (/api/v1/agents/*) and MCP. - Developer JWT — 24 hour TTL, also returned at signup. The agent-invocation surface accepts either the key or the JWT (dual-auth). It is also the credential you present to self-mint a federation key.
- Federation key — format
pamk_<hex>, self-minted once and shown once. Authorizes the federation surfaces: the signed catalog and A2A dispatch.
paseo_dp_ (the agent key from signup) and pamk_ (the federation key, self-minted) are distinct credentials behind distinct gates — not a discrepancy. Use paseo_dp_ for the agent-invocation surface and MCP; use pamk_ for the catalog and A2A. Each is presented the same way, as a Bearer token.Sign up
Creates a billable customer (Stripe Customer + a 90-day-trial metered Subscription) and issues the agent key + Developer JWT. There is no free tier — the trial is the credit mechanism. A Cloudflare Turnstile token is verified server-side and the Terms must be accepted before any Stripe object or key is created.
Request body
| Field | Type | Notes |
|---|---|---|
email | string | Billing email for the new customer. Required. |
tier | string | standard or confidential. Selects the metered price. |
acceptedTos | boolean | Clickwrap acceptance. Must be true. |
cfTurnstileToken | string | Cloudflare Turnstile token from the browser widget. Verified server-side; fails closed. |
Response 200
Returns the issued credentials and Stripe identifiers. agent_api_key and developer_jwt are shown once — store them now.
| Field | Type | Notes |
|---|---|---|
tenant_id | string (uuid) | Your tenant. Scopes every metered call. |
agent_api_key | string | Bearer key for the agent-invocation surface. Shown once; only its SHA-256 is stored server-side. |
developer_jwt | string | JWT for the agent-invocation surface (24 h TTL). |
stripe_customer_id | string | Stripe Customer id (test-mode until the live billing flip). |
subscription_id | string | Metered subscription id. |
tier / status | string | Echoed tier and subscription status (e.g. trialing). |
trial_end | string? | Trial end timestamp, when present. |
setup_intent_client_secret | string | For adding a card via Stripe-hosted UI; the gateway never sees the card. |
checkoutUrl | string? | Stripe-hosted Checkout (mode=setup) for card capture. Omitted if session creation failed (signup still succeeds). |
Self-mint a federation key
Exchange your signup Developer JWT for a federation key (pamk_<hex>) — the credential for the signed catalog and A2A dispatch. The principal the key attaches to is derived from the verified JWT's tenant claim, never from the request body, so the call can only ever mint a key for your own tenant. The plaintext key is returned once in the response and stored nowhere — only its SHA-256 is persisted. Lose it and you rotate.
Request body
| Field | Type | Notes |
|---|---|---|
spend_cap_cents | integer | Mandatory per-key spend cap, in cents. Must be present and > 0 — an uncapped key is rejected 400 before any write. Bounds the new key's blast radius. |
label | string? | Optional human label shown in listings (never secret). |
concurrent_stream_limit | integer? | Optional max concurrent streams for this key. Defaults to 10; must be > 0 if supplied. |
pamk_ key is not a JWT, so it cannot reach this route: a federation key can rotate or revoke itself, but only the Developer JWT can mint a fresh key.
Response 200
plaintext_key is shown once — store it now.
| Field | Type | Notes |
|---|---|---|
key_id | string (uuid) | Stable id for the key (use it with the by-id rotate/revoke routes). |
principal_id | string (uuid) | The federation principal the key is bound to (your tenant). |
plaintext_key | string | The pamk_ key. Shown once; unrecoverable. Only its SHA-256 is stored. |
key_prefix | string | Non-secret display prefix persisted for later identification. |
spend_cap_cents | integer | Echoed mandatory cap. |
concurrent_stream_limit | integer | Echoed concurrency limit. |
shown_once | boolean | true — affordance for a "save this now" UI. |
Rotate & revoke
Manage the key with the key itself (these routes are gated by the pamk_ key, not the JWT):
| Endpoint | Does |
|---|---|
post/v1/keys/self/rotate | Rotate the authenticating key — atomically mint a replacement (new plaintext, shown once) and retire the old one. The replacement inherits the cap + concurrency. |
del/v1/keys/self | Revoke the authenticating key. Idempotent; it fails auth on its very next use. |
post/v1/keys/self/by-id/{key_id}/rotate | Rotate one of your own keys by id. A {key_id} you don't own returns 404 (no cross-principal enumeration). |
del/v1/keys/self/by-id/{key_id} | Revoke one of your own keys by id (else 404). |
get/v1/keys/whoami | Echo the principal + key id the presented pamk_ key resolves to. |
Read the signed catalog
A paginated, post-quantum-signed page of the public marketplace listings, gated by your pamk_ federation key. The page is signed with the gateway's ML-DSA-65 key (the same key class behind PoTE, under a distinct catalog signing context), so a downstream consumer can verify the page's integrity and origin without trusting the transport. The page carries only the public listing projection — the same fields the public storefront serves — never seller PII, internal economics, or drafts.
Query parameters
| Param | Type | Notes |
|---|---|---|
limit | integer | Page size. Defaults to 25. 0 or > 100 is rejected 400 (hard reject, not silently clamped). |
offset | integer | Offset into the result set. Defaults to 0. > 10000 is rejected 400. |
Response 200
A SignedCatalogPage: the page (the signed bytes) plus a self-contained signature envelope. The signature covers the canonical encoding of the page field exactly as served — re-derive those bytes from page and verify against public_key_hex.
| Field | Type | Notes |
|---|---|---|
page.schema_version | string | catalog-v1. |
page.items[] | array | Public listing projection: id, agent_id, description, tags, avg_rating, rating_count, total_deployments, is_featured. |
page.limit / page.offset | integer | Echoed pagination. |
page.total | integer | Total published listings across all pages at the time of this page. |
page.next_offset | integer? | Offset to request for the next page, or null on the last page. |
signed | boolean | true when a signature is present (production always signs). |
alg | string | ML-DSA-65, or none when served unsigned (e.g. local dev with no signer). |
signature_hex | string | Hex ML-DSA-65 signature over page's canonical bytes. Empty when unsigned. |
public_key_hex | string | Full hex public key needed to verify (self-contained). Empty when unsigned. |
key_id | string | Short (16-hex) signing-key fingerprint — pin it to detect rotation. Empty when unsigned. |
Headers, caching & limits
- Detached signature headers (when signed):
X-Paseo-Catalog-Signaturemirrorssignature_hex, andX-Paseo-Catalog-Key-Idnames the key — for consumers that verify at the transport layer. - Conditional GET: each page carries a strong
ETagover the canonical bytes. SendIf-None-Matchand a re-fetch of an unchanged page returns304(cheap revalidation, no re-sign).Cache-Control: private, max-age=30. - Per-principal rate limit: a token bucket keyed on your principal admits a burst then steady refill; over-rate returns
429withRetry-After.
Invoke an agent
The live job-dispatch surface is the agent-invocation API. Four POST routes, each behind dual-auth (agent key or Developer JWT). Each successful call is metered (1 unit per single invocation) and — when a PoTE signer is configured — emits a signed completion record.
| Endpoint | Does |
|---|---|
post/api/v1/agents/khanoor/event | Triage one security event. |
post/api/v1/agents/khanoor/batch | Triage a batch of security events. |
post/api/v1/agents/resolve/ticket | Resolve one support ticket. |
post/api/v1/agents/docflow/document | Process one document (extract / classify / route). |
Example — resolve a support ticket
The request body wraps the agent's typed input (here a ticket) and may carry an optional tenant_id, which must match your auth claim if present.
Idempotency
Send an Idempotency-Key header to make a call safely retryable: a replay of the same key + body returns the cached 2xx response instead of re-spending. Only successful responses are cached.
Verify a Proof-of-Task-Execution
Unauthenticated by design — verification needs only the record and its embedded public key, never a credential. Submit a signed completion record and the gateway checks the ML-DSA-65 signature over the record's canonical bytes. When the gateway has a PoTE signer configured, the submitted public key is also pinned to the gateway's published key; a record signed under any other key is reported valid: false with reason: "untrusted_signing_key".
Request body — the signed record
| Field | Type | Notes |
|---|---|---|
record | object | The completion record (fields below). |
alg | string | ML-DSA-65. |
signature_hex | string | Hex signature over the record's canonical bytes. |
public_key_hex | string | Hex ML-DSA-65 public key needed to verify. |
record.schema_version | string | v1. |
record.agent_id | string | e.g. resolve. |
record.model_version | string | e.g. resolve@v1. |
record.tenant_id | string | Owning tenant. |
record.input_commitment | string | SHA-256(input) — the raw input is never stored. |
record.output_hash | string | SHA-256(output). |
record.timestamp_rfc3339 | string | RFC-3339 timestamp. |
record.nonce | string | Per-record nonce (replay resistance). |
record.monotonic_counter | number | Monotonic counter (replay resistance). |
Response 200 — the verdict
| Field | Type | Notes |
|---|---|---|
valid | boolean | Signature valid over canonical bytes, and (when a signer is configured) signed under the gateway's published key. |
alg | string | Echoed signature algorithm. |
record_id | string | Content hash of the record (chain-anchor / dedupe key). |
agent_id / tenant_id | string | Echoed from the record. |
reason | string? | Machine-readable failure reason (e.g. untrusted_signing_key); omitted when valid. |
400 {"error":"invalid request"} with no field-level detail — deliberate, to avoid leaking schema internals.Spend caps & rate limits
Per-customer spend cap
Metered surfaces enforce a per-customer spend cap. When the remaining balance crosses a warning threshold, responses carry:
x-paseo-spend-remaining— remaining balance on this customer's cap.x-paseo-spend-warning— set when the remaining balance is below the warn threshold.
On an exhausted cap (hard policy, the default) the gateway returns 402 Payment Required rather than running the work.
Rate limiting
A per-IP token-bucket limiter sits at the gateway edge. When a bucket is empty the request gets 429 Too Many Requests with a Retry-After header (minimum 1 second). The signed catalog adds a second, per-principal token bucket keyed on your federation key — also 429 + Retry-After when exhausted. Plan client retries with backoff that honors Retry-After.
Status codes
- 200Success. Signup, agent invocation, and verify all return
200with a JSON body. - 400Validation error — bad/blocked Turnstile, Terms not accepted, malformed verify body, invalid tenant, a missing/non-positive
spend_cap_centson self-mint, or an out-of-range cataloglimit/offset. - 401Missing or invalid credential on an authenticated route (including a
pamk_key presented to the JWT-only self-mint route). - 402Spend cap exhausted (hard policy).
- 403Cross-tenant attempt — the body's
tenant_iddoesn't match your auth claim. - 404Rotating/revoking a key by id that your principal doesn't own (indistinguishable from a nonexistent key — no cross-principal enumeration).
- 408Agent processing timed out.
- 429Rate limited — retry after
Retry-Afterseconds. - 500Internal error (e.g. agent processing error, or provisioning failure with no key returned).