Order Management API
Below is a comprehensive REST API documentation for managing Orders in your e-commerce ("commerce"
) schema. It includes cURL examples and TypeScript examples (using the native fetch
API) for each endpoint.
Note: There is an API client plus example available on: https://github.com/CatchTheTornado/open-agents-builder-client and https://github.com/CatchTheTornado/open-agents-builder-example
1. Overview
The /api/order
endpoints allow you to:
- Query orders with pagination, filtering, and sorting.
- Create or update an order via upsert.
- Delete an order by ID.
Note: Orders are stored in a commerce-partitioned table, with certain fields (like addresses, email) encrypted if a
storageKey
is provided (SaaS mode).
2. Data Schema: OrderDTO
From orderDTOSchema
in src/data/dto.ts
:
export const orderDTOSchema = z.object({ id: z.string().optional(), agentId: z.string().optional(), sessionId: z.string().optional(),
billingAddress: addressSchema.optional(), shippingAddress: addressSchema.optional(),
attributes: z.record(z.any()).optional(), notes: z.array(noteSchema).optional(), statusChanges: z.array(statusChangeSchema).optional(), status: z.enum([ "shopping_cart", "quote", "new", "processing", "shipped", "completed", "cancelled", ]).default("shopping_cart"), email: z.string().email().optional(), customer: customerSchema.optional(),
// Price fields subtotal: priceSchema.optional(), subTotalInclTax: priceSchema.optional(), subtotalTaxValue: priceSchema.optional(), total: priceSchema.optional(), totalInclTax: priceSchema.optional(), shippingMethod: z.string().optional(), shippingPrice: priceSchema.optional(), shippingPriceInclTax: priceSchema.optional(), shippingPriceTaxRate: z.number().optional(),
items: z.array(orderItemSchema).optional(),
createdAt: z.string().default(() => getCurrentTS()), updatedAt: z.string().default(() => getCurrentTS()),});export type OrderDTO = z.infer<typeof orderDTOSchema>;
Key fields:
id
(string, optional) – unique identifier for the order (often user-defined).status
– one of"shopping_cart"
,"quote"
,"new"
,"processing"
,"shipped"
,"completed"
,"cancelled"
.email
– optional, must be a valid email if present.items
– an array of order line items, each containing fields likesku
,quantity
, etc.subtotal
,total
and other price objects hold numeric values plus a currency code.
3. Endpoints
3.1 GET /api/order
3.1.1 Description
Returns a paginated list of orders, allowing you to filter or sort by certain fields. Supports query parameters:
limit
(default10
): how many records per page.offset
(default0
): how many records to skip.orderBy
: defaults to"createdAt"
. Possible values:"status"
,"email"
,"createdAt"
.id
: fetch a single order by ID.agentId
: filter by an agent’s ID.query
: partial match onemail
,id
, orstatus
.
3.1.2 cURL Example
curl -X GET \ "https://your-domain.com/api/order?limit=5&offset=0&orderBy=status&query=shipped" \ -H "Authorization: Bearer <YOUR_API_KEY>" \ -H "database-id-hash: <YOUR_DATABASE_ID_HASH>"
3.1.3 TypeScript fetch
Example
async function getOrders() { const limit = 5; const offset = 0; const orderBy = "status"; const query = "shipped";
const response = await fetch( `https://your-domain.com/api/order?limit=${limit}&offset=${offset}&orderBy=${orderBy}&query=${query}`, { method: "GET", headers: { "Authorization": "Bearer YOUR_API_KEY", "database-id-hash": "YOUR_DATABASE_ID_HASH" } } );
if (!response.ok) { throw new Error(`Error fetching orders: ${response.statusText}`); }
const data = await response.json(); console.log("Paginated order list:", data); // data.rows => array of OrderDTO return data;}
Using the TypeScript API Client
You can also retrieve orders using the open-agents-builder-client:
import { OpenAgentsBuilderClient } from "open-agents-builder-client";
const client = new OpenAgentsBuilderClient({ apiKey: "YOUR_API_KEY", databaseIdHash: "YOUR_DATABASE_ID_HASH"});
async function listOrdersClientExample() { const orders = await client.order.listOrders({ limit: 5, offset: 0, orderBy: "status", query: "shipped" }); console.log("Orders via client:", orders);}
3.1.4 Example Response (HTTP 200)
A paginated structure:
{ "rows": [ { "id": "ORD-2025-03-21-ABC", "agentId": "agent-XYZ", "sessionId": "session-123", "billingAddress": {}, "shippingAddress": {}, "attributes": {}, "notes": [], "statusChanges": [], "customer": { "name": "Alice", "email": "[email protected]" }, "status": "shipped", "email": "[email protected]", "subtotal": { "value": 100, "currency": "USD" }, "subTotalInclTax": { "value": 123, "currency": "USD" }, "subtotalTaxValue": { "value": 23, "currency": "USD" }, "total": { "value": 120, "currency": "USD" }, "totalInclTax": { "value": 150, "currency": "USD" }, "shippingPrice": { "value": 10, "currency": "USD" }, "shippingPriceTaxRate": 0.08, "shippingPriceInclTax": { "value": 10.8, "currency": "USD" }, "items": [ { "id": "line-1", "sku": "PROD-001", "variantSku": "VAR-001", "quantity": 2, ... } ], "createdAt": "2025-03-21T10:00:00.000Z", "updatedAt": "2025-03-21T10:05:00.000Z" }, ... ], "total": 10, "limit": 5, "offset": 0, "orderBy": "status", "query": "shipped"}
3.2 PUT /api/order
3.2.1 Description
Upserts an order. If id
does not exist in DB, creates a new record; otherwise updates the existing one.
- Request Body must match
OrderDTO
structure.
3.2.2 cURL Example
curl -X PUT \ "https://your-domain.com/api/order" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "database-id-hash: YOUR_DATABASE_ID_HASH" \ -H "Content-Type: application/json" \ -d '{ "id": "ORD-2025-03-21-ABC", "agentId": "agent-XYZ", "status": "new", "email": "[email protected]", "items": [ { "id": "line-1", "productSku": "PROD-ABC", "variantSku": "VAR-ABC", "quantity": 2, "price": { "value": 50, "currency": "USD" } } ], "shippingMethod": "UPS", "shippingPrice": { "value": 10, "currency": "USD" } }'
3.2.3 TypeScript fetch
Example
async function upsertOrder(orderData: any) { const response = await fetch("https://your-domain.com/api/order", { method: "PUT", headers: { "Authorization": "Bearer YOUR_API_KEY", "database-id-hash": "YOUR_DATABASE_ID_HASH", "Content-Type": "application/json" }, body: JSON.stringify(orderData) });
const result = await response.json(); if (!response.ok) { throw new Error(`Error upserting order: ${result?.error?.message || result?.message}`); }
console.log("Upserted order:", result.data); return result.data;}
// Example usageupsertOrder({ id: "ORD-2025-03-21-ABC", status: "new", agentId: "agent-XYZ", email: "[email protected]", items: [ { id: "line-1", productSku: "PROD-ABC", variantSku: "VAR-ABC", quantity: 2, price: { value: 50, currency: "USD" } } ], shippingMethod: "UPS", shippingPrice: { value: 10, currency: "USD" }});
Using the TypeScript API Client
import { OpenAgentsBuilderClient } from "open-agents-builder-client";
const client = new OpenAgentsBuilderClient({ apiKey: "YOUR_API_KEY", databaseIdHash: "YOUR_DATABASE_ID_HASH"});
async function upsertOrderClientExample() { const updated = await client.order.upsertOrder({ id: "ORD-2025-03-21-ABC", status: "new", agentId: "agent-XYZ", email: "[email protected]", items: [ { id: "line-1", productSku: "PROD-ABC", variantSku: "VAR-ABC", quantity: 2, price: { value: 50, currency: "USD" } } ], shippingMethod: "UPS", shippingPrice: { value: 10, currency: "USD" } }); console.log("Upserted via client:", updated);}
3.2.4 Example Success Response (HTTP 200)
{ "status": 200, "data": { "id": "ORD-2025-03-21-ABC", "agentId": "agent-XYZ", "sessionId": null, "billingAddress": {}, "shippingAddress": {}, "status": "new", "email": "[email protected]", "items": [ { "id": "line-1", "productSku": "PROD-ABC", "variantSku": "VAR-ABC", "quantity": 2, "price": { "value": 50, "currency": "USD" } } ], ... "createdAt": "2025-03-21T10:00:00.000Z", "updatedAt": "2025-03-21T10:05:00.000Z" }}
3.2.5 Validation Error (HTTP 400)
{ "status": 400, "error": { "issues": [ { "code": "invalid_type", "path": [...], ... } ] }}
3.3 DELETE /api/order/[id]
3.3.1 Description
Deletes an order with the given id
. If it doesn’t exist, returns 404 Not Found
.
3.3.2 cURL Example
curl -X DELETE \ "https://your-domain.com/api/order/ORD-2025-03-21-ABC" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "database-id-hash: YOUR_DATABASE_ID_HASH"
3.3.3 TypeScript fetch
Example
async function deleteOrder(orderId: string) { const response = await fetch(`https://your-domain.com/api/order/${orderId}`, { method: "DELETE", headers: { "Authorization": "Bearer YOUR_API_KEY", "database-id-hash": "YOUR_DATABASE_ID_HASH" } });
const result = await response.json(); if (!response.ok) { throw new Error(`Error deleting order: ${result.message}`); } console.log("Delete response:", result); return result;}
// Usage:deleteOrder("ORD-2025-03-21-ABC") .then(() => console.log("Order deleted.")) .catch((err) => console.error(err));
Using the TypeScript API Client
import { OpenAgentsBuilderClient } from "open-agents-builder-client";
const client = new OpenAgentsBuilderClient({ apiKey: "YOUR_API_KEY", databaseIdHash: "YOUR_DATABASE_ID_HASH"});
async function deleteOrderClientExample(orderId: string) { const result = await client.order.deleteOrder(orderId); console.log("Order deleted:", result);}
// UsagedeleteOrderClientExample("ORD-2025-03-21-ABC");
3.3.4 Success Response (HTTP 200)
{ "message": "Order deleted", "status": 200}
3.3.5 Not Found (HTTP 404)
{ "message": "Not found", "status": 404}
4. Encryption Details
In the ServerOrderRepository
, these fields are stored encrypted at rest:
billingAddress
shippingAddress
attributes
notes
customer
email
When you create or update an order, the server encrypts those fields before storing them in the database. When reading data, it decrypts them automatically.
Result: If you look at the raw database, you’ll see ciphertext for these fields. The REST endpoint always returns plaintext to your client if you have a valid
storageKey
.
5. Example Workflow
- Create a new order
PUT /api/order
with noid
or a unique newid
.- Provide
items
,email
, shipping method, etc. The server automatically calculates totals.
- Retrieve orders for admin UI
GET /api/order?limit=20&offset=0&orderBy=createdAt&query=someSearchTerm
- Update order (add items, change status)
PUT /api/order
with the existingid
.
- Delete an unwanted or canceled order
DELETE /api/order/[id]
.
6. Error Handling
- 400 Bad Request
- Invalidation by
zod
schema or missing mandatory fields.
- Invalidation by
- 404 Not Found
- Attempt to
DELETE
an order that doesn’t exist.
- Attempt to
- 499 or 500 Internal Server Error
- Unexpected issues (e.g., DB connection or encryption error).
- 401 / 403 Unauthorized
- Missing or invalid credentials (
Bearer token
,database-id-hash
).
- Missing or invalid credentials (
Each error typically includes a JSON structure with "message"
and "status"
.
7. Summary
Endpoint | Method | Purpose |
---|---|---|
/api/order?limit=&offset=... | GET | List or search orders (paginated, sorted). |
/api/order | PUT | Upsert (create or update) an order by id . |
/api/order/[id] | DELETE | Delete a specific order. |
Important:
calcTotals()
automatically adjusts the price/tax fields on the server.- Encryption ensures sensitive data (addresses, email) remain secure.
- An audit log records every create/update/delete action with the differences.
This completes the Order endpoint documentation, including cURL, TypeScript fetch
, and open-agents-builder-client examples.