Skip to main content
Version: v1.0.0

HTTP+JSON (REST) binding

Same AAP payload feeding two transports: JSON-RPC 2.0 on the left, HTTP+JSON on the right

A2A defines an HTTP+JSON binding in Section 11 of its specification. Every A2A operation maps to a single HTTP route. AAP rides on this binding without modification: every skill is invoked via POST /message:send with the AAP request packaged as a typed DataPart inside message.parts[].

HTTP+JSON envelope: POST message with a message body; the 200 response wraps the agent Message

HTTP+JSON is the OPTIONAL binding

In AAP v1.0, the JSON-RPC binding is REQUIRED on every AAP agent card; an agent MAY additionally expose an HTTP+JSON interface as described on this page. Buyer agents MUST NOT require HTTP+JSON support, and gRPC is out of scope.

AAP uses exactly one A2A operation: SendMessage — a request Message in, a response Message out (POST {base}/message:send in this binding). The rest of the optional A2A surface (SendStreamingMessage, tasks Get/List/Cancel/Subscribe, push notification configs, GetExtendedAgentCard) is out of scope for AAP v1.0: dealer agents do not need to implement it and buyer agents MUST NOT require it.

A2A wire format — A2A v1.0 ProtoJSON form

AAP rides on A2A v1.0. Use the v1.0 ProtoJSON form that the A2A SDKs (a2a-js, a2a-python) and clients (Claude, ChatGPT, Gemini, Perplexity) send and parse. A compliant AAP agent MUST emit this single canonical form so any A2A client can parse its replies. There is one wire form — no kind discriminators, Role is an enum name, and the response is wrapped under message.

AspectA2A v1.0 ProtoJSON form
URL (HTTP+JSON)POST /message:send
Role"ROLE_USER" / "ROLE_AGENT"
Part discriminatormember-name (the data member); no kind
Message discriminator(none); no kind
Response bodySendMessageResponse: { "message": <Message> }
messageIdrequired on every Message
mediaType on DataPartapplication/vnd.autoagent.<skill>-request+json

Endpoint

A dealer agent that opts into this binding advertises one or more HTTP+JSON endpoints under supportedInterfaces[] of its agent card, alongside its required JSONRPC interface. Each HTTP+JSON entry has protocolBinding: "HTTP+JSON" and a url for the base.

POST {base_url}/message:send
Content-Type: application/json

The body is an A2A SendMessageRequest with two top-level keys: message (an A2A Message) and configuration (the buyer's accepted output modes):

{
"message": {
"messageId": "01HZ9F4M7C0X3K5RN8B3WJTW2P",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "<scope>.<thing>.request",
"...": "skill-specific fields"
},
"mediaType": "application/vnd.autoagent.<skill>-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": [
"application/vnd.autoagent.<skill>-response+json"
]
}
}

The response body is an A2A SendMessageResponse, which wraps the agent Message under message:

{
"message": {
"messageId": "01HZ9F4N1JZ7QS8VKR2A3B4C5D",
"role": "ROLE_AGENT",
"parts": [
{
"data": {
"type": "<scope>.<thing>.response",
"data": {
"...": "skill-specific response data"
}
},
"mediaType": "application/vnd.autoagent.<skill>-response+json"
}
]
}
}

The remainder of this page shows a curl invocation for each of the five skills.

dealer.information

curl -X POST https://demo-toyota.example.com/a2a/message:send \
-H "Content-Type: application/json" \
-d '{
"message": {
"messageId": "01HZ9G5N8D1Y4M6SP9C4XKVW3Q",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "dealer.information.request"
},
"mediaType": "application/vnd.autoagent.dealer-information-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": ["application/vnd.autoagent.dealer-information-response+json"]
}
}'

inventory.facets

curl -X POST https://demo-toyota.example.com/a2a/message:send \
-H "Content-Type: application/json" \
-d '{
"message": {
"messageId": "01HZ9H6P9E2Z5N7TQ0D5YMWX4R",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "inventory.facets.request",
"filters": { "condition": ["used"] }
},
"mediaType": "application/vnd.autoagent.inventory-facets-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": ["application/vnd.autoagent.inventory-facets-response+json"]
}
}'

inventory.search

curl -X POST https://demo-toyota.example.com/a2a/message:send \
-H "Content-Type: application/json" \
-d '{
"message": {
"messageId": "01HZ9F4M7C0X3K5RN8B3WJTW2P",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "inventory.search.request",
"filters": {
"make": ["Honda"],
"condition": ["used", "cpo"],
"year_min": 2020,
"price_max": 30000
},
"pagination": { "skip": 0, "limit": 20 },
"sort": { "field": "price", "order": "asc" },
"privacy": { "anonymous": true }
},
"mediaType": "application/vnd.autoagent.inventory-search-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": ["application/vnd.autoagent.inventory-search-response+json"]
}
}'

inventory.vehicle

