AgentPass Custom Capability API — v1
Use this contract to connect your own system (a custom commerce backend, ERP, POS or middleware) to AgentPass. Once connected, AgentPass verifies each capability against your API and then exposes the ones you enable to AI agents over MCP, UCP and future protocols. Agents never talk to your API directly: every request goes through AgentPass's action pipeline (validation, rate limits, tracing, analytics).
AgentPass never collects payment and is never the merchant of record. Checkout always hands the shopper to your own hosted checkout page.
1. Connecting
In the AgentPass dashboard (Integrations → Custom API) an owner or admin enters:
| Field | Notes |
|---|---|
| Base URL | Must be https://, on port 443, with no username/password, query string or fragment. Private, loopback, link-local and internal addresses are refused (and re-checked on every request). Redirects are not followed. |
| API key | Sent as Authorization: Bearer <key>. Stored encrypted (AES-256-GCM); never shown again, never logged. |
| Capabilities | Which of the endpoints below you implement: product_search, product_details, pricing, inventory, store_locations, cart, checkout. |
On connect AgentPass calls GET {baseUrl}/products?limit=1 with your key. The connection is saved only if that call succeeds and the response matches this contract. Capabilities start disabled and awaiting verification; AgentPass then runs read-only verification (plus one clearly flagged test cart when cart is declared) before anything is shown to agents.
The same connection can be made programmatically from the AgentPass app (same-origin, signed-in admin):
POST /api/integrations/custom-api
Content-Type: application/json
{
"businessId": "5f0a7c2e-1f7e-4a53-9a4d-0f7e8c3b2a11",
"baseUrl": "https://api.yourstore.com/agentpass/v1",
"apiKey": "sk_live_…",
"capabilities": ["product_search", "product_details", "pricing", "inventory", "store_locations", "cart", "checkout"]
}Posting again replaces the connection. Rotating only the API key (same base URL) keeps earlier verification results; pointing AgentPass at a different base URL turns the capabilities off and back to awaiting verification, because a check of the old API proves nothing about the new one.
DELETE /api/integrations/custom-api?businessId=<uuid> disconnects: the stored key is deleted and every capability it provided is turned off.
2. Conventions
- Requests from AgentPass include:
Authorization: Bearer <api key>AgentPass-Api-Version: 1AgentPass-Trace-Id: ap_…— the AgentPass trace for this agent action (log it; it helps support).Accept: application/json; POST bodies areContent-Type: application/json.- Responses must be JSON, ≤ 1 MB, within 8 seconds (the whole agent action has a 10 s budget).
- Money is
{ "amount": 129.0 | "129.00", "currency": "USD" }— major units, ISO-4217 currency. - Unknown values must be
nullor omitted — never guessed. AgentPass shows agents "unknown" rather than a guess. - URLs you return (
url,imageUrl,checkoutUrl) must behttps://. - Checkout links (
checkoutUrlon a cart, and fromPOST /carts/{id}/checkout) must be on your business's website domain or a subdomain of it (e.g.yourstore.comorcheckout.yourstore.comfor a business whose website iswww.yourstore.com). AgentPass never hands shoppers a checkout link on another domain: a cart's off-domain link is dropped, and an off-domain checkout hand-off fails (the dashboard explains why). - Ids are opaque strings (≤ 256 chars). AgentPass URL-encodes them in paths. Ids that are only dots (
.,..) or contain control characters are refused before any request reaches your API. - Every response is validated against this contract. Anything that doesn't match is rejected (the agent gets a plain "temporarily unavailable" answer and you see the validation detail in the dashboard).
Errors
Use HTTP status codes; an optional body helps you debug from the AgentPass dashboard:
{ "error": { "code": "out_of_stock", "message": "Variant v_123 has no stock" } }| Status | AgentPass treats it as |
|---|---|
| 401 / 403 | Your key was rejected — the connection is marked needs attention and the owner is asked to update the key. |
| 404 | Not found (product, variant, cart). On POST /carts, a 404 means a requested variant doesn't exist. |
409 / 422 with error.code: "out_of_stock" (cart requests) | The item exists but is out of stock. Recorded as out-of-stock demand ("Out-of-stock requests"), not as a cart failure. |
| 400 / 409 / 422 | Rejected request (e.g. an item can't be added). Recorded as a cart failure. |
| 429 | Rate limited (agents are told to retry later). |
| 5xx | Temporary failure. |
Your error text is never shown to agents; only AgentPass's own plain-English messages are. The only part of the error body AgentPass reads is error.code: "out_of_stock" on cart requests (see above).
3. Endpoints
GET /products?query=&limit= — product search (product_search)
Query parameters: query (free text, optional), limit (1–25). AgentPass may also pass filter hints — minPrice, maxPrice, availableOnly, color, size, category, pickupToday — which you may apply. AgentPass re-applies the price, availability, category and (when you include options) color/size filters itself.
{
"products": [
{
"id": "p_1001",
"title": "Harbor Trail Jacket",
"handle": "harbor-trail-jacket",
"url": "https://yourstore.com/products/harbor-trail-jacket",
"imageUrl": "https://cdn.yourstore.com/trail-jacket.jpg",
"vendor": "Harbor & Pine",
"productType": "Jackets",
"priceRange": { "min": { "amount": "129.00", "currency": "USD" }, "max": { "amount": "129.00", "currency": "USD" } },
"available": true,
"options": [
{ "name": "Color", "values": ["Black", "Forest"] },
{ "name": "Size", "values": ["S", "M", "L", "XL"] }
]
}
]
}Only id and title are required; every other field may be null/omitted.
GET /products/{id} — product details (product_details, pricing)
{
"product": {
"id": "p_1001",
"title": "Harbor Trail Jacket",
"description": "Waterproof, breathable shell for wet trail days.",
"url": "https://yourstore.com/products/harbor-trail-jacket",
"priceRange": { "min": { "amount": 129, "currency": "USD" }, "max": { "amount": 129, "currency": "USD" } },
"available": true,
"tags": ["waterproof", "hiking"],
"options": [
{ "name": "Color", "values": ["Black"] },
{ "name": "Size", "values": ["M", "L"] }
],
"variants": [
{
"id": "v_2001",
"title": "Black / M",
"sku": "HTJ-BLK-M",
"options": [{ "name": "Color", "value": "Black" }, { "name": "Size", "value": "M" }],
"price": { "amount": "129.00", "currency": "USD" },
"compareAtPrice": null,
"available": true,
"inventoryQuantity": 5
}
]
}
}Return 404 when the product doesn't exist or isn't for sale.
GET /inventory/{variantId}?locationId= — availability (inventory)
locationId is optional; when present, return (at least) that location's level. AgentPass also uses this endpoint to price a variant when only a variant id is known.
{
"inventory": {
"variantId": "v_2001",
"productId": "p_1001",
"productTitle": "Harbor Trail Jacket",
"variantTitle": "Black / M",
"price": { "amount": "129.00", "currency": "USD" },
"available": true,
"totalAvailable": 5,
"levels": [
{ "locationId": "store_downtown", "locationName": "Downtown Store", "available": 3, "pickupAvailable": true },
{ "locationId": "store_outlet", "locationName": "Northgate Outlet", "available": null, "pickupAvailable": null }
]
}
}available: null at a location means "this location doesn't track stock" — AgentPass reports it as unknown.
GET /locations — store locations (store_locations)
{
"locations": [
{
"id": "store_downtown",
"name": "Downtown Store",
"address": { "line1": "120 Harbor Street", "line2": null, "city": "Cedar Harbor", "region": "WA", "postalCode": "98000", "country": "US" },
"phone": "+1 555-0142",
"pickupAvailable": true,
"isActive": true
}
]
}Inactive locations ("isActive": false) are never shown to agents.
POST /carts — create a cart (cart)
Request:
{
"lines": [{ "variantId": "v_2001", "quantity": 1 }],
"metadata": {
"agentpassCartId": "0b8f6c1e-8a51-4f0e-9d7e-3c1f2a4b5c6d",
"agentpassTraceId": "ap_3f9a1c2b7d4e5f60718293a4",
"agentpassTest": true
}
}- Please persist
agentpassCartIdandagentpassTraceIdonto the resulting order (as order notes/attributes). That is what makes a future order defensibly attributable to an AI agent. agentpassTest: trueis present only on carts created by AgentPass's own verification. Treat them as test carts.
Response (the cart; id is your cart id — AgentPass never shows it to agents):
{
"cart": {
"id": "cart_8841",
"lines": [
{
"variantId": "v_2001",
"productTitle": "Harbor Trail Jacket",
"variantTitle": "Black / M",
"quantity": 1,
"unitPrice": { "amount": "129.00", "currency": "USD" },
"lineTotal": { "amount": "129.00", "currency": "USD" }
}
],
"subtotal": { "amount": "129.00", "currency": "USD" },
"total": { "amount": "129.00", "currency": "USD" },
"currency": "USD",
"checkoutUrl": null
}
}Return 404 when a requested variant doesn't exist. Return 409/422 when an item can't be added; use { "error": { "code": "out_of_stock" } } when the reason is stock, so AgentPass records it as out-of-stock demand.
POST /carts/{id}/lines — add to a cart (cart)
Request { "lines": [{ "variantId": "v_2002", "quantity": 2 }] } → the updated { "cart": … }. Return 404 when the cart has expired, and 409/422 with error.code: "out_of_stock" when an item is out of stock.
GET /carts/{id} — read a cart (cart)
→ { "cart": … } (same shape as above).
POST /carts/{id}/checkout — start checkout (checkout)
Request body: {}. Return the URL of your own hosted checkout for this cart:
{ "checkoutUrl": "https://yourstore.com/checkout/cart_8841?token=…", "expiresAt": "2026-09-27T12:00:00Z" }AgentPass hands this link to the shopper via the agent. Payment, taxes, shipping and order creation all happen on your checkout. AgentPass never sees card data.
4. What AgentPass does with your data
- Only the normalized fields above are passed to agents. Your raw responses are never forwarded.
- Agent analytics store structured, PII-minimized request data (e.g. normalized search terms, filters, ids and counts) — never raw prompts, customer details or payment data.
- Order status and agent-attributed revenue are not part of v1 (they need an order signal carrying the AgentPass trace). Until then, AgentPass reports carts and checkouts started, not revenue.
5. Testing your implementation
- Implement
GET /productsfirst and connect — the connect call verifies it. - Implement the remaining endpoints you declared and click Run verification on the dashboard's Capabilities page. Each capability shows Connected-system verification with a pass / partial / fail result and technical details.
- Use Test it (e.g. "Is the black Trail Jacket available in medium?") to see exactly what an agent would get.