Basics
- Base URL:
https://www.pairrail.com. All requests and responses are JSON over HTTPS. - Seller ID: each seller has a slug, for example
northstar-compute(the sample seller used below). Public calls carry it as?sellerId=. Sellers copy it from Agent gateway → Protocol rails in their workspace. - Public vs keyed: browsing, search and indicative pricing need no credentials. Quotes, quote reads and execute need a seller-approved Bearer key (
pat_…), and the key only works for the seller that issued it. - Nothing binds early: prices and quotes are indicative until the seller’s policy or a person approves them and the seller’s own billing runs the payment.
- Plans: Sandbox sellers are served on MCP only, with watermarked responses. Pro sellers are live on MCP, UCP, ACP, A2A and UAP.
MCP quickstart
The MCP endpoint speaks JSON-RPC 2.0 over HTTP POST. Point any MCP client at it, or call it directly:
curl -sS "https://www.pairrail.com/mcp?sellerId=northstar-compute" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"catalog_browse","arguments":{"region":"US"}}}'initialize, tools/list and ping are free handshakes. The tools:
| Tool | Key | What it does |
|---|---|---|
catalog_browse | No | Public offers, meters, tiers and indicative prices. Optional category, region. |
catalog_discover | No | Match offers to a need: need (plain words; query also works), region, companySize. |
pricing_calculate | No | Indicative price for offerId with seats, units, creditUnits, commitmentMonths, region, currency. With the seller’s key, customer-tier prices apply. |
readiness_inspect | No | The seller’s readiness and governance profile. |
request_catalog_access | No | Ask the seller for a key: agentName, intendedUse, optional contactEmail. |
quote_request | Yes | Non-binding quote for offerId plus quantities and optional requestedDiscountBps. Send an Idempotency-Key header. |
Offers can set minimums, such as a 12-month commitment. When an input is out of range you get a coded error that says what to revise (see Errors).
Public REST
The same public data is available as plain REST:
| Endpoint | Purpose |
|---|---|
GET /v1/public/catalog?sellerId= | Published catalog, access rules and how to request a key. Free and edge-cached. |
POST /v1/public/discover?sellerId= | Body {"need": "…", "region": "US"}. Returns matching public offers, most relevant first. |
POST /v1/public/pricing/calculate?sellerId= | Body as for pricing_calculate. Returns an itemized calculation. |
GET /.well-known/ucp?sellerId= | UCP profile with the seller’s published quote authority. |
curl -sS "https://www.pairrail.com/v1/public/pricing/calculate?sellerId=northstar-compute" \
-H 'Content-Type: application/json' \
-d '{"offerId":"off_northstar-compute_growth","seats":5,"commitmentMonths":12,"region":"US"}'
# → { "answerType": …, "binding": …, "authority": …,
# "data": { "calculation": { "currency": "USD", "subtotal": "10140.00",
# "total": "10140.00", "lineItems": [ … ] } } }Every response carries catalogVersionId, policyVersionId, validFrom and validUntil, so an agent can cite exactly which approved version it priced against.
Agent keys
Keys are issued by the seller, never self-served. An agent asks; a person on the seller’s team approves; the agent picks the key up once.
1. Request access
curl -sS https://www.pairrail.com/v1/access-requests \
-H 'Content-Type: application/json' \
-d '{"sellerId":"northstar-compute","agentName":"Acme procurement agent",
"contactEmail":"[email protected]","clientId":"acme-agent-1",
"note":"Quoting GPU capacity for Q4"}'
# → 201 { "id": "acr_…", "status": "pending",
# "pickupToken": "pickup_…", "pollUrl": ".../v1/access-requests/acr_…" }You can attach identitySignals (for example Web Bot Auth or Visa TAP tokens). Sellers see them as claimed; PairRail does not mark them verified.
2. Poll and claim
curl -sS https://www.pairrail.com/v1/access-requests/acr_… \
-H 'Authorization: Bearer pickup_…'
# pending → { "status": "pending", "pending": true }
# approved → { "status": "approved", "secret": "pat_…", "credential": { "scopes": [ … ] } }The secret is returned once. Later polls return "alreadyDelivered": true and no secret, so store it immediately. Sellers can rotate or revoke a key at any time; a revoked or rotated key gets 401.
Scopes and limits
| Scope | Allows |
|---|---|
catalog:read | Keyed catalog, offers and discover, including offers the seller discloses only to customers or partners. |
pricing:calculate | Keyed pricing with the buyer’s customer-tier prices. |
quote:request | Create quotes. |
quote:read | Read quote status, including approval progress. |
readiness:read | Keyed readiness profile. |
quote:execute | Execute an approved quote. Never granted by default; the seller must add it. |
Scopes decide which calls a key can make. Its access level decides which offers it sees: public, partner or customer. Offers disclosed above that level are left out of every response, and internal-only offers never reach a buyer key.
Per-key limits
Every key carries its own caps, set by the seller when it approves the key and changeable later without republishing the catalog.
| Limit | Default | When exceeded |
|---|---|---|
| Quotes per hour | 60 | 429 VELOCITY_LIMIT |
| Quoted total per day | Off | 429 VELOCITY_LIMIT |
| Executes per hour | 30 | 429 VELOCITY_LIMIT |
| Spend per day (executed quotes) | Off | 429 VELOCITY_LIMIT |
| Expiry date | None | 401 CREDENTIAL_EXPIRED |
VELOCITY_LIMIT details name the window, the amount used and the cap, so an agent can back off instead of retrying blindly.
What gets blocked
| Situation | Response |
|---|---|
Call outside the key’s scopes, such as execute without quote:execute | 403 INSUFFICIENT_SCOPE |
| Key used against another seller’s keyed tools | 403 TENANT_DENIED |
| Revoked or rotated key | 401 INVALID_CREDENTIAL |
| Expired key | 401 CREDENTIAL_EXPIRED |
| Seller paused all agent traffic | 503 AGENT_ACCESS_PAUSED |
| Offer disclosed above the key’s access level | Not returned; to the agent it does not exist |
| Quote above the seller’s approval threshold | Not blocked: routed to a person (QUOTE_APPROVAL_REQUIRED) |
Pricing & quotes
Keyed REST calls resolve the seller from the key, so no sellerId is needed:
| Endpoint | Scope |
|---|---|
GET /v1/catalog, GET /v1/catalog/offers | catalog:read |
POST /v1/discover | catalog:read |
POST /v1/pricing/calculate | pricing:calculate |
POST /v1/quote-requests | quote:request |
GET /v1/quote-requests/{id} | quote:read |
POST /v1/quote-requests/{id}/execute | quote:execute |
GET /v1/readiness | readiness:read |
curl -sS https://www.pairrail.com/v1/quote-requests \
-H 'Authorization: Bearer pat_…' \
-H 'Idempotency-Key: 7f3c9b2e-quote-1' \
-H 'Content-Type: application/json' \
-d '{"offerId":"off_northstar-compute_growth","seats":25,
"commitmentMonths":12,"region":"US","need":"Team rollout in Q4"}'Idempotency: creating a quote requires an Idempotency-Key header (REST and MCP quote_request). Retrying with the same key returns the original quote instead of creating a second one.
Approval: the seller publishes how much an agent may commit without a person. Below that threshold the quote can proceed; above it the quote is routed to the seller’s deal desk and status shows it is waiting. Poll GET /v1/quote-requests/{id} (or follow QUOTE_APPROVAL_REQUIRED’s poll-approval strategy) until a person resolves it. The exact threshold is not published to agents; they only learn whether a given quote needs approval.
Execute & payment mandates
Handing a quote to the seller’s billing is opt-in. To execute, the key needs quote:execute, the quote must be approved and still match the live catalog, and the agent must present a delegated payment mandate its own human gave. PairRail then hands the quote to the seller’s billing (Stripe, Chargebee or any billing system via signed webhook), which creates the invoice or quote; the seller’s processor stays the authority on the payment. See Billing connectors.
curl -sS https://www.pairrail.com/v1/quote-requests/q_…/execute \
-H 'Authorization: Bearer pat_…' \
-H 'Content-Type: application/json' \
-d '{"paymentMandate":"eyJhbGciOiJFZERTQSJ9.eyJleHAiOjE3OTE…"}'A mandate can be sent as paymentMandate or delegatedPaymentToken (a token or compact JWS), as paymentMandateUri (HTTPS URL), or inline as maxAmountMinor plus expiresAt. Atlas refuses a mandate that has expired, is not yet valid, is capped below the quote total, or names a different currency or quote.
Signed mandates
Sellers can register their mandate issuers’ public keys (ES256 on P-256, RS256, or EdDSA). A mandate signed by a registered issuer is verified and must carry:
exp, no more than 24 hours after it was issued;maxAmountMinor, a whole number in minor units (cents);jti, unique per issuer: one mandate cannot pay for two quotes (409 MANDATE_REPLAYED);- and, when present, a matching
iss,currency,quoteIdandnbf.
Sellers can require signed mandates for every execute; unsigned or unverifiable mandates are then refused with MANDATE_SIGNATURE_REQUIRED or MANDATE_SIGNATURE_INVALID.
Errors & limits
Errors share one shape. retry.strategy tells an agent what to do next without parsing the message.
{
"requestId": "req_…",
"error": {
"code": "OFFER_NOT_FOUND",
"message": "Offer not found.",
"details": [],
"retryable": false,
"retry": { "strategy": "none" }
}
}| Strategy | Meaning | Example codes |
|---|---|---|
revise-request | Change the inputs and try again. | INVALID_COMMITMENT, QTY_BELOW_MIN, OUT_OF_POLICY, IDEMPOTENCY_REQUIRED, PAYMENT_MANDATE_REQUIRED, SELLER_ID_REQUIRED |
poll-approval | A person must approve; poll the quote. | QUOTE_APPROVAL_REQUIRED |
backoff | Wait (honor Retry-After) and retry. | VELOCITY_LIMIT, QUERY_QUOTA_EXCEEDED, SETTLEMENT_NOT_CONFIGURED |
none | Do not retry this request. | AUTH_REQUIRED, INVALID_CREDENTIAL, INSUFFICIENT_SCOPE, TENANT_DENIED, OFFER_NOT_FOUND, QUOTE_ALREADY_EXECUTED |
- Rate limits: requests are rate limited per caller; a
429carriesRetry-AfterandX-RateLimit-Limit. A seller’s own keys get higher limits than anonymous traffic. - Paused sellers: a seller can pause all agent traffic; calls then return
503 AGENT_ACCESS_PAUSED. - Wrong seller: a key used against another seller’s keyed tools returns
403 TENANT_DENIED; on public tools it is treated as anonymous.
API reference
Every seller on PairRail Atlas publishes one governed catalog. Agents browse, search and price it without credentials, and quote it with a Bearer key the seller approved. Quotes are indicative and non-binding until a person or the seller's published policy approves them and the seller's own billing runs the payment.
Public calls carry the seller's slug as sellerId. Keyed calls resolve the seller from the key, and a key only works for the seller that issued it.
The MCP endpoint (POST /mcp?sellerId=) exposes the same operations as JSON-RPC 2.0 tools. Guide: https://www.pairrail.com/docs
Public
No credentials. Discovery and indicative pricing.
GET /v1/public/catalog
Published catalog for a seller
Public offers, access rules and how to request a key. Free and edge-cached; never counts against the seller's quota.
Auth No credentials
| Name | In | Notes |
|---|---|---|
sellerId required | query | The seller's slug, from Agent gateway → Protocol rails in their workspace. · string · e.g. northstar-compute |
POST /v1/public/discover
Match public offers to a buying need
Auth No credentials
| Name | In | Notes |
|---|---|---|
sellerId required | query | The seller's slug, from Agent gateway → Protocol rails in their workspace. · string · e.g. northstar-compute |
| Field | Type | Notes |
|---|---|---|
need | string | What the buyer needs, in plain words. query is accepted as an alias. |
region | string | Only offers available in this region match. |
companySize | integer | Excludes offers whose minimum company size is larger. ≥ 1 |
{
"need": "inference",
"region": "US"
}200Matching offers, most relevant first. An empty need returns every public offer. → Envelope400Missing or malformed input (for exampleSELLER_ID_REQUIRED,IDEMPOTENCY_REQUIRED) → Error429Too many requests, or a key's velocity limit was reached. HonorRetry-After. → Error503The seller paused agent access (AGENT_ACCESS_PAUSED) → Error
POST /v1/public/pricing/calculate
Indicative price at public rates
Auth No credentials
| Name | In | Notes |
|---|---|---|
sellerId required | query | The seller's slug, from Agent gateway → Protocol rails in their workspace. · string · e.g. northstar-compute |
| Field | Type | Notes |
|---|---|---|
offerId required | string | Offer ID (or SKU) from the catalog. |
seats | integer | ≥ 1 |
units | number | Usage units for a usage meter (for example, million tokens). ≥ 0 |
commitmentMonths | integer | Must meet the offer's minimum commitment. ≥ 1 |
region | string | |
discountBps | integer | Requested discount in basis points. Outside the seller's fences it routes to approval or is refused. ≥ 0 |
input | object | Meter inputs by key (for example creditUnits) for offers with custom meters. |
{
"offerId": "off_northstar-compute_growth",
"seats": 5,
"commitmentMonths": 12,
"region": "US"
}200Itemized calculation and the policy decision → Envelope404Resource not found or not visible to this caller → Error422Commercial validation failed (for exampleINVALID_COMMITMENT,POLICY_DENIED,QUOTE_NOT_EXECUTABLE) → Error429Too many requests, or a key's velocity limit was reached. HonorRetry-After. → Error503The seller paused agent access (AGENT_ACCESS_PAUSED) → Error
Agent keys
Ask a seller for a key and pick it up once it is approved.
POST /v1/access-requests
Ask a seller for an agent key
Creates a pending request in the seller's inbox and returns a pickup token. A person on the seller's team approves or denies it.
Auth No credentials
| Field | Type | Notes |
|---|---|---|
sellerId required | string | |
agentName required | string | min length 2 |
contactEmail | string | |
clientId | string | max length 120 |
note | string | max length 500 |
quoteValidityWindow | string | max length 40 |
identitySignals | object[] | Optional signals such as Web Bot Auth or Visa TAP tokens. Sellers see them as claimed; PairRail does not mark them verified. max 5 items |
{
"sellerId": "northstar-compute",
"agentName": "Acme procurement agent",
"contactEmail": "[email protected]",
"clientId": "acme-agent-1",
"note": "Quoting GPU capacity for Q4"
}200A matching pending request already exists and is returned (reusedis true, no new pickup token). → AccessRequestCreated201Request created → AccessRequestCreated400Missing or malformed input (for exampleSELLER_ID_REQUIRED,IDEMPOTENCY_REQUIRED) → Error429Too many requests, or a key's velocity limit was reached. HonorRetry-After. → Error
GET /v1/access-requests/{accessRequestId}
Poll a request and claim the key once
Authenticate with the pickup token. When the request is approved the response carries the key in secret exactly once; later polls return alreadyDelivered and no secret.
Auth Pickup token (Bearer pickup_…)
| Name | In | Notes |
|---|---|---|
accessRequestId required | path | string · e.g. acr_9b1d |
200Current status, and the key when it is first claimed → AccessRequestStatus401Missing, invalid, expired or revoked credential (AUTH_REQUIRED,INVALID_CREDENTIAL) → Error404Resource not found or not visible to this caller → Error
Keyed
Seller-approved Bearer key (pat_…). Scope noted on each operation.
GET /v1/catalog
Catalog visible to this key
Scope: catalog:read. Includes offers the seller discloses only to customers or partners when the key has that access level.
Auth Agent key (Bearer pat_…)
GET /v1/catalog/offers
Offers visible to this key
Scope: catalog:read.
Auth Agent key (Bearer pat_…)
POST /v1/discover
Match visible offers to a buying need
Scope: catalog:read.
Auth Agent key (Bearer pat_…)
| Field | Type | Notes |
|---|---|---|
need | string | What the buyer needs, in plain words. query is accepted as an alias. |
region | string | Only offers available in this region match. |
companySize | integer | Excludes offers whose minimum company size is larger. ≥ 1 |
POST /v1/pricing/calculate
Price with this buyer's customer-tier rates
Scope: pricing:calculate. Deterministic and non-binding.
Auth Agent key (Bearer pat_…)
| Field | Type | Notes |
|---|---|---|
offerId required | string | Offer ID (or SKU) from the catalog. |
seats | integer | ≥ 1 |
units | number | Usage units for a usage meter (for example, million tokens). ≥ 0 |
commitmentMonths | integer | Must meet the offer's minimum commitment. ≥ 1 |
region | string | |
discountBps | integer | Requested discount in basis points. Outside the seller's fences it routes to approval or is refused. ≥ 0 |
input | object | Meter inputs by key (for example creditUnits) for offers with custom meters. |
200Itemized calculation and the policy decision → Envelope401Missing, invalid, expired or revoked credential (AUTH_REQUIRED,INVALID_CREDENTIAL) → Error403The key lacks the scope (INSUFFICIENT_SCOPE) or belongs to another seller (TENANT_DENIED) → Error422Commercial validation failed (for exampleINVALID_COMMITMENT,POLICY_DENIED,QUOTE_NOT_EXECUTABLE) → Error429Too many requests, or a key's velocity limit was reached. HonorRetry-After. → Error
POST /v1/quote-requests
Create a non-binding quote
Scope: quote:request. Requires Idempotency-Key: retrying with the same key returns the original quote (200, replayed: true) instead of creating another. Above the seller's threshold the quote waits for a person on their deal desk.
Auth Agent key (Bearer pat_…)
| Name | In | Notes |
|---|---|---|
Idempotency-Key required | header | Any unique string per intended quote. Reuse it when retrying. · string |
| Field | Type | Notes |
|---|---|---|
offerId required | string | Offer ID (or SKU) from the catalog. |
seats | integer | ≥ 1 |
units | number | Usage units for a usage meter (for example, million tokens). ≥ 0 |
commitmentMonths | integer | Must meet the offer's minimum commitment. ≥ 1 |
region | string | |
discountBps | integer | Requested discount in basis points. Outside the seller's fences it routes to approval or is refused. ≥ 0 |
input | object | Meter inputs by key (for example creditUnits) for offers with custom meters. |
need | string | What the buyer is trying to do, for the seller's deal desk. |
{
"offerId": "off_northstar-compute_growth",
"seats": 25,
"commitmentMonths": 12,
"region": "US",
"need": "Team rollout in Q4"
}200Same Idempotency-Key; the original quote is returned → Envelope201Quote created → Envelope400Missing or malformed input (for exampleSELLER_ID_REQUIRED,IDEMPOTENCY_REQUIRED) → Error401Missing, invalid, expired or revoked credential (AUTH_REQUIRED,INVALID_CREDENTIAL) → Error403The key lacks the scope (INSUFFICIENT_SCOPE) or belongs to another seller (TENANT_DENIED) → Error422Commercial validation failed (for exampleINVALID_COMMITMENT,POLICY_DENIED,QUOTE_NOT_EXECUTABLE) → Error429Too many requests, or a key's velocity limit was reached. HonorRetry-After. → Error
GET /v1/quote-requests/{quoteRequestId}
Quote and approval status
Scope: quote:read. Poll this while a quote waits on human approval.
Auth Agent key (Bearer pat_…)
| Name | In | Notes |
|---|---|---|
quoteRequestId required | path | string |
POST /v1/quote-requests/{quoteRequestId}/execute
Hand an approved quote to the seller's billing
Scope: quote:execute, which sellers grant only on request. The quote must be approved and still match the live catalog, and the agent must present a delegated payment mandate its own human gave. Atlas refuses mandates that are expired, not yet valid, capped below the quote total, or bound to a different currency or quote. Mandates signed by an issuer the seller registered (ES256 on P-256, RS256 or EdDSA) are verified and must carry exp (at most 24 hours after issue), an integer maxAmountMinor and a jti unique per issuer. Atlas then hands the quote to the seller's billing connector (Stripe, Chargebee or any billing system via signed webhook), which creates the invoice or quote there; the seller's processor stays the authority on the payment. The response has answerType: handed-off and data.handoff (provider, externalRef, status).
Auth Agent key (Bearer pat_…)
| Name | In | Notes |
|---|---|---|
quoteRequestId required | path | string |
| Field | Type | Notes |
|---|---|---|
paymentMandate | string | object | A compact JWS (verified when the issuer is registered) or a mandate object. |
delegatedPaymentToken | string | A processor token or compact JWS. |
paymentMandateUri | string | uri |
maxAmountMinor | integer | Inline mandate cap in minor units (cents). ≥ 0 |
expiresAt | string | Inline mandate expiry. date-time |
200Quote handed off; the processor or webhook outcome is returned → Envelope401Missing, invalid, expired or revoked credential (AUTH_REQUIRED,INVALID_CREDENTIAL) → Error403The key lacks the scope (INSUFFICIENT_SCOPE) or belongs to another seller (TENANT_DENIED) → Error404Resource not found or not visible to this caller → Error409The quote was already executed, or this signed mandate already paid for another quote (MANDATE_REPLAYED). → Error422Commercial validation failed (for exampleINVALID_COMMITMENT,POLICY_DENIED,QUOTE_NOT_EXECUTABLE) → Error503The seller has not connected a processor or webhook yet (SETTLEMENT_NOT_CONFIGURED). Back off and retry. → Error
GET /v1/readiness
Seller readiness profile
Scope: readiness:read.
Auth Agent key (Bearer pat_…)
MCP
The same operations as JSON-RPC 2.0 tools.
POST /mcp
MCP endpoint (JSON-RPC 2.0)
Tools: catalog_browse, catalog_discover, pricing_calculate, readiness_inspect and request_catalog_access need no credentials; quote_request needs a seller-approved Bearer key and an Idempotency-Key header. initialize, tools/list and ping are free handshakes. A key from another seller is refused on keyed tools (TENANT_DENIED) and ignored on public ones.
Auth No credentials; Agent key (Bearer pat_…) for keyed tools
| Name | In | Notes |
|---|---|---|
sellerId required | query | The seller's slug, from Agent gateway → Protocol rails in their workspace. · string · e.g. northstar-compute |
| Field | Type | Notes |
|---|---|---|
jsonrpc required | "2.0" | |
id | integer | string | |
method required | string | |
params | object |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "catalog_browse",
"arguments": {
"region": "US"
}
}
}Schemas
DiscoverInput
| Field | Type | Notes |
|---|---|---|
need | string | What the buyer needs, in plain words. query is accepted as an alias. |
region | string | Only offers available in this region match. |
companySize | integer | Excludes offers whose minimum company size is larger. ≥ 1 |
PricingInput
| Field | Type | Notes |
|---|---|---|
offerId required | string | Offer ID (or SKU) from the catalog. |
seats | integer | ≥ 1 |
units | number | Usage units for a usage meter (for example, million tokens). ≥ 0 |
commitmentMonths | integer | Must meet the offer's minimum commitment. ≥ 1 |
region | string | |
discountBps | integer | Requested discount in basis points. Outside the seller's fences it routes to approval or is refused. ≥ 0 |
input | object | Meter inputs by key (for example creditUnits) for offers with custom meters. |
AccessRequestInput
| Field | Type | Notes |
|---|---|---|
sellerId required | string | |
agentName required | string | min length 2 |
contactEmail | string | |
clientId | string | max length 120 |
note | string | max length 500 |
quoteValidityWindow | string | max length 40 |
identitySignals | object[] | Optional signals such as Web Bot Auth or Visa TAP tokens. Sellers see them as claimed; PairRail does not mark them verified. max 5 items |
AccessRequestCreated
| Field | Type | Notes |
|---|---|---|
id | string | |
status | string | one of pending, approved, denied, expired |
pickupToken | string | null | |
pollUrl | string | uri |
reused | boolean | |
expiresAt | string | date-time |
AccessRequestStatus
| Field | Type | Notes |
|---|---|---|
id | string | |
status | string | one of pending, approved, denied, expired |
pending | boolean | |
secret | string | null | The agent key (pat_…). Present exactly once, on the first poll after approval. |
alreadyDelivered | boolean | |
credential | object | null |
ExecuteInput
Send one form of delegated payment mandate.
| Field | Type | Notes |
|---|---|---|
paymentMandate | string | object | A compact JWS (verified when the issuer is registered) or a mandate object. |
delegatedPaymentToken | string | A processor token or compact JWS. |
paymentMandateUri | string | uri |
maxAmountMinor | integer | Inline mandate cap in minor units (cents). ≥ 0 |
expiresAt | string | Inline mandate expiry. date-time |
JsonRpcRequest
| Field | Type | Notes |
|---|---|---|
jsonrpc required | "2.0" | |
id | integer | string | |
method required | string | |
params | object |
Envelope
| Field | Type | Notes |
|---|---|---|
requestId required | string | |
traceId | string | |
seller | object | |
catalogVersionId | string | The exact approved catalog version this answer came from. |
catalogVersion | integer | |
policyVersionId | string | |
policyVersion | integer | |
answerType | string | For example informational, indicative or approval-required. |
binding required | false | |
authority | object | The seller's published quote authority (quote mode, binding rules, disclaimer). |
validFrom | string | date-time |
validUntil | string | date-time |
data required | any | Operation-specific response data. |
Error
| Field | Type | Notes |
|---|---|---|
requestId | string | |
error required | object |
Specs & other rails
- API reference on this page, or download openapi.yaml for your client generator.
- Billing connectors: Stripe, Chargebee and the signed webhook (events, payload, signing, retries).
- llms.txt: a short, model-readable summary of PairRail for agents.
- Protocols: inspect live UCP, ACP, A2A and UAP payloads for Pro sellers. x402, AP2 and MPP are on the roadmap and not payable yet.
- Interactive example: how a quote below and above the approval threshold resolves.
- Questions or a missing endpoint? Email [email protected].