Part 6: API Documentation and Versioning in gRPC
The Undocumented API Nightmare
Protocol Buffer Documentation
Comprehensive Proto Comments
// protos/order/v1/order.proto
syntax = "proto3";
package order.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
import "common/types.proto";
/// OrderService manages customer orders in the e-commerce platform.
///
/// All methods require authentication via JWT token in metadata.
/// Rate limits apply per user: 100 requests/minute for read operations,
/// 10 requests/minute for write operations.
///
/// Support: [email protected]
/// SLA: 99.9% uptime
service OrderService {
/// Creates a new order for a customer.
///
/// This operation is idempotent when using the same idempotency_key.
/// The order will be created with status PENDING and requires
/// subsequent payment processing.
///
/// Business Rules:
/// - User must have valid billing address
/// - All products must be in stock
/// - Maximum 50 items per order
/// - Total amount must not exceed $50,000 USD
///
/// Error Codes:
/// - INVALID_ARGUMENT: Invalid request parameters or missing required fields
/// - NOT_FOUND: Product not found
/// - FAILED_PRECONDITION: Insufficient stock, user not eligible
/// - ALREADY_EXISTS: Order with same idempotency key exists
/// - UNAUTHENTICATED: Missing or invalid authentication token
/// - RESOURCE_EXHAUSTED: Rate limit exceeded
///
/// Example:
/// ```
/// {
/// "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
/// "user_id": "usr_123",
/// "items": [
/// {"product_id": "prod_456", "quantity": 2}
/// ],
/// "shipping_address": {
/// "street": "123 Main St",
/// "city": "San Francisco",
/// "state": "CA",
/// "postal_code": "94105",
/// "country": "US"
/// }
/// }
/// ```
rpc CreateOrder(CreateOrderRequest) returns (Order);
/// Retrieves an order by ID.
///
/// Users can only retrieve their own orders unless they have
/// the 'order:read:all' permission (admin/manager roles).
///
/// Error Codes:
/// - INVALID_ARGUMENT: Invalid order ID format
/// - NOT_FOUND: Order not found
/// - PERMISSION_DENIED: User doesn't have access to this order
/// - UNAUTHENTICATED: Missing or invalid authentication token
///
/// Performance: Average 50ms, P99 150ms
rpc GetOrder(GetOrderRequest) returns (Order);
/// Lists orders with filtering and pagination.
///
/// Returns orders sorted by created_at DESC (newest first).
/// Maximum page size is 100 items.
///
/// Filtering:
/// - By user_id: Required for non-admin users
/// - By status: Optional status filter
///
/// Error Codes:
/// - INVALID_ARGUMENT: Invalid parameters (page_size > 100, etc.)
/// - PERMISSION_DENIED: Non-admin user querying other users' orders
/// - UNAUTHENTICATED: Missing or invalid authentication token
///
/// Performance: Average 100ms, P99 300ms
rpc ListOrders(ListOrdersRequest) returns (ListOrdersResponse);
/// Updates the status of an order.
///
/// Requires 'order:update' permission (manager/admin only).
///
/// Valid status transitions:
/// - PENDING -> CONFIRMED, CANCELLED
/// - CONFIRMED -> PROCESSING, CANCELLED
/// - PROCESSING -> SHIPPED
/// - SHIPPED -> DELIVERED
/// - DELIVERED -> REFUNDED
///
/// Error Codes:
/// - INVALID_ARGUMENT: Invalid status value
/// - NOT_FOUND: Order not found
/// - FAILED_PRECONDITION: Invalid status transition
/// - PERMISSION_DENIED: Insufficient permissions
/// - UNAUTHENTICATED: Missing or invalid authentication token
rpc UpdateOrderStatus(UpdateOrderStatusRequest) returns (Order);
/// Cancels an order.
///
/// Can only cancel orders in PENDING or CONFIRMED status.
/// Users can cancel their own orders. Admins can cancel any order.
///
/// This operation:
/// - Restores product inventory
/// - Triggers refund if payment was processed
/// - Sends cancellation notification to user
///
/// Error Codes:
/// - NOT_FOUND: Order not found
/// - FAILED_PRECONDITION: Order cannot be cancelled in current status
/// - PERMISSION_DENIED: User doesn't have permission to cancel
/// - UNAUTHENTICATED: Missing or invalid authentication token
rpc CancelOrder(CancelOrderRequest) returns (Order);
/// Streams real-time status updates for an order.
///
/// Server streaming RPC that sends updates when order status changes.
/// Stream automatically closes when order reaches terminal status
/// (DELIVERED, CANCELLED, or REFUNDED).
///
/// Typical update frequency: Every 30-60 seconds
/// Maximum stream duration: 24 hours
///
/// Error Codes:
/// - NOT_FOUND: Order not found
/// - PERMISSION_DENIED: User doesn't have access to this order
/// - UNAUTHENTICATED: Missing or invalid authentication token
rpc StreamOrderUpdates(StreamOrderUpdatesRequest) returns (stream OrderUpdate);
}
/// Represents a customer order
message Order {
/// Unique order identifier.
/// Format: "ord_" followed by 16 alphanumeric characters
/// Example: "ord_a1b2c3d4e5f6g7h8"
string id = 1;
/// ID of the user who placed the order.
/// Format: "usr_" followed by 16 alphanumeric characters
/// Example: "usr_x1y2z3a4b5c6d7e8"
string user_id = 2;
/// Current status of the order.
/// See OrderStatus enum for details.
/// Default: ORDER_STATUS_PENDING
OrderStatus status = 3;
/// List of items in the order.
/// Minimum: 1 item
/// Maximum: 50 items
repeated OrderItem items = 4;
/// Shipping address for the order.
/// Required field.
common.v1.Address shipping_address = 5;
/// Subtotal before tax and shipping.
/// Sum of all item total_price values.
common.v1.Money subtotal = 6;
/// Tax amount.
/// Calculated based on shipping address and local tax rates.
common.v1.Money tax = 7;
/// Shipping cost.
/// Calculated based on weight, dimensions, and shipping method.
common.v1.Money shipping_cost = 8;
/// Total amount (subtotal + tax + shipping_cost).
/// This is the amount charged to the customer.
common.v1.Money total = 9;
/// Timestamp when the order was created.
/// Immutable after creation.
google.protobuf.Timestamp created_at = 10;
/// Timestamp when the order was last updated.
/// Updated whenever any field changes.
google.protobuf.Timestamp updated_at = 11;
}
/// Represents a single item within an order
message OrderItem {
/// Unique item identifier (within the order).
/// Generated by the system.
string id = 1;
/// ID of the product.
/// Must reference a valid product in the catalog.
string product_id = 2;
/// Name of the product at time of order.
/// Snapshot of product name (may differ from current product name).
string product_name = 3;
/// Quantity ordered.
/// Minimum: 1
/// Maximum: 100 per item
int32 quantity = 4;
/// Unit price at time of order.
/// Snapshot of product price (may differ from current price).
common.v1.Money unit_price = 5;
/// Total price for this item (unit_price * quantity).
/// Calculated field.
common.v1.Money total_price = 6;
}
/// Order status values
enum OrderStatus {
/// Default value. Should never be used.
/// If you see this, there's a bug.
ORDER_STATUS_UNSPECIFIED = 0;
/// Order created but not yet confirmed.
/// Awaiting payment or manual review.
ORDER_STATUS_PENDING = 1;
/// Order confirmed and payment received.
/// Ready for processing.
ORDER_STATUS_CONFIRMED = 2;
/// Order is being prepared/packaged.
/// Inventory has been reserved.
ORDER_STATUS_PROCESSING = 3;
/// Order has been shipped.
/// Tracking information available.
ORDER_STATUS_SHIPPED = 4;
/// Order delivered to customer.
/// Terminal status (unless refunded).
ORDER_STATUS_DELIVERED = 5;
/// Order cancelled by user or system.
/// Inventory restored, refund issued if applicable.
/// Terminal status.
ORDER_STATUS_CANCELLED = 6;
/// Order refunded after delivery.
/// Payment reversed to customer.
/// Terminal status.
ORDER_STATUS_REFUNDED = 7;
}
/// Request to create a new order
message CreateOrderRequest {
/// Idempotency key to prevent duplicate orders.
/// Use a UUID v4 for uniqueness.
/// Required field.
/// Max length: 128 characters
///
/// If a request with the same idempotency_key is received within 24 hours,
/// the previously created order will be returned without creating a new one.
///
/// Example: "550e8400-e29b-41d4-a716-446655440000"
string idempotency_key = 1;
/// ID of the user placing the order.
/// Must match authenticated user unless caller has admin role.
/// Required field.
string user_id = 2;
/// Items to include in the order.
/// Required field.
/// Minimum: 1 item
/// Maximum: 50 items
repeated CreateOrderItem items = 3;
/// Shipping address for the order.
/// Required field.
/// Must be a valid, deliverable address.
common.v1.Address shipping_address = 4;
}
/// Item to add to a new order
message CreateOrderItem {
/// ID of the product to order.
/// Must reference a valid, active product.
/// Required field.
string product_id = 1;
/// Quantity to order.
/// Required field.
/// Minimum: 1
/// Maximum: 100
///
/// Quantity must not exceed available stock.
int32 quantity = 2;
}
// ... Additional messages with similar documentationDocumentation Best Practices
Generating API Documentation
Using protoc-gen-doc
Custom Documentation Template
Automated Documentation Generation
API Versioning Strategies
1. Package Versioning (Recommended)
Server Supporting Multiple Versions
Client Choosing Version
2. Field Versioning (Backward Compatible)
3. Method Versioning
Migration Strategies
Gradual Migration Pattern
Deprecation Headers
Breaking Change Checklist
Safe Changes (Backward Compatible)
Breaking Changes (Require New Version)
Version Sunset Policy
Changelog and Release Notes
CHANGELOG.md
Documentation Website
Using Docusaurus
Key Takeaways
PreviousPart 5: Error Handling and Interceptors in gRPCNextPart 7: Testing, Performance, and Production Deployment
Last updated