Order Capability Specification
Basic Information
- Capability Name:
dev.ucp.shopping.order - Version:
2026-01-11 - Official Specification: order.md
Overview
An Order represents a confirmed transaction resulting from a successful checkout submission. It provides a complete purchase record, delivery method, and post-order events.
Core Concepts
Orders have three main components:
Line Items — What was purchased at checkout:
- Includes current quantity counts (total, fulfilled)
Fulfillment — How items are delivered:
- Expectations — Delivery promises to the buyer
- Events — Append-only logs of actual events
Adjustments — Post-order events independent of fulfillment:
- Typically financial flows (refunds, returns, credits, disputes, cancellations)
- Can be any post-order change
- Can occur before, during, or after fulfillment
Data Model
Line Items
Line items reflect what was purchased at checkout and their current state:
- Item details (product, price, quantity ordered)
- Quantity counts and status are derived
Quantity Structure
{
"total": 3, // Current total quantity
"fulfilled": 2 // Fulfilled quantity
}Status Derivation
if (fulfilled == total) → "fulfilled"
else if (fulfilled > 0) → "partial"
else → "processing"Fulfillment
Fulfillment tracks how items are delivered to the buyer.
Expectations
Expectations are buyer-facing item groupings (like “packages 📦”), representing:
- Which items are grouped together
- Where they go (
destination) - How they’re delivered (
method_type) - When they arrive (
description,fulfillable_on)
Expectations can be split, merged, or adjusted post-order. For example:
- Group by delivery date: “what arrives when”
- Use single expectation with broad date range for flexibility
- Goal is to set buyer expectations — provide optimal buyer experience
Fulfillment Events
Fulfillment Events are append-only logs tracking physical shipment:
- Reference line items by ID and quantity
- Include tracking information
typeis an open string field — businesses can use any meaningful value- Common examples:
processing,shipped,in_transit,delivered,failed_attempt,canceled,undeliverable,returned_to_sender
- Common examples:
Adjustments
Adjustments are append-only event logs existing independently of fulfillment:
typeis an open string field — businesses can use any meaningful value- Typically financial flows:
refund,return,credit,price_adjustment,dispute,cancellation
- Typically financial flows:
- Can be any post-order change
- May optionally link to line items (or order-level, like shipping refund)
- Include relevant amounts
- Can occur anytime, regardless of fulfillment status
Order Example
{
"ucp": {
"version": "2026-01-11",
"capabilities": [
{"name": "dev.ucp.shopping.order", "version": "2026-01-11"}
]
},
"id": "order_abc123",
"checkout_id": "checkout_xyz789",
"permalink_url": "https://business.com/orders/abc123",
"line_items": [
{
"id": "li_shoes",
"item": { "id": "prod_shoes", "title": "Running Shoes", "price": 3000 },
"quantity": { "total": 3, "fulfilled": 3 },
"totals": [
{"type": "subtotal", "amount": 9000},
{"type": "total", "amount": 9000}
],
"status": "fulfilled"
},
{
"id": "li_shirts",
"item": { "id": "prod_shirts", "title": "Cotton T-Shirt", "price": 2000 },
"quantity": { "total": 2, "fulfilled": 0 },
"totals": [
{"type": "subtotal", "amount": 4000},
{"type": "total", "amount": 4000}
],
"status": "processing"
}
],
"fulfillment": {
"expectations": [
{
"id": "exp_1",
"line_items": [{ "id": "li_shoes", "quantity": 3 }],
"method_type": "shipping",
"destination": {
"street_address": "123 Main St",
"address_locality": "Austin",
"address_region": "TX",
"address_country": "US",
"postal_code": "78701"
},
"description": "Arrives in 2-3 business days",
"fulfillable_on": "now"
},
{
"id": "exp_2",
"line_items": [{ "id": "li_shirts", "quantity": 2 }],
"method_type": "shipping",
"destination": {
"street_address": "123 Main St",
"address_locality": "Austin",
"address_region": "TX",
"address_country": "US",
"postal_code": "78701"
},
"description": "Backordered - ships Jan 15, arrives in 7-10 days",
"fulfillable_on": "2025-01-15T00:00:00Z"
}
],
"events": [
{
"id": "evt_1",
"occurred_at": "2025-01-08T10:30:00Z",
"type": "delivered",
"line_items": [{ "id": "li_shoes", "quantity": 3 }],
"tracking_number": "123456789",
"tracking_url": "https://fedex.com/track/123456789",
"description": "Delivered to front door"
}
]
},
"adjustments": [
{
"id": "adj_1",
"type": "refund",
"occurred_at": "2025-01-10T14:30:00Z",
"status": "completed",
"line_items": [{ "id": "li_shoes", "quantity": 1 }],
"amount": 3000,
"description": "Defective item"
}
],
"totals": [
{ "type": "subtotal", "amount": 13000 },
{ "type": "shipping", "amount": 1200 },
{ "type": "tax", "amount": 1142 },
{ "type": "total", "amount": 15342 }
]
}Event Mechanism
Businesses send order status change events after an order is placed.
| Event Mechanism | Method | Endpoint | Description |
|---|---|---|---|
| Order Event Webhook | POST | Platform-provided URL | Business sends order lifecycle events to platform |
Order Event Webhook
Businesses POST order events to the webhook URL provided by the platform during onboarding. URL format is platform-specific.
Webhook URL Configuration
Platforms provide their webhook URL in the config field of the order capability during capability negotiation. Businesses discover this URL from the platform’s profile and use it to send order lifecycle events.
Example:
{
"name": "dev.ucp.shopping.order",
"version": "2026-01-11",
"config": {
"webhook_url": "https://platform.example.com/webhooks/ucp/orders"
}
}Webhook Signature Verification
Webhook payloads MUST be signed by businesses and verified by platforms to ensure authenticity and integrity.
Signing (Business)
- Select a key from the
signing_keysarray in the UCP profile - Create a detached JWT of the request body using the selected key (RFC 7797)
- Include JWT in
Request-Signatureheader - Include key ID in JWT header’s
kidclaim so recipient can identify which key to use for verification
Verification (Platform)
- Extract
Request-Signatureheader from incoming webhook request - Parse JWT header to retrieve
kid(key ID) - Fetch business’s UCP profile from
/.well-known/ucp(appropriately cached) - Locate key with matching
kidinsigning_keys - Verify JWT signature of request body using public key
- If verification fails, reject webhook with appropriate error response
Key Rotation
The signing_keys array supports multiple keys for zero-downtime rotation:
- Add new key: Add new key to
signing_keys, then start using it for signing. Verifiers will find it bykid. - Remove old key: After sufficient time for all in-flight webhook deliveries, remove old key from
signing_keys.
Implementation Guidelines
Platform Requirements
- MUST respond quickly with 2xx HTTP status code to acknowledge receipt
- Process events asynchronously after response
Business Requirements
- MUST sign all webhook payloads using keys from their
signing_keysarray (published at/.well-known/ucp). Signature MUST be included inRequest-Signatureheader as a detached JWT (RFC 7797) - MUST send “order created” event with fully populated order entity
- MUST send complete order entity on updates (not incremental deltas)
- MUST retry failed webhook deliveries
- MUST include business identifier in webhook path or headers
Implementation Checklist
Platform Implementation Checklist
- Provide webhook URL endpoint
- Respond quickly with 2xx status code
- Process webhook events asynchronously
- Verify webhook signatures
- Handle key rotation
Business Implementation Checklist
- Sign all webhook payloads
- Send complete order entity
- Retry failed deliveries
- Include business identifier
- Support key rotation