curl -X POST https://demo-toyota.example.com/a2a/message:send \
-H "Content-Type: application/json" \
-d '{
"message": {
"messageId": "01HZ9J7Q0F3A6P8VR1E6ZNXY5S",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "inventory.vehicle.request",
"vin": "1HGCY2F57RA000001",
"zip": "94105"
},
"mediaType": "application/vnd.autoagent.vehicle-detail-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": ["application/vnd.autoagent.vehicle-detail-response+json"]
}
}'

lead.submit

The unified lead carries customer info plus any combination of vehicle_of_interest, trade_in, and appointment. Below: a single test-drive lead that also queues the buyer's trade-in for in-person appraisal.

curl -X POST https://demo-toyota.example.com/a2a/message:send \
-H "Content-Type: application/json" \
-d '{
"message": {
"messageId": "01HZ9K8R1G4B7Q9WS2F7APYZ6T",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "lead.submit.request",
"customer": {
"first_name": "Anna",
"last_name": "Lee",
"email": "anna@example.com",
"phone": "+14155550123",
"preferred_contact": "phone",
"address": {
"address_line_1": "200 Folsom St",
"city": "San Francisco",
"state": "CA",
"zip": "94105"
}
},
"consent": {
"granted_at": "2026-04-30T10:16:00Z",
"allowed_channels": ["email", "phone"],
"consent_text": "I agree to share my contact info with Demo Toyota about VIN 1HGCY2F57RA000001, my Saturday test drive, and the trade-in of my 2014 Toyota Corolla.",
"source_agent": "chatgpt-shopping",
"scope": ["lead_submission"]
},
"vehicle_of_interest": {
"vin": "1HGCY2F57RA000001",
"year": 2022, "make": "Honda", "model": "Civic", "trim": "EX",
"condition": "cpo"
},
"trade_in": {
"year": 2014, "make": "Toyota", "model": "Corolla",
"condition": "good",
"mileage": 96000
},
"appointment": {
"appointment_type": "test_drive",
"appointment_at": "2026-05-02T17:00:00Z",
"duration_minutes": 60
},
"message": "Interested in this Civic; please appraise my Corolla at the same visit.",
"source_agent": "chatgpt-shopping",
"submitted_at": "2026-04-30T10:16:05Z"
},
"mediaType": "application/vnd.autoagent.lead-submit-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": ["application/vnd.autoagent.lead-submit-response+json"]
}
}'

Successful response shape

A successful HTTP+JSON response uses HTTP status 200 OK and its body is an A2A SendMessageResponse: a top-level message object whose value is the agent's A2A Message:

HTTP/1.1 200 OK
Content-Type: application/json

{
"message": {
"messageId": "01HZ9F4N1JZ7QS8VKR2A3B4C5D",
"role": "ROLE_AGENT",
"parts": [
{
"data": {
"type": "inventory.search.response",
"data": {
"total": 1,
"skip": 0,
"limit": 20,
"vehicles": [/* ... */]
}
},
"mediaType": "application/vnd.autoagent.inventory-search-response+json"
}
]
}
}

The dealer agent's messageId MUST differ from the buyer agent's request messageId.

Error mapping (A2A Section 11.6)

When a skill cannot be fulfilled, the dealer agent MUST return a non-2xx HTTP status with a body matching A2A's Section 11.6 error envelope: a top-level error object with code, message, and details[]. AAP places its typed error payload (aap.error) into details[] alongside the standard google.rpc.ErrorInfo entry.

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
"error": {
"code": 422,
"message": "filters.year_min must be an integer",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SCHEMA_VALIDATION_FAILED",
"domain": "autoagentprotocol.org",
"metadata": {
"instancePath": "/filters/year_min",
"received": "twenty-twenty"
}
},
{
"@type": "type.googleapis.com/aap.error",
"type": "aap.error",
"error_id": "err_01HZ9EXAMPLE",
"code": "SCHEMA_VALIDATION_FAILED",
"message": "filters.year_min must be an integer",
"retryable": false,
"details": {
"instancePath": "/filters/year_min",
"received": "twenty-twenty"
},
"created_at": "2026-04-30T10:15:30Z"
}
]
}
}

The error.code field is the HTTP status code. The first detail entry uses Google's standard ErrorInfo shape with reason set to the AAP error code; the second entry carries the full AAP error payload for clients that prefer to consume it directly.

Recommended HTTP status mapping:

AAP codeHTTP statusNotes
SCHEMA_VALIDATION_FAILED422Body fails schema validation.
MISSING_REQUIRED_FIELD422A required field is absent.
UNSUPPORTED_SKILL404Skill id is unknown to this agent.
VEHICLE_NOT_FOUND404VIN/stock/vehicle_id does not match a listing.
VEHICLE_UNAVAILABLE409Vehicle exists but is no longer available (e.g. sold).
CONTACT_CONSENT_REQUIRED403Customer info present without consent or with insufficient scope.
INVALID_CONSENT403Consent grant present but malformed or expired.
APPOINTMENT_TIME_UNAVAILABLE409None of the requested windows can be honored and no proposals offered.
RATE_LIMITED429Client has exceeded the dealer's rate limits.
INTERNAL_ERROR500Unhandled dealer-side error.

See Errors for the full vocabulary and per-code semantics.