{"openapi":"3.0.3","info":{"title":"API Learning Sandbox","description":"## Welcome to the API Learning Sandbox 🧪\n\nA hands-on API testing platform for learning **REST**, **GraphQL**, **SOAP**, and **Authentication**.\n\n### Quick Start\n1. **No login required** — a session is auto-created on your first request\n2. Your session ID is returned in the `x-session-id` response header\n3. All data you create is **private to your session** and **auto-expires** in 30 minutes\n4. Use the REST, GraphQL, or SOAP endpoints — they all share the same data store\n\n### Authentication Methods\n| Method | How to use |\n|--------|-----------|\n| **API Key** | Add header `x-api-key: demo-key-sandbox-2026` |\n| **JWT** | POST `/auth/token` → use `Authorization: Bearer <token>` |\n| **OAuth2** | POST `/auth/oauth` with client credentials |\n\n### Simulation Features\nAdd these query params to any REST endpoint:\n- `?delay=2000` — add 2 second artificial delay\n- `?error=500` — force a 500 error response\n- `?random_fail=true` — 30% random failure chance\n\n### Rate Limiting\n100 requests/minute per IP. Headers: `X-RateLimit-Remaining`\n\n### Entities Available\n- `users` — name, email, role, age\n- `products` — name, price, description, stock, category\n- `orders` — user_id, product_id, quantity, status, notes\n\n### Standard Demo Dataset\nYour first REST request auto-seeds your session with standard users, products,\nand orders — no special header needed, so every entity endpoint below always\nhas data to test against. Create/update/delete freely for practice: the seed\nonly ever runs once per session, so your edits are never overwritten. See\n`GET /api/v1/demo` for the fixed record IDs, and `POST /api/v1/demo/reset`\nto restore your session to the standard dataset at any time.\n\n### HTTP QUERY Method — search with a request body\nEvery entity below also supports the **QUERY** method — a safe, idempotent\n\"GET with a JSON body\" ([IETF draft](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/)).\nIt isn't shown as a separate operation below because OpenAPI has no schema\nslot for custom HTTP methods, but it's fully implemented on every entity path\nyou see here — same path, method `QUERY` instead of `GET`, with a JSON body:\n\n```\nQUERY /api/v1/{entity}\nContent-Type: application/json\n\n{\n  \"filters\": { \"price\": { \"gte\": 10, \"lte\": 100 }, \"category\": [\"books\", \"games\"] },\n  \"sort\": \"price\", \"order\": \"asc\", \"limit\": 20, \"fields\": [\"name\", \"price\"]\n}\n```\nFilter operators: `eq`, `ne`, `contains`, `in`, `nin`, `gt`, `gte`, `lt`, `lte`\n(combine per field — they're AND-ed). A teaching endpoint is also available at\n`QUERY /api/v1/echo`, which just reflects your request back to you.\n","version":"1.0.0","contact":{"name":"TotalShiftLeft","url":"https://demo.totalshiftleft.ai"},"license":{"name":"MIT"}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Demo keys: `demo-key-sandbox-2026` or `admin-key-sandbox-2026`"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Obtain via POST /auth/token"},"SessionHeader":{"type":"apiKey","in":"header","name":"x-session-id","description":"Session ID (auto-created on first request, returned in response headers)"}},"schemas":{"User":{"type":"object","description":"A sandbox user record.","properties":{"id":{"type":"string","format":"uuid","description":"Unique record ID"},"name":{"type":"string","description":"Full name"},"email":{"type":"string","format":"email","description":"Email address"},"role":{"type":"string","enum":["user","admin","moderator"],"description":"User role"},"age":{"type":"integer","nullable":true,"description":"Age in years"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Product":{"type":"object","description":"A catalogue product.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Product name"},"price":{"type":"number","description":"Unit price"},"description":{"type":"string","description":"Product description"},"stock":{"type":"integer","description":"Units available"},"category":{"type":"string","description":"Product category"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Order":{"type":"object","description":"An order linking a user to a product.","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"quantity":{"type":"integer","description":"Quantity ordered"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string","description":"Optional notes"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user":{"type":"object","nullable":true,"description":"Populated when ?expand=user"},"product":{"type":"object","nullable":true,"description":"Populated when ?expand=product"}}},"UserInput":{"type":"object","required":["name","email"],"description":"Payload for creating or fully replacing a user.","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Full name"},"email":{"type":"string","format":"email","maxLength":255,"description":"Email address (unique per session)"},"role":{"type":"string","enum":["user","admin","moderator"],"default":"user","description":"User role"},"age":{"type":"integer","minimum":0,"maximum":150,"description":"Age in years"}},"additionalProperties":false},"ProductInput":{"type":"object","required":["name","price"],"description":"Payload for creating or fully replacing a product.","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Product name"},"price":{"type":"number","exclusiveMinimum":0,"description":"Unit price (must be > 0)"},"description":{"type":"string","maxLength":500,"default":"","description":"Product description"},"stock":{"type":"integer","minimum":0,"default":0,"description":"Units available in stock"},"category":{"type":"string","maxLength":50,"default":"general","description":"Product category"}},"additionalProperties":false},"OrderInput":{"type":"object","description":"Payload for creating a new order.","properties":{"user_id":{"type":"string","format":"uuid","description":"ID of the user placing the order"},"product_id":{"type":"string","format":"uuid","description":"ID of the product being ordered"},"quantity":{"type":"integer","minimum":1,"default":1,"description":"Quantity ordered"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"],"default":"pending","description":"Initial order status"},"notes":{"type":"string","maxLength":500,"default":"","description":"Optional order notes"}},"additionalProperties":false},"UserPatch":{"type":"object","description":"Partial update payload for a user — include only fields to change.","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","format":"email","maxLength":255},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","minimum":0,"maximum":150}},"additionalProperties":false},"ProductPatch":{"type":"object","description":"Partial update payload for a product — include only fields to change.","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"price":{"type":"number","exclusiveMinimum":0},"description":{"type":"string","maxLength":500},"stock":{"type":"integer","minimum":0},"category":{"type":"string","maxLength":50}},"additionalProperties":false},"OrderPatch":{"type":"object","description":"Partial update payload for an order — include only fields to change.","properties":{"quantity":{"type":"integer","minimum":1},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string","maxLength":500}},"additionalProperties":false},"Pagination":{"type":"object","description":"Pagination metadata returned with list responses.","properties":{"total":{"type":"integer","description":"Total matching records"},"page":{"type":"integer","description":"Current page number"},"limit":{"type":"integer","description":"Results per page"},"pages":{"type":"integer","description":"Total page count"},"hasNext":{"type":"boolean","description":"Whether a next page exists"},"hasPrev":{"type":"boolean","description":"Whether a previous page exists"}}},"Error":{"type":"object","description":"Standard error response envelope.","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST","description":"Machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"details":{"type":"array","description":"Field-level validation errors (present on 400 responses)","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}},"paths":{"/health":{"get":{"summary":"Health check","tags":["System"],"description":"Returns server status and uptime.","responses":{"200":{"description":"Default Response"}}}},"/api":{"get":{"summary":"API root — getting started guide","tags":["System"],"responses":{"200":{"description":"Default Response"}}}},"/session":{"get":{"summary":"Get current session info","tags":["System"],"description":"Returns your current session ID and expiry. Useful for debugging cross-protocol requests.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/demo":{"get":{"summary":"Standard demo dataset — how to use it","tags":["Demo Data"],"description":"Explains the standard demo dataset every session is seeded with, and whether YOUR current session has been seeded yet.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/demo/reset":{"post":{"summary":"Restore the standard demo dataset","tags":["Demo Data"],"description":"Wipes your current session's users/products/orders and re-seeds the standard dataset. Useful after you have modified or deleted records while learning.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/users":{"post":{"summary":"Create a new user","tags":["Users"],"description":"Creates a new record in the sandbox. Data is session-scoped and auto-expires in 30 minutes.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","email"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Full name"},"email":{"type":"string","format":"email","maxLength":255,"description":"Email address (unique per session)"},"role":{"type":"string","enum":["user","admin","moderator"],"default":"user","description":"User role"},"age":{"type":"integer","minimum":0,"maximum":150,"description":"Age in years"}},"additionalProperties":false}}},"required":true},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"get":{"summary":"List users","tags":["Users"],"description":"Returns a paginated list. Supports `?page`, `?limit`, `?sort`, `?order`, and any field as a filter (e.g. `?status=pending`). Also supports `?delay`, `?error`, `?random_fail` for simulation. Need richer filters (ranges, contains, in-lists)? Send the same request as **QUERY /api/v1/users** with a JSON body instead — see the API description above.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number (1-based)"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"in":"query","name":"limit","required":false,"description":"Results per page (max 100)"},{"schema":{"type":"string","default":"created_at"},"in":"query","name":"sort","required":false,"description":"Field to sort by (e.g. name, created_at)"},{"schema":{"type":"string","enum":["asc","desc","ASC","DESC"],"default":"desc"},"in":"query","name":"order","required":false,"description":"Sort direction"},{"schema":{"type":"integer","minimum":0,"maximum":10000},"in":"query","name":"delay","required":false,"description":"Simulation: artificial delay in ms"},{"schema":{"type":"integer"},"in":"query","name":"error","required":false,"description":"Simulation: force this HTTP status code as an error"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"random_fail","required":false,"description":"Simulation: 30% random failure rate"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer","description":"Total matching records"},"page":{"type":"integer"},"limit":{"type":"integer"},"pages":{"type":"integer","description":"Total page count"},"hasNext":{"type":"boolean"},"hasPrev":{"type":"boolean"}}}}}}}}}}},"/api/v1/users/{id}":{"get":{"summary":"Get a single user by ID","tags":["Users"],"description":"Fetch one record by UUID.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"put":{"summary":"Replace a user (full update)","tags":["Users"],"description":"Full replacement — all required fields must be supplied. Missing optional fields revert to defaults.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","email"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Full name"},"email":{"type":"string","format":"email","maxLength":255,"description":"Email address (unique per session)"},"role":{"type":"string","enum":["user","admin","moderator"],"default":"user","description":"User role"},"age":{"type":"integer","minimum":0,"maximum":150,"description":"Age in years"}},"additionalProperties":false}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"patch":{"summary":"Partially update a user (PATCH)","tags":["Users"],"description":"Send only the fields you want to change. Omitted fields are left as-is.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","format":"email","maxLength":255},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","minimum":0,"maximum":150}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"delete":{"summary":"Delete a user by ID","tags":["Users"],"description":"Permanently removes the record from the session. Returns 204 No Content on success.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"204":{"description":"Deleted successfully"},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}},"/api/v1/orders":{"post":{"summary":"Create a new order","tags":["Orders"],"description":"Creates a new record in the sandbox. Data is session-scoped and auto-expires in 30 minutes.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid","description":"ID of the user placing the order"},"product_id":{"type":"string","format":"uuid","description":"ID of the product being ordered"},"quantity":{"type":"integer","minimum":1,"default":1,"description":"Quantity ordered"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"],"default":"pending","description":"Order status"},"notes":{"type":"string","maxLength":500,"default":"","description":"Optional order notes"}},"additionalProperties":false}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"quantity":{"type":"integer"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=user"},"product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=product"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"get":{"summary":"List orders","tags":["Orders"],"description":"Returns a paginated list. Supports `?page`, `?limit`, `?sort`, `?order`, and any field as a filter (e.g. `?status=pending`). Also supports `?delay`, `?error`, `?random_fail` for simulation. Need richer filters (ranges, contains, in-lists)? Send the same request as **QUERY /api/v1/orders** with a JSON body instead — see the API description above.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number (1-based)"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"in":"query","name":"limit","required":false,"description":"Results per page (max 100)"},{"schema":{"type":"string","default":"created_at"},"in":"query","name":"sort","required":false,"description":"Field to sort by (e.g. name, created_at)"},{"schema":{"type":"string","enum":["asc","desc","ASC","DESC"],"default":"desc"},"in":"query","name":"order","required":false,"description":"Sort direction"},{"schema":{"type":"integer","minimum":0,"maximum":10000},"in":"query","name":"delay","required":false,"description":"Simulation: artificial delay in ms"},{"schema":{"type":"integer"},"in":"query","name":"error","required":false,"description":"Simulation: force this HTTP status code as an error"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"random_fail","required":false,"description":"Simulation: 30% random failure rate"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"quantity":{"type":"integer"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=user"},"product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=product"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer","description":"Total matching records"},"page":{"type":"integer"},"limit":{"type":"integer"},"pages":{"type":"integer","description":"Total page count"},"hasNext":{"type":"boolean"},"hasPrev":{"type":"boolean"}}}}}}}}}}},"/api/v1/orders/{id}":{"get":{"summary":"Get a single order by ID","tags":["Orders"],"description":"Fetch one record by UUID. Add `?expand=user,product` to inline the linked user and product objects.","parameters":[{"schema":{"type":"string","example":"user,product"},"in":"query","name":"expand","required":false,"description":"Comma-separated relations to inline: user, product"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"quantity":{"type":"integer"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=user"},"product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=product"}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"put":{"summary":"Replace a order (full update)","tags":["Orders"],"description":"Full replacement — all required fields must be supplied. Missing optional fields revert to defaults.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid","description":"ID of the user placing the order"},"product_id":{"type":"string","format":"uuid","description":"ID of the product being ordered"},"quantity":{"type":"integer","minimum":1,"default":1,"description":"Quantity ordered"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"],"default":"pending","description":"Order status"},"notes":{"type":"string","maxLength":500,"default":"","description":"Optional order notes"}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"quantity":{"type":"integer"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=user"},"product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=product"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"patch":{"summary":"Partially update a order (PATCH)","tags":["Orders"],"description":"Send only the fields you want to change. Omitted fields are left as-is.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"quantity":{"type":"integer","minimum":1},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string","maxLength":500}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"quantity":{"type":"integer"},"status":{"type":"string","enum":["pending","processing","completed","cancelled"]},"notes":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["user","admin","moderator"]},"age":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=user"},"product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"nullable":true,"description":"Populated when ?expand=product"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"delete":{"summary":"Delete a order by ID","tags":["Orders"],"description":"Permanently removes the record from the session. Returns 204 No Content on success.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"204":{"description":"Deleted successfully"},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}},"/api/v1/products":{"post":{"summary":"Create a new product","tags":["Products"],"description":"Creates a new record in the sandbox. Data is session-scoped and auto-expires in 30 minutes.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","price"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Product name"},"price":{"type":"number","exclusiveMinimum":0,"description":"Unit price (must be > 0)"},"description":{"type":"string","maxLength":500,"default":"","description":"Product description"},"stock":{"type":"integer","minimum":0,"default":0,"description":"Units available in stock"},"category":{"type":"string","maxLength":50,"default":"general","description":"Product category"}},"additionalProperties":false}}},"required":true},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"get":{"summary":"List products","tags":["Products"],"description":"Returns a paginated list. Supports `?page`, `?limit`, `?sort`, `?order`, and any field as a filter (e.g. `?status=pending`). Also supports `?delay`, `?error`, `?random_fail` for simulation. Need richer filters (ranges, contains, in-lists)? Send the same request as **QUERY /api/v1/products** with a JSON body instead — see the API description above.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number (1-based)"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"in":"query","name":"limit","required":false,"description":"Results per page (max 100)"},{"schema":{"type":"string","default":"created_at"},"in":"query","name":"sort","required":false,"description":"Field to sort by (e.g. name, created_at)"},{"schema":{"type":"string","enum":["asc","desc","ASC","DESC"],"default":"desc"},"in":"query","name":"order","required":false,"description":"Sort direction"},{"schema":{"type":"integer","minimum":0,"maximum":10000},"in":"query","name":"delay","required":false,"description":"Simulation: artificial delay in ms"},{"schema":{"type":"integer"},"in":"query","name":"error","required":false,"description":"Simulation: force this HTTP status code as an error"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"random_fail","required":false,"description":"Simulation: 30% random failure rate"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer","description":"Total matching records"},"page":{"type":"integer"},"limit":{"type":"integer"},"pages":{"type":"integer","description":"Total page count"},"hasNext":{"type":"boolean"},"hasPrev":{"type":"boolean"}}}}}}}}}}},"/api/v1/products/{id}":{"get":{"summary":"Get a single product by ID","tags":["Products"],"description":"Fetch one record by UUID.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"put":{"summary":"Replace a product (full update)","tags":["Products"],"description":"Full replacement — all required fields must be supplied. Missing optional fields revert to defaults.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name","price"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Product name"},"price":{"type":"number","exclusiveMinimum":0,"description":"Unit price (must be > 0)"},"description":{"type":"string","maxLength":500,"default":"","description":"Product description"},"stock":{"type":"integer","minimum":0,"default":0,"description":"Units available in stock"},"category":{"type":"string","maxLength":50,"default":"general","description":"Product category"}},"additionalProperties":false}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"patch":{"summary":"Partially update a product (PATCH)","tags":["Products"],"description":"Send only the fields you want to change. Omitted fields are left as-is.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"price":{"type":"number","exclusiveMinimum":0},"description":{"type":"string","maxLength":500},"stock":{"type":"integer","minimum":0},"category":{"type":"string","maxLength":50}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},"stock":{"type":"integer"},"category":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"description":"Validation failed","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"delete":{"summary":"Delete a product by ID","tags":["Products"],"description":"Permanently removes the record from the session. Returns 204 No Content on success.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true,"description":"Record UUID"}],"responses":{"204":{"description":"Deleted successfully"},"404":{"description":"Record not found","content":{"application/json":{"schema":{"description":"Record not found","type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"BAD_REQUEST"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}},"/api/v1/flows":{"get":{"summary":"List available end-to-end flows","tags":["End-to-End Flows"],"description":"Returns metadata for all automated demo flows. Each flow runs multiple API calls in sequence and returns every step result.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/flows/order-placement":{"post":{"summary":"Flow: Create user → product → order","tags":["End-to-End Flows"],"description":"Runs the full order placement flow in one call.\nStep 1 — POST /api/v1/users — creates a demo customer.\nStep 2 — POST /api/v1/products — creates a demo product.\nStep 3 — POST /api/v1/orders — places an order linking the user and product by ID.\nReturns all three records plus a tip to expand the order.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/flows/auth-and-data":{"post":{"summary":"Flow: Issue JWT → create data → list data","tags":["End-to-End Flows"],"description":"Demonstrates the authenticate-then-write pattern.\nStep 1 — POST /auth/token — issues a JWT for the demo user \"alice\".\nStep 2 — POST /api/v1/users — creates a user record in the session.\nStep 3 — GET /api/v1/users — lists the most recent 5 users in the session.\nUse the access_token from step 1 with the Authorization: Bearer header on real requests.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/flows/cross-protocol":{"post":{"summary":"Flow: REST create → GraphQL read → REST delete","tags":["End-to-End Flows"],"description":"Proves all three protocols share one session-scoped data store.\nStep 1 — POST /api/v1/users (REST) — creates a user.\nStep 2 — returns the equivalent GraphQL query — run it at /graphql to read the same record.\nStep 3 — returns the REST delete URL — call it to remove the record (disappears from GraphQL too).","responses":{"200":{"description":"Default Response"}}}},"/api/v1/flows/seed-store":{"post":{"summary":"Seed the store with demo products","tags":["End-to-End Flows"],"description":"Creates 4 realistic products in your session so other flows have inventory to work with.","responses":{"200":{"description":"Default Response"}}}},"/api/v1/flows/customer-journey":{"post":{"summary":"Flow: Shopper registers → browses → orders → confirms","tags":["End-to-End Flows"],"description":"A complete customer journey across 4 API calls.\nStep 1 — Customer registers an account (POST /api/v1/users).\nStep 2 — Customer browses the product catalogue (GET /api/v1/products).\nStep 3 — Customer places an order linking their account to a product (POST /api/v1/orders).\nStep 4 — Customer views order confirmation with full details expanded (GET /api/v1/orders/:id?expand=user,product).","responses":{"200":{"description":"Default Response"}}}},"/api/v1/flows/process-order":{"post":{"summary":"Flow: Manager receives → processes → completes an order","tags":["End-to-End Flows"],"description":"Shows the order status lifecycle from a store manager perspective.\nStep 1 — A new order arrives with status \"pending\".\nStep 2 — Manager accepts it: PATCH status to \"processing\".\nStep 3 — Manager fulfils it: PATCH status to \"completed\".","responses":{"200":{"description":"Default Response"}}}},"/auth/token":{"post":{"summary":"Issue a JWT access token","tags":["Authentication"],"description":"Login with demo credentials to receive a JWT.\n\n**Demo accounts:**\n| Email | Password | Role |\n|---|---|---|\n| alice@demo.com | alice123 | admin |\n| bob@demo.com | bob123 | user |\n| charlie@demo.com | charlie123 | moderator |","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string","example":"alice@demo.com"},"password":{"type":"string","example":"alice123"}}}}},"required":true},"responses":{"200":{"description":"Default Response"}}}},"/auth/verify":{"post":{"summary":"Verify a JWT and return its claims","tags":["Authentication"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}},"required":true},"responses":{"200":{"description":"Default Response"}}}},"/auth/me":{"get":{"summary":"Get the authenticated identity for the current request","tags":["Authentication"],"description":"Pass either `Authorization: Bearer <token>` or `x-api-key: <key>`. Returns the resolved identity.","responses":{"200":{"description":"Default Response"}}}},"/auth/oauth":{"post":{"summary":"OAuth2 client_credentials grant (simplified)","tags":["Authentication"],"description":"Simulated OAuth2 flow. Use client_id=`sandbox-client` and client_secret=`sandbox-secret`.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"type":"string","enum":["client_credentials"]},"client_id":{"type":"string","example":"sandbox-client"},"client_secret":{"type":"string","example":"sandbox-secret"},"scope":{"type":"string","example":"read write"}}}}},"required":true},"responses":{"200":{"description":"Default Response"}}}},"/auth/apikey-info":{"get":{"summary":"Information about API Key authentication","tags":["Authentication"],"description":"Demo API keys for testing. Send as `x-api-key` header.","responses":{"200":{"description":"Default Response"}}}},"/auth/methods":{"get":{"summary":"List every testable authentication scheme","tags":["Auth Testing"],"description":"Catalog of auth schemes with demo credentials and per-tool setup notes. Hit /auth/protected/{id} to test one.","responses":{"200":{"description":"Default Response"}}}},"/auth/protected/{scheme}":{"get":{"summary":"Test a single authentication scheme","tags":["Auth Testing"],"description":"Send credentials for the given scheme. 200 + identity on success; 401 + reason (and the correct challenge header) on failure.","parameters":[{"schema":{"type":"string"},"in":"path","name":"scheme","required":true}],"responses":{"200":{"description":"Default Response"}}},"post":{"summary":"Test a single authentication scheme","tags":["Auth Testing"],"description":"Send credentials for the given scheme. 200 + identity on success; 401 + reason (and the correct challenge header) on failure.","parameters":[{"schema":{"type":"string"},"in":"path","name":"scheme","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/auth/oauth/authorize":{"get":{"summary":"OAuth2 authorization endpoint (authorization_code, PKCE)","tags":["Auth Testing"],"description":"Auto-approves a demo user and returns an authorization code. With redirect_uri it 302-redirects with ?code&state; without one it renders a copyable code.","responses":{"200":{"description":"Default Response"}}}},"/auth/oauth/token":{"post":{"summary":"OAuth2 token endpoint (client_credentials, password, authorization_code, refresh_token)","tags":["Auth Testing"],"description":"Unified grant endpoint. Accepts JSON or application/x-www-form-urlencoded. Returns access_token (JWT) and, for user grants, a rotating refresh_token.","responses":{"200":{"description":"Default Response"}}}},"/graphql":{"get":{"parameters":[{"schema":{"type":"string"},"in":"query","name":"query","required":false},{"schema":{"type":"boolean"},"in":"query","name":"persisted","required":false},{"schema":{"type":["string","null"]},"in":"query","name":"operationName","required":false},{"schema":{"type":"string"},"in":"query","name":"variables","required":false},{"schema":{"type":"string"},"in":"query","name":"extensions","required":false}],"responses":{"2XX":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":["null","object"],"additionalProperties":true},"errors":{"type":"array","items":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"locations":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"column":{"type":"integer"}}}},"path":{"type":"array","items":{"type":"string"}},"extensions":{"type":"object","properties":{"code":{"type":"string"}},"additionalProperties":true}}}},"extensions":{"type":"object","additionalProperties":true}}}}}}}},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"persisted":{"type":"boolean"},"operationName":{"type":["string","null"]},"variables":{"type":["object","null"]},"extensions":{"type":"object"}}}}}},"responses":{"2XX":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":["null","object"],"additionalProperties":true},"errors":{"type":"array","items":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"locations":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"column":{"type":"integer"}}}},"path":{"type":"array","items":{"type":"string"}},"extensions":{"type":"object","properties":{"code":{"type":"string"}},"additionalProperties":true}}}},"extensions":{"type":"object","additionalProperties":true}}}}}}}}},"/soap/":{"get":{"summary":"SOAP WSDL / usage info","tags":["SOAP"],"description":"Append ?wsdl to get the WSDL definition. Otherwise returns JSON usage guide.","responses":{"200":{"description":"Default Response"}}},"post":{"summary":"Execute a SOAP operation","tags":["SOAP"],"description":"Supported operations: CreateUser, GetUsers, GetUser, UpdateUser, DeleteUser, CreateProduct, GetProducts, GetProduct, UpdateProduct, DeleteProduct, CreateOrder, GetOrders, GetOrder, UpdateOrder, DeleteOrder.","responses":{"200":{"description":"Default Response"}}}},"/learn/":{"get":{"summary":"List all learning scenarios","tags":["Learning"],"description":"Returns guided exercises for learning API testing across REST, GraphQL, SOAP, and authentication.","responses":{"200":{"description":"Default Response"}}}},"/learn/{id}":{"get":{"summary":"Get a specific learning scenario with all steps","tags":["Learning"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/status.json":{"get":{"summary":"Machine-readable status","tags":["System"],"description":"Live operational status, days online since public launch, current process uptime, active sessions, sessions today, SLO target, rate-limit policy and pricing pledge. Designed for LLM crawlers and external uptime monitors. No auth required, no rate limit.","responses":{"200":{"description":"Default Response"}}}}},"servers":[{"url":"https://demo.totalshiftleft.ai","description":"API Learning Sandbox"}],"tags":[{"name":"Users","description":"User management — create, read, update, delete"},{"name":"Products","description":"Product catalogue — create, read, update, delete"},{"name":"Orders","description":"Order management — create, read, update, delete; supports ?expand=user,product"},{"name":"Demo Data","description":"The standard, always-available demo dataset — how to use it and how to reset it"},{"name":"Authentication","description":"API Key, JWT, and OAuth2 simulation"},{"name":"GraphQL","description":"GraphQL endpoint (use /graphql directly or GraphiQL UI)"},{"name":"SOAP","description":"SOAP 1.1 endpoint with WSDL"},{"name":"Learning","description":"Guided scenarios and exercises"},{"name":"System","description":"Health and session info"}],"externalDocs":{"url":"https://demo.totalshiftleft.ai/docs","description":"Full API Learning Guide"}}