E-Commerce API
A comprehensive e-commerce API demonstrating advanced Soxom features.
Features Demonstrated
Section titled “Features Demonstrated”- Nested resources (users → settings)
- Union types with discriminator (PaymentMethod)
- Schema composition with allOf
- Multiple authentication methods
- Cursor and offset pagination
- Custom timeouts and retry configuration
Soxom Configuration
Section titled “Soxom Configuration”version: "1.0"
sdk: name: acme-store-sdk version: 1.0.0 description: SDK for Acme Store API
spec: path: ./openapi.yaml
targets: typescript: package_name: "@acme/store-sdk" python: package_name: acme-store-sdk
resources: users: models: - User - UserCreate methods: list: get /users create: post /users get: get /users/{user_id} update: put /users/{user_id} subresources: settings: models: - UserSettings methods: get: get /users/{user_id}/settings update: put /users/{user_id}/settings
products: models: - Product - ProductCreate methods: list: get /products create: post /products get: get /products/{product_id}
orders: models: - Order - OrderCreate methods: list: get /orders create: post /orders get: get /orders/{order_id} cancel: post /orders/{order_id}/cancel
payments: models: - Payment - PaymentMethod - CreditCard - BankAccount methods: create: post /payments get: get /payments/{payment_id}
pagination: default_type: cursor schemes: cursor: cursor: request_param: after response_property: next_cursor limit: request_param: limit default: 20 max: 100 has_more: response_property: has_more offset: offset: request_param: offset limit: request_param: limit default: 20 total: response_property: total
authentication: default: bearer env_vars: bearer: token: ACME_API_TOKEN
retries: enabled: true max_attempts: 3
timeouts: default_ms: 60000 operations: orders_create: default_ms: 30000OpenAPI Specification (Key Parts)
Section titled “OpenAPI Specification (Key Parts)”PaymentMethod Union Type
Section titled “PaymentMethod Union Type”components: schemas: PaymentMethod: oneOf: - $ref: '#/components/schemas/CreditCard' - $ref: '#/components/schemas/BankAccount' discriminator: propertyName: type mapping: credit_card: '#/components/schemas/CreditCard' bank_account: '#/components/schemas/BankAccount'
CreditCard: type: object required: - type - card_number - expiry_month - expiry_year properties: type: type: string enum: [credit_card] card_number: type: string expiry_month: type: integer expiry_year: type: integer cardholder_name: type: string
BankAccount: type: object required: - type - account_number - routing_number properties: type: type: string enum: [bank_account] account_number: type: string routing_number: type: stringUser with Composition
Section titled “User with Composition”components: schemas: TimestampedResource: type: object properties: created_at: type: string format: date-time updated_at: type: string format: date-time
User: allOf: - $ref: '#/components/schemas/TimestampedResource' - type: object required: - id - email - name properties: id: type: string email: type: string name: type: string status: type: string enum: [active, inactive]Generated SDK Usage
Section titled “Generated SDK Usage”Users with Nested Settings
Section titled “Users with Nested Settings”import { AcmeStoreClient } from '@acme/store-sdk';
const client = new AcmeStoreClient({ token: process.env.ACME_API_TOKEN});
// List users with paginationfor await (const user of client.users.list()) { console.log(`${user.name} - ${user.email}`);}
// Get userconst user = await client.users.get("user-123");
// Nested resource: user settingsconst settings = await client.users.settings.get("user-123");console.log(`Theme: ${settings.theme}`);
// Update settingsawait client.users.settings.update("user-123", { theme: "dark", notifications_enabled: true});from acme_store_sdk import AcmeStoreClient
client = AcmeStoreClient( token=os.environ["ACME_API_TOKEN"])
# List users with paginationfor user in client.users.list(): print(f"{user.name} - {user.email}")
# Get useruser = client.users.get("user-123")
# Nested resource: user settingssettings = client.users.settings.get("user-123")print(f"Theme: {settings.theme}")
# Update settingsclient.users.settings.update("user-123", theme="dark", notifications_enabled=True)Products with Offset Pagination
Section titled “Products with Offset Pagination”// Products use offset paginationconst page1 = await client.products.list({ limit: 10 });console.log(`Total products: ${page1.total}`);
// Get next pageconst page2 = await client.products.list({ offset: 10, limit: 10});# Products use offset paginationpage1 = client.products.list(limit=10)print(f"Total products: {page1.total}")
# Get next pagepage2 = client.products.list(offset=10, limit=10)Orders
Section titled “Orders”// Create orderconst order = await client.orders.create({ items: [ { product_id: "prod-123", quantity: 2 }, { product_id: "prod-456", quantity: 1 } ], shipping_address: { street: "123 Main St", city: "San Francisco", country: "US" }});console.log(`Order ${order.id}: $${order.total}`);
// Cancel orderconst cancelled = await client.orders.cancel(order.id);console.log(`Status: ${cancelled.status}`); // "cancelled"# Create orderorder = client.orders.create( items=[ {"product_id": "prod-123", "quantity": 2}, {"product_id": "prod-456", "quantity": 1} ], shipping_address={ "street": "123 Main St", "city": "San Francisco", "country": "US" })print(f"Order {order.id}: ${order.total}")
# Cancel ordercancelled = client.orders.cancel(order.id)print(f"Status: {cancelled.status}") # "cancelled"Payments with Union Types
Section titled “Payments with Union Types”// Pay with credit cardconst payment = await client.payments.create({ amount: 99.99, currency: "USD", order_id: "order-123", payment_method: { type: "credit_card", card_number: "4111111111111111", expiry_month: 12, expiry_year: 2025, cardholder_name: "John Doe" }});
// Pay with bank accountconst bankPayment = await client.payments.create({ amount: 500.00, currency: "USD", order_id: "order-456", payment_method: { type: "bank_account", account_number: "123456789", routing_number: "021000021" }});
// Type narrowing worksconst pm = payment.payment_method;if (pm.type === "credit_card") { console.log(`Card: **** ${pm.card_number.slice(-4)}`);} else { console.log(`Bank: ${pm.account_number}`);}# Pay with credit cardpayment = client.payments.create( amount=99.99, currency="USD", order_id="order-123", payment_method={ "type": "credit_card", "card_number": "4111111111111111", "expiry_month": 12, "expiry_year": 2025, "cardholder_name": "John Doe" })
# Pay with bank accountbank_payment = client.payments.create( amount=500.00, currency="USD", order_id="order-456", payment_method={ "type": "bank_account", "account_number": "123456789", "routing_number": "021000021" })
# Type checkingpm = payment.payment_methodmatch pm: case CreditCard(): print(f"Card: **** {pm.card_number[-4:]}") case BankAccount(): print(f"Bank: {pm.account_number}")