API Reference
Complete reference documentation for Unified Commerce Platform's GraphQL API.
Overview
Unified Commerce Platform provides a single GraphQL endpoint that unifies 14 microservices. All API requests are made to:
https://gateway.unifiedcommerce.app/graphql
Quick Links
📖 Queries
Fetch data from products, orders, customers, and more
✏️ Mutations
Create, update, and delete resources
🔔 Subscriptions
Real-time updates via WebSockets
📦 Types
All object types, inputs, and enums
Schema Organization
Our GraphQL schema is organized by service domains:
Core Commerce
- Product Catalog - Products, categories, variants, attributes
- Order Management - Orders, order items, fulfillment, shipping
- Cart - Shopping carts, cart items, checkout
- Inventory - Stock levels, warehouses, reservations
Customer & Identity
- Identity - Users, authentication, authorization, roles
- CRM - Customers, contacts, interactions, loyalty
- Booking - Appointments, schedules, resources, staff
Payments & Finance
- Payment - Payment intents, transactions, refunds
- Promotions - Discounts, coupons, campaigns
Operations
- Email - Email templates, campaigns, delivery logs
- Notifications - Push notifications, alerts, preferences
- Analytics - Reports, metrics, dashboards
- Search - Full-text search, autocomplete, facets
Platform
- Merchant Account - Multi-tenant management, subscriptions, settings
Common Patterns
Fetching Resources
All resources follow consistent naming patterns:
query {
# Single resource by ID
product(id: "prod_123") { ... }
order(id: "ord_456") { ... }
customer(id: "cust_789") { ... }
# List resources with pagination
products(first: 10, after: "cursor") { ... }
orders(first: 20, status: PENDING) { ... }
customers(first: 50, searchQuery: "john") { ... }
}
Creating Resources
Mutations use consistent input patterns:
mutation {
# Create with input object
createProduct(input: {
name: "Product Name"
price: 2999
# ... other fields
}) {
product { id name }
errors { field message }
}
# Update with ID + input
updateProduct(id: "prod_123", input: {
name: "Updated Name"
}) {
product { id name }
errors { field message }
}
# Delete by ID
deleteProduct(id: "prod_123") {
success
errors { message }
}
}
Error Handling
All mutations return consistent error structures:
type CreateProductPayload {
product: Product # Null if errors occurred
errors: [UserError!]! # Array of validation errors
}
type UserError {
field: String # Which field caused the error
message: String! # Human-readable error message
code: String # Machine-readable error code
}
Example error response:
{
"data": {
"createProduct": {
"product": null,
"errors": [
{
"field": "name",
"message": "Name is required",
"code": "REQUIRED_FIELD"
},
{
"field": "price",
"message": "Price must be positive",
"code": "INVALID_VALUE"
}
]
}
}
}
Pagination
We use cursor-based pagination (Relay spec):
query GetProducts($first: Int!, $after: String) {
products(first: $first, after: $after) {
edges {
cursor # Use this for next page
node {
id
name
price
}
}
pageInfo {
hasNextPage # Are there more results?
hasPreviousPage # Can we go back?
startCursor # First cursor in this page
endCursor # Last cursor (use for next page)
}
totalCount # Total number of items
}
}
Fetch next page:
const { data } = await client.query({
query: GET_PRODUCTS,
variables: {
first: 10,
after: data.products.pageInfo.endCursor
}
});
Field Arguments
Common Arguments
Most list queries accept these standard arguments:
Argument | Type | Description |
---|---|---|
first | Int | Number of items to return (forward pagination) |
after | String | Cursor for forward pagination |
last | Int | Number of items to return (backward pagination) |
before | String | Cursor for backward pagination |
sortBy | Enum | Field to sort by |
sortOrder | Enum | ASC or DESC |
filters | Input | Service-specific filter object |
Example:
query {
products(
first: 20
after: "cursor_abc123"
sortBy: PRICE
sortOrder: DESC
filters: {
categoryId: "cat_123"
priceMin: 1000
priceMax: 5000
inStock: true
}
) {
edges { node { id name price } }
pageInfo { hasNextPage endCursor }
}
}
Federation & Cross-Service Queries
Query across services in a single request:
query GetProductWithDetails {
product(id: "prod_123") {
# From Product Catalog Service
id
name
description
price
# From Inventory Service (federated)
inventory {
available
reserved
warehouse {
id
name
location
}
}
# From Order Service (federated)
totalSold
recentOrders(limit: 5) {
id
orderNumber
createdAt
}
# From Analytics Service (federated)
analytics {
views
conversions
revenue
}
}
}
Type System
Scalar Types
Type | Description | Example |
---|---|---|
ID | Unique identifier | "prod_abc123" |
String | UTF-8 string | "Hello World" |
Int | Signed 32-bit integer | 42 |
Float | Signed double-precision floating-point | 3.14 |
Boolean | True or false | true |
DateTime | ISO 8601 datetime | "2025-01-15T10:30:00Z" |
Date | ISO 8601 date | "2025-01-15" |
JSON | Arbitrary JSON | {"key": "value"} |
URL | Valid URL | "https://example.com" |
EmailAddress | Valid email | "user@example.com" |
Custom Scalars
scalar DateTime # ISO 8601 timestamp with timezone
scalar Date # ISO 8601 date (YYYY-MM-DD)
scalar Money # Integer representing cents (e.g., 2999 = $29.99)
scalar JSON # Arbitrary JSON object
scalar URL # Valid HTTP/HTTPS URL
scalar EmailAddress # Valid email address
Money Representation
All monetary values are represented as integers in cents to avoid floating-point precision issues:
type Product {
price: Money! # 2999 = $29.99
compareAtPrice: Money # 3999 = $39.99
currency: String! # "USD", "EUR", "GBP"
}
When displaying:
const displayPrice = (cents, currency) => {
const dollars = cents / 100;
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency
}).format(dollars);
};
displayPrice(2999, 'USD'); // "$29.99"
Rate Limits
All API requests are subject to rate limits based on your plan:
Plan | Requests/Hour | Requests/Minute | Burst Limit |
---|---|---|---|
Free | 1,000 | 50 | 100 |
Pro | 10,000 | 500 | 1,000 |
Enterprise | Unlimited* | Custom | Custom |
See Rate Limiting Guide for details.
Authentication
All requests require authentication via API key:
curl -X POST https://gateway.unifiedcommerce.app/graphql \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ products(limit: 5) { id name } }"}'
See Authentication Guide for details.
Introspection
Explore the schema using introspection:
query IntrospectSchema {
__schema {
types {
name
kind
description
}
queryType {
name
fields {
name
description
args {
name
type {
name
}
}
}
}
}
}
Or use our Interactive Playground with built-in documentation explorer.
Versioning
We do not version the GraphQL API. Instead:
- Additive changes (new fields, types) are added continuously
- Deprecation is marked with
@deprecated
directive - Breaking changes are avoided, but when necessary, we provide 6+ months notice
Check for deprecated fields:
query {
__type(name: "Product") {
fields(includeDeprecated: true) {
name
isDeprecated
deprecationReason
}
}
}
Error Codes
Standard error codes returned in extensions.code
:
Code | HTTP | Description |
---|---|---|
UNAUTHENTICATED | 401 | Missing or invalid authentication |
UNAUTHORIZED | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource doesn't exist |
BAD_USER_INPUT | 400 | Invalid input data |
CONFLICT | 409 | Resource conflict (e.g., duplicate) |
RATE_LIMITED | 429 | Too many requests |
INTERNAL_SERVER_ERROR | 500 | Server error |
SERVICE_UNAVAILABLE | 503 | Service temporarily down |
See Error Handling Guide for details.
Best Practices
1. Request Only What You Need
✅ Good - Specific fields:
query {
products(limit: 10) {
id
name
price
}
}
❌ Bad - Requesting everything:
query {
products(limit: 10) {
id
name
description
price
currency
images { url alt order }
variants { ... }
# ... everything
}
}
2. Use Fragments for Reusability
fragment ProductCard on Product {
id
name
price
currency
images(limit: 1) {
url
alt
}
}
query {
featured: products(featured: true, limit: 5) {
...ProductCard
}
newest: products(sortBy: CREATED_AT, limit: 5) {
...ProductCard
}
}
3. Batch Requests
Fetch multiple resources in one query:
query {
product1: product(id: "prod_1") { ...ProductDetails }
product2: product(id: "prod_2") { ...ProductDetails }
product3: product(id: "prod_3") { ...ProductDetails }
}
4. Use Persisted Queries (Production)
For security and performance, use persisted queries in production.
5. Handle Partial Data
GraphQL can return partial data with errors. Always check both:
const { data, errors } = await client.query({ query: GET_PRODUCTS });
if (errors) {
console.error('Errors:', errors);
}
if (data?.products) {
// Use partial data
console.log('Products:', data.products);
}
Interactive Documentation
Explore the API interactively:
- GraphQL Playground - Interactive query builder with autocomplete
- Code Examples - Copy/paste examples in multiple languages
- Postman Collection - Pre-built API requests
Reference by Service
Detailed documentation for each service:
- Identity Service API
- Product Catalog API
- Order Management API
- Payment API
- Inventory API
- Cart API
- CRM API
- Email API
- Booking API
- Promotions API
- Merchant Account API
- Analytics API
- Notifications API
- Search API
Need Help?
- Guides & Tutorials - Step-by-step guides
- GraphQL Basics - Learn GraphQL fundamentals
- Discord Community - Ask questions
- Support - Technical support
Ready to start? Check out our Quickstart Guide or jump into the Playground!