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

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:

ArgumentTypeDescription
firstIntNumber of items to return (forward pagination)
afterStringCursor for forward pagination
lastIntNumber of items to return (backward pagination)
beforeStringCursor for backward pagination
sortByEnumField to sort by
sortOrderEnumASC or DESC
filtersInputService-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

TypeDescriptionExample
IDUnique identifier"prod_abc123"
StringUTF-8 string"Hello World"
IntSigned 32-bit integer42
FloatSigned double-precision floating-point3.14
BooleanTrue or falsetrue
DateTimeISO 8601 datetime"2025-01-15T10:30:00Z"
DateISO 8601 date"2025-01-15"
JSONArbitrary JSON{"key": "value"}
URLValid URL"https://example.com"
EmailAddressValid 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:

PlanRequests/HourRequests/MinuteBurst Limit
Free1,00050100
Pro10,0005001,000
EnterpriseUnlimited*CustomCustom

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:

CodeHTTPDescription
UNAUTHENTICATED401Missing or invalid authentication
UNAUTHORIZED403Insufficient permissions
NOT_FOUND404Resource doesn't exist
BAD_USER_INPUT400Invalid input data
CONFLICT409Resource conflict (e.g., duplicate)
RATE_LIMITED429Too many requests
INTERNAL_SERVER_ERROR500Server error
SERVICE_UNAVAILABLE503Service 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:

Reference by Service

Detailed documentation for each service:

Need Help?


Ready to start? Check out our Quickstart Guide or jump into the Playground!

Was this page helpful?