What We'll Build
A realistic e-commerce API with three interconnected resources:
- Products - Catalog management
- Customers - User accounts
- Orders - Purchase tracking
This demonstrates:
- β Multiple related resources
- β Resource references (foreign keys)
- β Query parameters and filtering
- β Security schemes
- β Validation rules
- β Complete OpenAPI spec generation
Time required: 20-30 minutes
Project Setup
mkdir ecommerce-api
cd ecommerce-api
mkdir resources
Step 1: Products Resource
Create resources/products.yaml:
kind: products
apiVersion: v1
metadata:
description: Product catalog management
methods:
resource:
- get # List products
- post # Create product
instance:
- get # Get product details
- put # Update product
- delete # Remove product
descriptions:
resource:
get: List all products with optional filtering
post: Create a new product in the catalog
instance:
get: Get detailed information about a specific product
put: Update product information
delete: Remove a product from the catalog
schema:
type: array
key:
name: product_id
description: Unique product identifier
schema:
type: string
format: uuid
# Query parameters for filtering
query_params:
- name: category
description: Filter by product category
required: false
schema:
type: string
enum: [electronics, clothing, books, home, sports]
methods:
- get
- name: in_stock
description: Filter by stock availability
required: false
schema:
type: boolean
methods:
- get
- name: min_price
description: Minimum price (in cents)
required: false
schema:
type: integer
minimum: 0
methods:
- get
- name: max_price
description: Maximum price (in cents)
required: false
schema:
type: integer
minimum: 0
methods:
- get
items:
type: object
properties:
name:
type: string
minLength: 1
maxLength: 200
description: Product name
description:
type: string
maxLength: 2000
description: Product description
sku:
type: string
pattern: '^[A-Z0-9-]+$'
minLength: 5
maxLength: 20
description: Stock Keeping Unit (uppercase alphanumeric)
category:
type: string
enum: [electronics, clothing, books, home, sports]
description: Product category
price:
type: integer
minimum: 0
description: Price in cents (e.g., 1999 = $19.99)
stock_quantity:
type: integer
minimum: 0
description: Available stock quantity
in_stock:
type: boolean
description: Whether product is currently in stock
images:
type: array
items:
type: string
format: uri
minItems: 0
maxItems: 10
description: Product image URLs
tags:
type: array
items:
type: string
minLength: 1
maxLength: 50
uniqueItems: true
maxItems: 20
description: Search tags
required:
- name
- sku
- category
- price
- stock_quantity
- in_stock
# Security: Only authenticated users can modify products
security:
scheme:
bearer_auth:
type: http
scheme: bearer
bearerFormat: JWT
resource:
- post # Create requires auth
instance:
- put # Update requires auth
- delete # Delete requires auth
Step 2: Customers Resource
Create resources/customers.yaml:
kind: customers
apiVersion: v1
metadata:
description: Customer account management
methods:
resource:
- get # List customers (admin only)
- post # Register new customer
instance:
- get # Get customer details
- put # Update customer
- delete # Delete account
descriptions:
resource:
get: List all customers (admin only)
post: Register a new customer account
instance:
get: Get customer account details
put: Update customer information
delete: Delete customer account
schema:
type: array
key:
name: customer_id
description: Unique customer identifier
schema:
type: string
format: uuid
query_params:
- name: email
description: Filter by email address
required: false
schema:
type: string
format: email
methods:
- get
items:
type: object
properties:
email:
type: string
format: email
maxLength: 254
description: Customer email address
name:
type: string
minLength: 1
maxLength: 100
description: Full name
phone:
type: string
pattern: '^\+?[1-9]\d{1,14}$'
description: Phone number (E.164 format)
shipping_address:
type: object
description: Default shipping address
properties:
street:
type: string
maxLength: 200
city:
type: string
maxLength: 100
state:
type: string
pattern: '^[A-Z]{2}$'
description: Two-letter state code
postal_code:
type: string
pattern: '^\d{5}(-\d{4})?$'
description: ZIP code
country:
type: string
pattern: '^[A-Z]{2}$'
description: Two-letter country code
required:
- street
- city
- postal_code
- country
billing_address:
type: object
description: Billing address (same structure as shipping)
properties:
street: {type: string, maxLength: 200}
city: {type: string, maxLength: 100}
state: {type: string, pattern: '^[A-Z]{2}$'}
postal_code: {type: string, pattern: '^\d{5}(-\d{4})?$'}
country: {type: string, pattern: '^[A-Z]{2}$'}
required:
- street
- city
- postal_code
- country
marketing_opt_in:
type: boolean
default: false
description: Opted in to marketing emails
created_at:
type: string
format: date-time
description: Account creation timestamp
required:
- email
- name
- shipping_address
security:
scheme:
bearer_auth:
type: http
scheme: bearer
bearerFormat: JWT
resource:
- get # List requires auth (admin)
- post # Create does NOT require auth (registration)
instance:
- get # View own account requires auth
- put # Update requires auth
- delete # Delete requires auth
Step 3: Orders Resource
Create resources/orders.yaml:
kind: orders
apiVersion: v1
metadata:
description: Order management and tracking
methods:
resource:
- get # List orders
- post # Create order
instance:
- get # Get order details
- put # Update order (status changes)
descriptions:
resource:
get: List all orders for the authenticated customer
post: Create a new order
instance:
get: Get detailed order information
put: Update order (status, tracking, etc.)
schema:
type: array
key:
name: order_id
description: Unique order identifier
schema:
type: string
format: uuid
query_params:
- name: customer_id
description: Filter by customer (admin only)
required: false
schema:
type: string
format: uuid
methods:
- get
- name: status
description: Filter by order status
required: false
schema:
type: string
enum: [pending, confirmed, shipped, delivered, cancelled]
methods:
- get
items:
type: object
properties:
customer_id:
type: string
format: uuid
description: Reference to customer who placed the order
order_date:
type: string
format: date-time
description: When the order was placed
status:
type: string
enum: [pending, confirmed, shipped, delivered, cancelled]
default: pending
description: Current order status
line_items:
type: array
description: Products in this order
minItems: 1
maxItems: 100
items:
type: object
properties:
product_id:
type: string
format: uuid
description: Reference to product
quantity:
type: integer
minimum: 1
maximum: 999
description: Number of units
unit_price:
type: integer
minimum: 0
description: Price per unit at time of order (in cents)
subtotal:
type: integer
minimum: 0
description: Line item total (quantity Γ unit_price)
required:
- product_id
- quantity
- unit_price
- subtotal
subtotal:
type: integer
minimum: 0
description: Sum of all line items
tax:
type: integer
minimum: 0
description: Tax amount in cents
shipping:
type: integer
minimum: 0
description: Shipping cost in cents
total:
type: integer
minimum: 0
description: Grand total (subtotal + tax + shipping)
shipping_address:
type: object
description: Shipping address for this order
properties:
street: {type: string}
city: {type: string}
state: {type: string, pattern: '^[A-Z]{2}$'}
postal_code: {type: string}
country: {type: string, pattern: '^[A-Z]{2}$'}
required:
- street
- city
- postal_code
- country
tracking_number:
type: string
description: Shipping tracking number (when shipped)
required:
- customer_id
- order_date
- status
- line_items
- subtotal
- tax
- shipping
- total
- shipping_address
security:
scheme:
bearer_auth:
type: http
scheme: bearer
bearerFormat: JWT
resource:
- get # List requires auth
- post # Create requires auth
instance:
- get # View requires auth
- put # Update requires auth
Step 4: Generate OpenAPI Spec
firestone generate \
--resources resources/ \
--title "E-Commerce API" \
--description "Complete e-commerce platform API" \
--version "1.0.0" \
openapi > openapi.yaml
Step 5: Generate Clients
Python Client
openapi-generator generate \
-i openapi.yaml \
-g python \
-o clients/python \
--additional-properties=packageName=ecommerce_client
TypeScript Client
openapi-generator generate \
-i openapi.yaml \
-g typescript-axios \
-o clients/typescript \
--additional-properties=npmName=@mycompany/ecommerce-client
Step 6: Test with Swagger UI
firestone generate \
--resources resources/ \
--title "E-Commerce API" \
openapi \
--ui-server
Visit http://127.0.0.1:5000/apidocs
Key Learnings
1. Resource References
Notice how orders reference customers and products:
customer_id:
type: string
format: uuid
description: Reference to customer
This creates a foreign key relationship documented in the API.
2. Nested Objects
Addresses are nested within customers and orders:
shipping_address:
type: object
properties:
street: {type: string}
# ...
3. Security Differentiation
Different endpoints have different auth requirements:
security:
resource:
- post # Create requires auth
instance:
- put # Update requires auth
- delete # Delete requires auth
# GET does not require auth
4. Query Parameters
Enable filtering:
query_params:
- name: category
schema:
enum: [electronics, clothing, books]
Generates: GET /products?category=electronics
5. Validation Rules
Comprehensive validation:
price:
type: integer
minimum: 0 # No negative prices
stock_quantity:
type: integer
minimum: 0 # No negative stock
email:
type: string
format: email # Must be valid email
Complete Project Structure
ecommerce-api/
βββ resources/
β βββ products.yaml
β βββ customers.yaml
β βββ orders.yaml
βββ openapi.yaml (generated)
βββ clients/
β βββ python/
β βββ typescript/
βββ README.md
Next Steps
Add More Features
- Product Reviews - Add a reviews resource
- Wishlists - Customer wishlist management
- Inventory - Stock tracking and alerts
- Promotions - Discounts and coupons
Deploy
- Generate FastAPI server
- Implement business logic
- Connect to database
- Deploy to production
Integrate
- Generate frontend client
- Build React/Vue app
- Use generated TypeScript types
- Connect to API
Congratulations! You've built a complete multi-resource API specification with Firestone. From here, you can generate servers, clients, documentation, and CLIsβall from these three resource files.