Agent Commerce Protocol Specification
The formal specification for ACP v2.0. This document defines the complete protocol for AI agent-to-brand commerce.
1. Introduction
The Agent Commerce Protocol (ACP) is an open standard that defines how AI shopping agents interact with brand storefronts. It provides a structured, machine-readable interface for product discovery, search, negotiation, and transactions.
Purpose
ACP enables any AI agent — whether it's ChatGPT, Claude, Gemini, or a custom shopping assistant — to query products, negotiate prices, and complete purchases from any ACP-compatible storefront using a single, consistent protocol.
Design Goals
- Simplicity: RESTful JSON APIs that any developer can implement in hours
- Machine-readability: Every response is structured for AI consumption, not human browsing
- Extensibility: Custom attributes and metadata without breaking the protocol
- Backward compatibility: New features never break existing integrations within a major version
Versioning
ACP uses semantic versioning. The current version is 2.0. Minor versions (2.1, 2.2) add features without breaking changes. Major versions (3.0) may introduce breaking changes with a 6-month deprecation window.
2. Protocol Overview
Architecture
ACP follows a three-tier architecture:
Request/Response Lifecycle
- Agent sends an authenticated request to the storefront API endpoint
- The storefront validates the API key, rate limits, and request schema
- The request is processed against the brand's catalog and policies
- A structured JSON response is returned with product data, negotiation state, or transaction status
- The agent parses the response and presents results to the user
Base URL
https://cresva.ai/api/storefront/{brandId}All endpoints are relative to this base URL. Replace {brandId}with the brand's unique identifier.
Content Type
All requests and responses use application/json. Requests must include the Content-Type: application/json header for POST/PUT/PATCH methods.
3. Discovery
Discovery allows AI agents to find ACP-compatible storefronts. Brands publish a discovery file at a well-known URL, similar to robots.txt but designed for AI agents.
Discovery File
Every ACP-compatible storefront MUST serve a JSON file at:
GET https://{domain}/.well-known/acp.jsonThe discovery file format:
{
"acp_version": "2.0",
"storefront_url": "https://cresva.ai/api/storefront/brand_abc123",
"brand_id": "brand_abc123",
"brand_name": "Acme Co",
"capabilities": [
"search",
"recommend",
"compare",
"negotiate",
"transact"
],
"supported_currencies": ["USD", "EUR"],
"supported_languages": ["en", "es", "fr"],
"rate_limits": {
"public": "100/minute",
"authenticated": "1000/minute"
},
"documentation": "https://developers.cresva.ai/protocol/spec"
}Discovery File Fields
acp_versionstringrequiredProtocol version. Currently "2.0".
storefront_urlstringrequiredThe base URL for all API requests to this storefront.
brand_idstringrequiredUnique identifier for the brand.
brand_namestringrequiredHuman-readable brand name.
capabilitiesstring[]requiredList of supported ACP features: search, recommend, compare, negotiate, transact.
supported_currenciesstring[]ISO 4217 currency codes accepted by this storefront.
supported_languagesstring[]ISO 639-1 language codes supported.
rate_limitsobjectRate limit information by key type.
documentationstringURL to the storefront's API documentation.
4. Query Protocol
The query protocol is the primary interface for agents to search and retrieve products. All queries go through a unified endpoint that supports multiple intent types.
Endpoint
POST /queryAgentQueryRequest
The request body for a query:
intentstringrequiredOne of: "search", "recommend", "compare", "detail", "review", "availability".
querystringNatural language query string. Required for search intent.
product_idsstring[]Product IDs for detail, compare, review, or availability intents.
filtersQueryFiltersStructured filters to narrow results.
contextQueryContextAdditional context about the user's shopping session.
sortstringSort order: "relevance", "price_asc", "price_desc", "rating", "newest".
offsetnumberPagination offset. Default: 0.
limitnumberResults per page. Default: 10, max: 50.
QueryFilters
categorystringProduct category path, e.g. "electronics/audio/headphones".
pricePriceRangePrice range with min, max, and currency.
attributesRecord<string, any>Key-value pairs for product attributes.
in_stockbooleanFilter to only in-stock products.
brandstringFilter by sub-brand or product line.
rating_minnumberMinimum average rating (1-5).
QueryContext
budgetstringUser's budget level: "budget", "moderate", "premium", "luxury".
preferencesstring[]User preferences that should influence ranking.
session_idstringSession ID for tracking multi-turn conversations.
platformstringThe AI platform making the request (e.g. "chatgpt", "claude").
AgentQueryResponse
productsAgentProductCard[]requiredArray of product cards matching the query.
totalnumberrequiredTotal number of matching products.
query_idstringrequiredUnique ID for this query (for analytics and follow-ups).
filters_appliedobjectEcho of which filters were actually applied.
suggestionsstring[]Alternative query suggestions if results are limited.
categoriesCategoryFacet[]Available category facets for refinement.
Example
POST /query
Authorization: Bearer pk_live_your_key_here
Content-Type: application/json
{
"intent": "search",
"query": "running shoes for marathon training",
"filters": {
"category": "sports/footwear/running",
"price": { "max": 180, "currency": "USD" },
"in_stock": true
},
"context": {
"budget": "moderate",
"preferences": ["cushioning", "durability"]
},
"limit": 5
}5. Product Card Format
The AgentProductCard is the standard format for representing a product to an AI agent. It is optimized for machine consumption — structured, typed, and rich with metadata.
AgentProductCard Fields
idstringrequiredUnique product identifier.
titlestringrequiredProduct title, optimized for AI readability.
pricenumberrequiredCurrent price.
currencystringrequiredISO 4217 currency code.
urlstringrequiredDirect URL to the product page.
descriptionstringProduct description, typically 1-3 sentences.
imagesImageObject[]Array of product images with URL, alt text, and dimensions.
attributesRecord<string, any>Structured product attributes (color, size, material, etc.).
reviews_summaryReviewsSummaryAggregated review data: average rating, count, and highlights.
availabilitystringStock status: "in_stock", "low_stock", "out_of_stock", "preorder".
trust_scoreTrustScoreBrand trust score with overall rating and tier.
comparison_highlightsstring[]Key differentiators vs. similar products.
brand_voice_summarystringHow the brand describes this product in their own voice.
original_pricenumberOriginal price before any discounts.
categoriesstring[]Category paths this product belongs to.
Example
{
"id": "prod_h7k2m",
"title": "ProSound ANC-300 Wireless Headphones",
"price": 179.99,
"currency": "USD",
"url": "https://acme.com/products/prosound-anc-300",
"description": "Premium over-ear wireless headphones with adaptive noise cancellation, 40-hour battery life, and memory foam cushions for all-day comfort.",
"images": [
{
"url": "https://cdn.acme.com/images/anc-300-black.jpg",
"alt": "ProSound ANC-300 in matte black",
"width": 1200,
"height": 1200
}
],
"attributes": {
"wireless": true,
"noiseCancelling": true,
"batteryLife": "40 hours",
"weight": "250g",
"color": "Matte Black",
"connectivity": "Bluetooth 5.3"
},
"reviews_summary": {
"average": 4.6,
"count": 2847,
"highlights": ["Excellent ANC", "All-day comfort", "Great battery"]
},
"availability": "in_stock",
"trust_score": {
"overall": 92,
"tier": "Gold"
},
"comparison_highlights": [
"40hr battery vs 30hr industry average",
"250g — lightest in class",
"Adaptive ANC with transparency mode"
],
"brand_voice_summary": "Engineered for audiophiles who refuse to compromise on comfort or sound quality.",
"original_price": 229.99,
"categories": ["electronics/audio/headphones", "electronics/audio/wireless"]
}6. Negotiation Protocol
The negotiation protocol enables AI agents to negotiate pricing with brand storefronts. This supports direct offers, counter-offers, and alternative deal structures.
Actions
initiateactionAgent sends an initial offer for a product.
counteractionBrand responds with a counter-offer.
acceptactionEither party accepts the current offer.
rejectactionEither party rejects and ends negotiation.
withdrawactionAgent withdraws their offer before a response.
inquireactionAgent asks what deals are possible without committing.
Endpoint
POST /negotiateNegotiation Request
actionstringrequiredOne of: "initiate", "counter", "accept", "reject", "withdraw", "inquire".
negotiation_idstringRequired for all actions except "initiate" and "inquire".
product_idstringrequiredThe product being negotiated.
offered_pricenumberThe price being offered (for initiate and counter).
currencystringCurrency of the offer. Default: storefront's primary currency.
quantitynumberNumber of units. Default: 1.
messagestringOptional natural language message with the offer.
State Machine
INITIATED ├── COUNTERING (brand sends counter-offer) │ ├── COUNTERING (agent counters back) │ ├── ACCEPTED (either party accepts) │ └── REJECTED (either party rejects) ├── ACCEPTED (brand accepts initial offer) ├── REJECTED (brand rejects) ├── EXPIRED (no response within timeout) └── WITHDRAWN (agent withdraws offer)
Alternative Deal Types
- Volume discount: Better price for buying multiple units
- Bundle: Discount when purchasing with related products
- Subscription: Lower per-unit price for recurring purchases
- Time-limited: Special price valid for a limited window
Timeout Rules
Negotiations expire after 24 hours of inactivity by default. Brands can configure shorter timeouts. The expires_at field in the response indicates when the current offer expires.
Example: Initiating a Negotiation
// Request
POST /negotiate
{
"action": "initiate",
"product_id": "prod_h7k2m",
"offered_price": 149.99,
"currency": "USD",
"quantity": 1,
"message": "User is comparing with a competitor at $145"
}
// Response
{
"negotiation_id": "neg_a1b2c3",
"status": "COUNTERING",
"original_price": 179.99,
"offered_price": 149.99,
"counter_price": 164.99,
"currency": "USD",
"message": "We can offer 8% off. Bundle with our carrying case for an additional 5% off.",
"alternatives": [
{
"type": "bundle",
"products": ["prod_h7k2m", "prod_case01"],
"bundle_price": 189.99,
"savings": "15%"
}
],
"expires_at": "2026-03-28T12:00:00Z"
}7. Transaction Protocol
The transaction protocol manages the full lifecycle of a purchase, from cart creation through payment, fulfillment, and completion.
Transaction Lifecycle
CREATED → CONFIRMED → PAID → FULFILLING → COMPLETED
↘ CANCELLED
↘ DISPUTED → RESOLVEDEndpoints
/transactionsCreate a new transaction/transactions/{id}Get transaction status/transactions/{id}/confirmConfirm a transaction/transactions/{id}/cancelCancel a transactionEscrow
ACP supports escrow for conditional purchases. Funds are held until conditions are met (e.g., product inspection, delivery confirmation). Escrow is managed through:
/transactions/{id}/escrow/releaseRelease escrowed funds to the seller/transactions/{id}/escrow/disputeDispute and hold escrowed fundsExample: Creating a Transaction
// Request
POST /transactions
{
"items": [
{
"product_id": "prod_h7k2m",
"quantity": 1,
"price": 164.99,
"negotiation_id": "neg_a1b2c3"
}
],
"currency": "USD",
"shipping_address": {
"line1": "123 Main St",
"city": "San Francisco",
"state": "CA",
"postal_code": "94102",
"country": "US"
}
}
// Response
{
"transaction_id": "txn_x9y8z7",
"status": "CREATED",
"items": [...],
"subtotal": 164.99,
"shipping": 0,
"tax": 13.61,
"total": 178.60,
"currency": "USD",
"payment_url": "https://cresva.ai/pay/txn_x9y8z7",
"expires_at": "2026-03-27T13:00:00Z"
}8. Trust Score
Trust scores help AI agents make informed recommendations. Every ACP storefront has a composite trust score based on multiple quality and reliability signals.
Trust Score Format
overallnumberrequiredComposite score from 0-100.
tierstringrequiredTier level: "Platinum" (90-100), "Gold" (75-89), "Silver" (60-74), "Bronze" (40-59), "Unrated" (<40).
componentsobjectIndividual score components (0-100 each).
Score Components
product_accuracynumberHow accurately product listings match actual products.
fulfillment_reliabilitynumberOn-time delivery and order accuracy rate.
pricing_transparencynumberConsistency between listed and actual prices.
customer_satisfactionnumberAggregated customer review sentiment.
response_timenumberAPI response time and uptime reliability.
dispute_resolutionnumberHow effectively disputes are resolved.
data_freshnessnumberHow up-to-date product and pricing data is.
Tier System
Agent Usage Guidelines
Agents SHOULD use trust scores to weight recommendations. Higher-trust storefronts should be preferred when product quality and price are comparable. Agents MUST NOT hide products solely based on trust score but MAY include trust information in recommendations to users.
9. Events + Webhooks
ACP supports real-time event notifications via webhooks. Storefronts emit events for state changes across queries, negotiations, transactions, and trust scores.
Event Types
query.completedA query has been processed and results returnedquery.failedA query failed to processnegotiation.initiatedA new negotiation has startednegotiation.counteredA counter-offer was madenegotiation.acceptedA negotiation was acceptednegotiation.rejectedA negotiation was rejectednegotiation.expiredA negotiation timed outnegotiation.withdrawnAn offer was withdrawntransaction.createdA new transaction was createdtransaction.confirmedA transaction was confirmedtransaction.paidPayment was receivedtransaction.fulfillingOrder is being fulfilledtransaction.completedOrder was delivered and completedtransaction.cancelledTransaction was cancelledtransaction.disputedA dispute was openedtransaction.resolvedA dispute was resolvedescrow.createdFunds placed in escrowescrow.releasedEscrowed funds released to sellerescrow.disputedEscrow dispute openedproduct.updatedProduct details were updatedproduct.out_of_stockProduct went out of stockproduct.back_in_stockProduct is back in stockprice.changedProduct price was updatedoffer.createdA new agent-exclusive offer was createdoffer.expiredAn offer expiredoffer.claimedAn offer was claimedtrust.updatedTrust score was recalculatedbundle.createdA new bundle was createdbundle.expiredA bundle expiredfeedback.receivedAgent feedback was receivedWebhook Delivery Format
{
"id": "evt_1234567890",
"type": "transaction.completed",
"created_at": "2026-03-27T10:30:00Z",
"data": {
"transaction_id": "txn_x9y8z7",
"status": "COMPLETED",
"total": 178.60,
"currency": "USD"
}
}HMAC Signature Verification
Every webhook includes an X-ACP-Signature header containing an HMAC-SHA256 signature. Verify this signature using your webhook secret to ensure the payload is authentic.
import crypto from "crypto";
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Retry Behavior
Failed webhook deliveries (non-2xx response or timeout after 30 seconds) are retried with exponential backoff: 1 min, 5 min, 30 min, 2 hours, 24 hours. After 5 failed attempts, the endpoint is disabled and an email notification is sent.
10. Authentication
ACP uses API keys for authentication. Keys are scoped by type and environment.
API Key Types
pk_live_*Public Key (Live)Read-only access to product data. Safe to use in client-side code. Rate limit: 1,000 requests/minute.
sk_live_*Secret Key (Live)Full access including transactions and negotiations. Must be kept server-side. Rate limit: 5,000 requests/minute.
pk_test_*Public Key (Test)Read-only access to sandbox data. Rate limit: 100 requests/minute.
sk_test_*Secret Key (Test)Full sandbox access. Rate limit: 500 requests/minute.
Authorization Header
Authorization: Bearer pk_live_your_key_hereInclude the API key in the Authorization header of every request using the Bearer scheme.
Rate Limits
Rate limits are applied per API key. When exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating when the limit resets.
11. Errors
ACP uses standard HTTP status codes and returns structured error responses.
Error Response Format
{
"error": {
"code": "invalid_query",
"message": "The 'intent' field is required for all query requests.",
"details": {
"field": "intent",
"expected": "one of: search, recommend, compare, detail, review, availability"
}
}
}HTTP Status Codes
400Bad RequestInvalid request body or parameters401UnauthorizedMissing or invalid API key403ForbiddenAPI key lacks required permissions404Not FoundResource does not exist429Too Many RequestsRate limit exceeded500Internal Server ErrorUnexpected server error503Service UnavailableStorefront is temporarily unavailableDegradation Headers
When a storefront is serving partial or stale data, it includes degradation headers:
X-ACP-Data-FreshnessheaderISO 8601 timestamp of when the data was last updated.
X-ACP-DegradedheaderSet to "true" when serving from cache or with reduced functionality.
X-ACP-Degraded-ReasonheaderHuman-readable reason for degradation.
12. Versioning + Compatibility
Protocol Version Header
Every request and response includes an X-ACP-Version header. Clients SHOULD send their supported version; servers MUST include the version used to process the request.
// Request
X-ACP-Version: 2.0
// Response
X-ACP-Version: 2.0Backward Compatibility Rules
- New optional fields MAY be added to responses without a version bump
- New optional request fields MAY be added without a version bump
- Existing fields MUST NOT be removed or have their type changed within a major version
- New required fields MUST trigger a major version increment
- New endpoints MAY be added in minor versions
Deprecation Policy
When a feature or endpoint is deprecated:
- A deprecation notice is published in the changelog and API responses include a
Sunsetheader - The feature continues to work for 6 months after the deprecation notice
- After the sunset date, the endpoint returns
410 Gone
Changelog
See the full protocol changelog for a detailed history of all versions and changes.