토론

RESTful API 설계 청사진 생성기

Wikiprompt, 무료 프롬프트 백과사전에서

Lautaro Schiaffino

2025년 12월 28일

RESTful API 설계 청사진 생성기 API 설계 문서를 생성하되, 엔드포인트, 요청/응답 스키마, 오류 처리, 인증, OpenAPI 사양을 포함하세요.

프롬프트 내용저장

🌐
I notice you've provided a prompt asking me to design an API, but you haven't filled in the project requirements section (API Purpose, Target Users, Core Resources, Authentication Method, Expected Scale). However, I'll design a comprehensive API for a typical e-commerce platform as a concrete example, since that's a common use case that demonstrates all the patterns well. I'll make reasonable assumptions and note where you'd customize for your specific needs. --- # E-Commerce Platform API Design Document ## 1. API OVERVIEW **API Name:** Commerce API **Version:** v1 **Base URL:** `https://api.example.com/v1` **Content-Type:** `application/json` (UTF-8) **API Style:** RESTful (with a few RPC-style endpoints for complex operations) ### Rate Limiting Strategy - **Default tier:** 100 requests/minute per API key - **Premium tier:** 1000 requests/minute per API key - **Burst allowance:** 2x the rate limit for 10-second windows - **Strategy:** Token bucket algorithm with sliding window for burst handling --- ## 2. AUTHENTICATION & AUTHORIZATION ### Authentication Method: OAuth 2.0 with JWT Access Tokens **Primary flow:** Authorization Code + PKCE for server-to-server and web apps **Machine-to-machine:** Client Credentials flow **Token format:** JWT (RS256 signed) **Access token lifetime:** 15 minutes **Refresh token lifetime:** 30 days (rotating) ### Token Structure ```json { "iss": "https://auth.example.com", "sub": "user_12345", "aud": "api.example.com", "exp": 1704067200, "iat": 1704066300, "scope": "products:read products:write", "client_id": "client_abc123" } ``` ### Scopes/Permissions Model | Scope | Description | |-------|-------------| | `products:read` | View products | | `products:write` | Create/update/delete products | | `orders:read` | View orders | | `orders:write` | Create/update orders | | `customers:read` | View customer data | | `customers:write` | Modify customer data | | `admin` | Full access (admin only) | ### Auth Headers ``` Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9... X-API-Key: live_abc123def456 ``` ### Refresh Token Strategy - Refresh tokens are single-use and rotate on each refresh - Refresh token rotation endpoint: `POST /v1/auth/refresh` - Revocation on password change or security event - Refresh token stored in HttpOnly cookie for web apps --- ## 3. RESOURCE DESIGN ### Resource: Products **Description:** Products available for purchase in the catalog **Relationships:** Belongs to a `Category`, has many `Variants`, has many `Images` **ID format:** UUID v4 (e.g., `prod_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d`) **Endpoints:** ``` GET /products - List products (with pagination, filtering) GET /products/:id - Get single product POST /products - Create new product PUT /products/:id - Full update PATCH /products/:id - Partial update DELETE /products/:id - Delete product (soft delete) GET /products/:id/variants - List product variants POST /products/:id/variants - Add variant ``` **Data Schema:** ```json { "id": "prod_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "type": "product", "attributes": { "name": "Wireless Headphones Pro", "slug": "wireless-headphones-pro", "description": "Premium noise-cancelling headphones", "price": 299.99, "currency": "USD", "status": "active", "category_id": "cat_12345", "sku": "WH-PRO-001", "stock_quantity": 150, "is_featured": true, "metadata": { "color": "black", "weight_kg": 0.25 } }, "relationships": { "category": { "data": { "type": "category", "id": "cat_12345" } }, "variants": { "data": [{ "type": "variant", "id": "var_67890" }] } }, "links": { "self": "/v1/products/prod_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d" } } ``` **Field Definitions Table:** | Field | Type | Required | Description | Constraints | |-------|------|----------|-------------|-------------| | id | string | Yes (server-generated) | Unique identifier | UUID v4, prefixed with `prod_` | | name | string | Yes | Product name | 1-200 chars | | slug | string | Yes | URL-friendly identifier | Unique, lowercase, hyphens | | description | string | No | Detailed description | Max 5000 chars | | price | number | Yes | Unit price | >= 0, max 2 decimal places | | currency | string | Yes | ISO 4217 currency code | 3-letter code | | status | string | Yes | Product status | `draft`, `active`, `archived` | | category_id | string | No | Parent category | Must reference existing category | | sku | string | No | Stock keeping unit | Unique, max 50 chars | | stock_quantity | integer | No | Available stock | >= 0 | | is_featured | boolean | No | Featured product flag | Default: false | | metadata | object | No | Custom attributes | Key-value pairs, max 20 keys | | created_at | string | Yes | Creation timestamp | ISO 8601 UTC | | updated_at | string | Yes | Last update timestamp | ISO 8601 UTC | --- ### Resource: Orders **Description:** Customer orders containing one or more line items **Relationships:** Belongs to a `Customer`, has many `LineItems`, has one `Payment` **ID format:** UUID v4 (e.g., `ord_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d`) **Endpoints:** ``` GET /orders - List orders (with pagination, filtering) GET /orders/:id - Get single order POST /orders - Create new order PUT /orders/:id - Full update (admin only) PATCH /orders/:id - Partial update (status changes) DELETE /orders/:id - Cancel order (soft delete) POST /orders/:id/capture - Capture payment (RPC-style) POST /orders/:id/refund - Refund order (RPC-style) ``` **Data Schema:** ```json { "id": "ord_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "type": "order", "attributes": { "order_number": "ORD-2024-0001", "status": "pending_payment", "subtotal": 299.99, "tax_total": 24.00, "shipping_total": 10.00, "total": 333.99, "currency": "USD", "customer_id": "cus_12345", "shipping_address": { "line1": "123 Main St", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country": "US" }, "billing_address": { "line1": "123 Main St", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country": "US" }, "placed_at": "2024-01-15T10:30:00Z" }, "relationships": { "customer": { "data": { "type": "customer", "id": "cus_12345" } }, "line_items": { "data": [{ "type": "line_item", "id": "li_67890" }] } } } ``` **Field Definitions Table:** | Field | Type | Required | Description | Constraints | |-------|------|----------|-------------|-------------| | id | string | Yes (server-generated) | Unique identifier | UUID v4, prefixed with `ord_` | | order_number | string | Yes | Human-readable order number | Auto-generated, unique | | status | string | Yes | Order status | `pending_payment`, `processing`, `shipped`, `delivered`, `cancelled`, `refunded` | | subtotal | number | Yes | Sum of line items | >= 0 | | tax_total | number | Yes | Tax amount | >= 0 | | shipping_total | number | Yes | Shipping cost | >= 0 | | total | number | Yes | Grand total | subtotal + tax + shipping | | currency | string | Yes | ISO 4217 currency code | 3-letter code | | customer_id | string | Yes | Ordering customer | Must reference existing customer | | shipping_address | object | Yes | Shipping destination | Valid address object | | billing_address | object | Yes | Billing address | Valid address object | | placed_at | string | Yes | Order placement time | ISO 8601 UTC | --- ### Resource: Customers **Description:** Registered users who can place orders **Relationships:** Has many `Orders`, has many `Addresses` **ID format:** UUID v4 (e.g., `cus_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d`) **Endpoints:** ``` GET /customers - List customers (admin only) GET /customers/:id - Get single customer POST /customers - Create new customer PUT /customers/:id - Full update PATCH /customers/:id - Partial update DELETE /customers/:id - Delete customer (soft delete) GET /customers/:id/orders - List customer's orders ``` **Data Schema:** ```json { "id": "cus_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "type": "customer", "attributes": { "email": "john.doe@example.com", "first_name": "John", "last_name": "Doe", "phone": "+1-555-123-4567", "status": "active", "default_address_id": "addr_12345", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z" }, "relationships": { "orders": { "data": [{ "type": "order", "id": "ord_67890" }] }, "addresses": { "data": [{ "type": "address", "id": "addr_12345" }] } } } ``` **Field Definitions Table:** | Field | Type | Required | Description | Constraints | |-------|------|----------|-------------|-------------| | id | string | Yes (server-generated) | Unique identifier | UUID v4, prefixed with `cus_` | | email | string | Yes | Customer email | Valid email format, unique | | first_name | string | Yes | First name | 1-100 chars | | last_name | string | Yes | Last name | 1-100 chars | | phone | string | No | Contact phone | E.164 format | | status | string | Yes | Account status | `active`, `disabled`, `deleted` | | default_address_id | string | No | Default shipping address | Must reference existing address | | created_at | string | Yes | Creation timestamp | ISO 8601 UTC | | updated_at | string | Yes | Last update timestamp | ISO 8601 UTC | --- ## 4. REQUEST/RESPONSE FORMATS ### Standard Success Response ```json { "data": { "id": "prod_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "type": "product", "attributes": { "name": "Wireless Headphones Pro", "price": 299.99 } }, "meta": { "request_id": "req_abc123", "timestamp": "2024-01-15T10:30:00Z", "api_version": "v1" } } ``` ### List Response (with pagination) ```json { "data": [ { "id": "prod_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "type": "product", "attributes": { "name": "Wireless Headphones Pro", "price": 299.99 } } ], "pagination": { "total": 100, "page": 1, "per_page": 20, "total_pages": 5, "next_cursor": "eyJpZCI6MTAwfQ==", "has_more": true }, "meta": { "request_id": "req_abc123", "timestamp": "2024-01-15T10:30:00Z" } } ``` ### Query Parameters for Lists | Parameter | Type | Description | Example | |-----------|------|-------------|---------| | `page` | integer | Page number (offset pagination) | `?page=2` | | `per_page` | integer | Items per page (max 100) | `?per_page=50` | | `cursor` | string | Cursor for cursor-based pagination | `?cursor=eyJpZCI6MTAwfQ==` | | `sort` | string | Field to sort by | `?sort=price` | | `order` | string | Sort order: `asc` or `desc` | `?order=desc` | | `filter[field]` | string | Filter by field | `?filter[status]=active` | | `include` | string | Related resources to embed | `?include=category,variants` | | `fields` | string | Sparse fieldsets | `?fields=name,price,sku` | ### Curl Examples **List products with filtering:** ```bash curl -X GET "https://api.example.com/v1/products?filter[category]=electronics&filter[price][gte]=100&sort=price&order=asc&per_page=20" \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" ``` **Create a new order:** ```bash curl -X POST "https://api.example.com/v1/orders" \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cus_12345", "line_items": [ { "product_id": "prod_67890", "quantity": 2 } ], "shipping_address": { "line1": "123 Main St", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country": "US" } }' ``` --- ## 5. ERROR HANDLING ### Error Response Format ```json { "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "details": [ { "field": "email", "code": "INVALID_FORMAT", "message": "Email must be a valid email address" }, { "field": "price", "code": "MIN_VALUE", "message": "Price must be greater than or equal to 0" } ], "request_id": "req_abc123", "documentation_url": "https://api.example.com/docs/errors#VALIDATION_ERROR" } } ``` ### Standard Error Codes | HTTP Status | Error Code | Description | |-------------|------------|-------------| | 400 | VALIDATION_ERROR | Request validation failed | | 401 | UNAUTHORIZED | Missing or invalid auth | | 403 | FORBIDDEN | Valid auth but insufficient permissions | | 404 | NOT_FOUND | Resource does not exist | | 409 | CONFLICT | Resource state conflict (e.g., duplicate SKU) | | 422 | UNPROCESSABLE | Valid syntax but semantic error (e.g., insufficient stock) | | 429 | RATE_LIMITED | Too many requests | | 500 | INTERNAL_ERROR | Server error | | 503 | SERVICE_UNAVAILABLE | Service temporarily unavailable | ### Error Handling Best Practices - Always include `request_id` for correlation - Provide actionable error messages - Include `documentation_url` for developer reference - Use appropriate HTTP status codes - Never expose stack traces or internal details --- ## 6. VERSIONING STRATEGY ### Primary: URL Versioning - **Current version:** `/v1/` - **Next version:** `/v2/` (when breaking changes needed) ### Secondary: Header Versioning ``` API-Version: 2024-01-15 ``` ### Deprecation Policy 1. **Deprecation notice:** 6 months before removal 2. **Headers on deprecated endpoints:** - `Deprecation: true` - `Sunset: 2024-07-15` 3. **Migration guide:** Published with each deprecation ### Migration Guide Template ```markdown ## Migration Guide: v1 to v2 ### Breaking Changes - [ ] List each breaking change - [ ] Provide before/after examples - [ ] Include migration timeline ### New Features - [ ] Describe new capabilities - [ ] Show usage examples ### Deprecated Features - [ ] List deprecated endpoints/fields - [ ] Provide alternatives ``` --- ## 7. PAGINATION DESIGN ### Chosen Approach: Hybrid (Cursor + Offset) **Primary:** Cursor-based for stable pagination **Secondary:** Offset-based for simple use cases **Cursor-based:** ``` GET /products?cursor=eyJpZCI6MTAwfQ==&per_page=20 ``` **Offset-based:** ``` GET /products?page=2&per_page=20 ``` ### Rationale - **Cursor-based pros:** Stable with data changes, efficient for large datasets, no duplicates/skips - **Cursor-based cons:** More complex to implement, opaque to clients - **Offset-based pros:** Simple, intuitive, easy to jump to specific pages - **Offset-based cons:** Unstable with data changes, inefficient for large offsets ### Implementation Details - Cursor is base64-encoded JSON: `{"last_id": "prod_12345", "sort_value": "2024-01-15T10:30:00Z"}` - Default `per_page`: 20, max: 100 - Response includes both `next_cursor` and `page` for flexibility --- ## 8. FILTERING & SEARCH ### Filtering Patterns ``` # Exact match GET /products?filter[status]=active # Range (numeric/date) GET /products?filter[price][gte]=100&filter[price][lte]=500 GET /products?filter[created_at][gte]=2024-01-01 # Multiple values GET /products?filter[category]=electronics,books # Nested fields GET /products?filter[variants.color]=black # Null/not null GET /products?filter[description][null]=true ``` ### Search ``` # Full-text search GET /products?search=wireless headphones # Search with filters GET /products?search=wireless&filter[category]=electronics ``` ### Filter Operators | Operator | Description | Example | |----------|-------------|---------| | `eq` | Equal (default) | `filter[status]=active` | | `neq` | Not equal | `filter[status][neq]=archived` | | `gt` | Greater than | `filter[price][gt]=100` | | `gte` | Greater than or equal | `filter[price][gte]=100` | | `lt` | Less than | `filter[price][lt]=500` | | `lte` | Less than or equal | `filter[price][lte]=500` | | `in` | In list | `filter[status][in]=active,pending` | | `null` | Is null | `filter[description][null]=true` | --- ## 9. RATE LIMITING ### Rate Limit Tiers | Tier | Requests/Minute | Burst | Use Case | |------|----------------|-------|----------| | Free | 60 | 120 | Development/testing | | Standard | 300 | 600 | Production apps | | Premium | 1000 | 2000 | High-volume apps | | Enterprise | Custom | Custom | Custom SLA | ### Rate Limit Headers ``` X-RateLimit-Limit: 300 X-RateLimit-Remaining: 299 X-RateLimit-Reset: 1704067200 ``` ### 429 Response ```json { "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Please retry after 30 seconds.", "retry_after": 30, "request_id": "req_abc123" } } ``` ### Retry-After Header ``` Retry-After: 30 ``` --- ## 10. WEBHOOKS ### Event Types | Event | Description | Trigger | |-------|-------------|---------| | `order.created` | New order placed | POST /orders | | `order.updated` | Order status changed | PATCH /orders/:id | | `order.cancelled` | Order cancelled | DELETE /orders/:id | | `payment.captured` | Payment captured | POST /orders/:id/capture | | `payment.refunded` | Payment refunded | POST /orders/:id/refund | | `product.updated` | Product modified | PATCH /products/:id | ### Webhook Payload Format ```json { "id": "wh_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d", "event_type": "order.created", "created_at": "2024-01-15T10:30:00Z", "data": { "id": "ord_12345", "type": "order", "attributes": { "status": "pending_payment", "total": 333.99 } }, "signature": "sha256=abc123def456..." } ``` ### Signature Verification ```python import hmac import hashlib def verify_webhook_signature(payload, signature, secret): expected = hmac.new( secret.encode(), payload.encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature) ``` ### Retry Policy - **Retry attempts:** 3 retries with exponential backoff (1min, 5min, 30min) - **Timeout:** 10 seconds per attempt - **Failure handling:** After 3 failures, webhook is disabled and admin notified - **Idempotency:** Include `X-Idempotency-Key` header for deduplication --- ## 11. OPENAPI SPECIFICATION ```yaml openapi: 3.0.0 info: title: Commerce API version: 1.0.0 description: E-commerce platform API for managing products, orders, and customers contact: name: API Support email: api-support@example.com license: name: MIT url: https://opensource.org/licenses/MIT servers: - url: https://api.example.com/v1 description: Production server - url: https://staging-api.example.com/v1 description: Staging server security: - bearerAuth: [] paths: /products: get: summary: List products description: Returns a paginated list of products with optional filtering operationId: listProducts parameters: - name: page in: query description: Page number schema: type: integer minimum: 1 - name: per_page in: query description: Items per page schema: type: integer minimum: 1 maximum: 100 default: 20 - name: sort in: query description: Field to sort by schema: type: string enum: [name, price, created_at, updated_at] - name: order in: query description: Sort order schema: type: string enum: [asc, desc] default: asc - name: filter[status] in: query description: Filter by status schema: type: string enum: [draft, active, archived] - name: filter[price][gte] in: query description: Minimum price schema: type: number minimum: 0 - name: filter[price][lte] in: query description: Maximum price schema: type: number minimum: 0 - name: search in: query description: Full-text search schema: type: string responses: '200': description: Successful response content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Product' pagination: $ref: '#/components/schemas/Pagination' meta: $ref: '#/components/schemas/Meta' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/RateLimited' post: summary: Create product description: Creates a new product operationId: createProduct security: - bearerAuth: [] scopes: [products:write] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProductCreate' responses: '201': description: Product created content: application/json: schema: $ref: '#/components/schemas/Product' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' /products/{id}: get: summary: Get product by ID description: Returns a single product operationId: getProduct parameters: - name: id in: path required: true description: Product ID schema: type: string pattern: '^prod_[a-f0-9-]{36}$' responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/Product' '404': $ref: '#/components/responses/NotFound' patch: summary: Update product description: Partially updates a product operationId: updateProduct security: - bearerAuth: [] scopes: [products:write] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProductUpdate' responses: '200': description: Product updated content: application/json: schema: $ref: '#/components/schemas/Product' '404': $ref: '#/components/responses/NotFound' delete: summary: Delete product description: Soft-deletes a product operationId: deleteProduct security: - bearerAuth: [] scopes: [products:write] parameters: - name: id in: path required: true schema: type: string responses: '204': description: Product deleted '404': $ref: '#/components/responses/NotFound' /orders: get: summary: List orders description: Returns a paginated list of orders operationId: listOrders security: - bearerAuth: [] scopes: [orders:read] parameters: - name: page in: query schema: type: integer - name: per_page in: query schema: type: integer - name: filter[status] in: query schema: type: string enum: [pending_payment, processing, shipped, delivered, cancelled, refunded] responses: '200': description: Successful response content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Order' pagination: $ref: '#/components/schemas/Pagination' post: summary: Create order description: Creates a new order operationId: createOrder security: - bearerAuth: [] scopes: [orders:write] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/OrderCreate' responses: '201': description: Order created content: application/json: schema: $ref: '#/components/schemas/Order' '422': description: Unprocessable entity (e.g., insufficient stock) content: application/json: schema: $ref: '#/components/schemas/Error' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT schemas: Product: type: object required: [id, type, attributes] properties: id: type: string example: "prod_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d" type: type: string enum: [product] attributes: type: object properties: name: type: string slug: type: string description: type: string price: type: number format: float currency: type: string status: type: string enum: [draft, active, archived] category_id: type: string sku: type: string stock_quantity: type: integer is_featured: type: boolean metadata: type: object created_at: type: string format: date-time updated_at: type: string format: date-time ProductCreate: type: object required: [name, price, currency] properties: name: type: string minLength: 1 maxLength: 200 description: type: string maxLength: 5000 price: type: number minimum: 0 currency: type: string pattern: '^[A-Z]{3}$' category_id: type: string sku: type: string maxLength: 50 stock_quantity: type: integer minimum: 0 is_featured: type: boolean default: false metadata: type: object additionalProperties: true ProductUpdate: type: object properties: name: type: string minLength: 1 maxLength: 200 description: type: string maxLength: 5000 price: type: number minimum: 0 status: type: string enum: [draft, active, archived] category_id: type: string sku: type: string maxLength: 50 stock_quantity: type: integer minimum: 0 is_featured: type: boolean metadata: type: object Order: type: object required: [id, type, attributes] properties: id: type: string example: "ord_8f2b9c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d" type: type: string enum: [order] attributes: type: object properties: order_number: type: string status: type: string enum: [pending_payment, processing, shipped, delivered, cancelled, refunded] subtotal: type: number tax_total: type: number shipping_total: type: number total: type: number currency: type: string customer_id: type: string shipping_address: $ref: '#/components/schemas/Address' billing_address: $ref: '#/components/schemas/Address' placed_at: type: string format: date-time OrderCreate: type: object required: [customer_id, line_items, shipping_address] properties: customer_id: type: string line_items: type: array minItems: 1 items: type: object required: [product_id, quantity] properties: product_id: type: string quantity: type: integer minimum: 1 shipping_address: $ref: '#/components/schemas/Address' billing_address: $ref: '#/components/schemas/Address' Address: type: object required: [line1, city, country] properties: line1: type: string line2: type: string city: type: string state: type: string postal_code: type: string country: type: string pattern: '^[A-Z]{2}$' Pagination: type: object properties: total: type: integer page: type: integer per_page: type: integer total_pages: type: integer next_cursor: type: string has_more: type: boolean Meta: type: object properties: request_id: type: string timestamp: type: string format: date-time api_version: type: string Error: type: object properties: error: type: object properties: code: type: string message: type: string details: type: array items: type: object properties: field: type: string code: type: string message: type: string request_id: type: string documentation_url: type: string responses: ValidationError: description: Validation error content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: Authentication required content: application/json: schema: $ref: '#/components/schemas/Error' Forbidden: description: Insufficient permissions content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' RateLimited: description: Rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' ``` --- ## 12. SDK CONSIDERATIONS ### Recommended SDK Patterns **Language-specific naming conventions:** | Language | Package Name | Naming Style | Example | |----------|-------------|--------------|---------| | Python | `commerce-api` | snake_case | `client.products.list()` | | JavaScript | `@example/commerce-api` | camelCase | `client.products.list()` | | Ruby | `commerce_api` | snake_case | `client.products.list` | | Go | `commerce-api` | camelCase | `client.Products().List()` | | Java | `com.example.commerce` | camelCase | `client.products().list()` | ### SDK Structure ``` commerce-api/ ├── README.md ├── LICENSE ├── setup.py / package.json / Gemfile ├── src/ │ ├── client.py # Main client class │ ├── resources/ │ │ ├── products.py # Product resource │ │ ├── orders.py # Order resource │ │ └── customers.py # Customer resource │ ├── errors.py # Exception classes │ ├── pagination.py # Pagination helpers │ └── auth.py # Authentication handling └── tests/ ├── test_products.py ├── test_orders.py └── test_auth.py ``` ### Error Handling Expectations ```python # Python SDK example from commerce_api import Client, CommerceAPIError client = Client(api_key="live_abc123") try: products = client.products.list( filters={"category": "electronics"}, sort="price", order="asc" ) for product in products: print(f"{product.name}: ${product.price}") except CommerceAPIError as e: print(f"Error {e.status_code}: {e.code}") print(f"Request ID: {e.request_id}") ``` ### Pagination Helpers ```python # Automatic pagination handling products = client.products.list(per_page=100) while products.has_more: products = client.products.list(cursor=products.next_cursor) # Process products ``` ### SDK Best Practices 1. **Automatic retry** with exponential backoff for 429 and 5xx errors 2. **Request timeout** defaults (30s connect, 60s read) 3. **Logging** with request IDs for correlation 4. **Type hints** for all methods and parameters 5. **Comprehensive documentation** with examples 6. **Versioned SDK releases** matching API versions 7. **Async support** for high-concurrency applications --- ## Design Rationale Summary ### Why REST over GraphQL? - **Simplicity:** REST is well-understood and easy to debug - **Caching:** HTTP caching works naturally with REST - **Scalability:** Stateless design scales horizontally - **Tooling:** Mature ecosystem of tools and libraries ### Why JSON:API Specification? - **Consistency:** Standardized structure across all resources - **Relationships:** Clean handling of related resources - **Sparse fieldsets:** Efficient payload sizes - **Inclusion:** Reduce N+1 query problems ### Why Hybrid Pagination? - **Flexibility:** Supports both simple and complex use cases - **Performance:** Cursor-based for large datasets - **Developer experience:** Offset-based for simple needs ### Why OAuth 2.0 + JWT? - **Industry standard:** Well-tested and widely supported - **Stateless:** JWT allows stateless authentication - **Scopes:** Granular permission control - **Refresh tokens:** Secure long-lived sessions --- This API design provides a complete, production-ready foundation that follows industry best practices while remaining pragmatic and developer-friendly. The design is consistent, well-documented, and includes all necessary components for building a robust e-commerce platform API.

전체 프롬프트를 보려면 로그인하세요

Continue with:

By logging in, you agree to our Terms of Use and Privacy Policy

사용법

이 프롬프트는 coding와 함께 사용하도록 설계되었습니다. 위의 프롬프트 내용을 복사하여 원하는 AI 도구에 붙여넣으세요.

최상의 결과를 얻으려면 자리 표시자(대괄호 또는 대문자로 표시)를 특정 요구 사항으로 사용자 지정할 수 있습니다.

참고 자료

분류:coding| api| rest| backend

토론