{"openapi":"3.0.3","info":{"title":"WSQ API Lab — by SoftTelRG, for WebSureQTool","version":"1.0.0","description":"A free, open reference REST API test site by **SoftTelRG LLC** — the official practice API for [WebSureQTool](https://websureqtool.com/), a local-first QA workspace for Web UI and API testing. Point WebSureQTool’s API module at this spec to exercise every scenario: JWT auth, full CRUD, typed/required query + header params, JSON bodies with validation, pagination, filtering, sorting, ETags, rate limiting, and structured error envelopes. Free for anyone practicing API test automation. Companion Web UI test site: https://wsqdemo.com/.","termsOfService":"https://websureqtool.com/terms","contact":{"name":"SoftTelRG LLC","url":"https://www.softtelrg.com/"},"license":{"name":"Free for QA practice, training, and testing"}},"externalDocs":{"description":"WebSureQTool — local-first QA workspace for Web UI and API testing (by SoftTelRG)","url":"https://websureqtool.com/"},"servers":[{"url":"https://api.wsqdemo.com/api/v1","description":"WSQ API Lab v1"}],"tags":[{"name":"auth","description":"Authentication & tokens"},{"name":"products","description":"Product catalog CRUD"},{"name":"orders","description":"Order placement & public tracking (self-contained signed order tokens; trackable on https://wsqdemo.com/track)"},{"name":"system","description":"Health & metadata"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"issue":{"type":"string"}}}}}}}},"Product":{"type":"object","required":["id","name","price","category","sku","inStock"],"properties":{"id":{"type":"integer","example":1},"name":{"type":"string","example":"Relay Mechanical Keyboard"},"price":{"type":"number","example":129},"category":{"type":"string","example":"keyboards"},"sku":{"type":"string","example":"RLY-KBD-001"},"inStock":{"type":"boolean","example":true},"updatedAt":{"type":"string","example":"2026-01-01T00:00:00.000Z"}}},"ProductInput":{"type":"object","required":["name","price","category","sku"],"properties":{"name":{"type":"string","minLength":1,"example":"Relay Wrist Rest"},"price":{"type":"number","minimum":0,"example":24.99},"category":{"type":"string","example":"accessories"},"sku":{"type":"string","pattern":"^RLY-[A-Z]+-[0-9]{3}$","example":"RLY-WRR-009"},"inStock":{"type":"boolean","example":true}}},"Pagination":{"type":"object","required":["page","pageSize","total","totalPages"],"properties":{"page":{"type":"integer"},"pageSize":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasNext":{"type":"boolean"},"hasPrev":{"type":"boolean"}}},"ProductList":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"LoginInput":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string","example":"admin"},"password":{"type":"string","example":"admin123"}}},"OrderInput":{"type":"object","required":["sku","quantity"],"properties":{"sku":{"type":"string","pattern":"^RLY-[A-Z]+-[0-9]{3}$","example":"RLY-KBD-001"},"quantity":{"type":"integer","minimum":1,"maximum":99,"example":2},"customer":{"type":"object","properties":{"name":{"type":"string","example":"QA Tester"}}}}},"Order":{"type":"object","required":["orderId","status","sku","quantity","unitPrice","total"],"properties":{"orderId":{"type":"string","example":"ord_1a2b3c4d5e"},"status":{"type":"string","example":"confirmed"},"sku":{"type":"string","example":"RLY-KBD-001"},"productName":{"type":"string","example":"Relay Mechanical Keyboard"},"quantity":{"type":"integer","example":2},"unitPrice":{"type":"number","example":129},"total":{"type":"number","example":258},"totalFormatted":{"type":"string","example":"$258.00"},"placedAt":{"type":"string","example":"2026-01-01T00:00:00.000Z"},"orderToken":{"type":"string","description":"Self-contained signed token; paste into https://wsqdemo.com/track or pass to /orders/lookup"},"trackUrl":{"type":"string","example":"https://wsqdemo.com/track?order=..."},"customerName":{"type":"string","nullable":true}}},"TokenResponse":{"type":"object","required":["accessToken","tokenType","expiresIn"],"properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"tokenType":{"type":"string","example":"Bearer"},"expiresIn":{"type":"integer","example":3600},"user":{"type":"object","properties":{"username":{"type":"string"},"role":{"type":"string"}}}}}}},"paths":{"/auth/login":{"post":{"tags":["auth"],"operationId":"login","summary":"Exchange credentials for tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/refresh":{"post":{"tags":["auth"],"operationId":"refresh","summary":"Exchange a refresh token for a new access token","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string","example":"wsq-demo-refresh-token"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid refresh token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/token":{"post":{"tags":["auth"],"operationId":"oauthToken","summary":"OAuth2 client-credentials grant (form or JSON) -> access_token","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"type":"string","example":"client_credentials"},"client_id":{"type":"string","example":"wsq-admin"},"client_secret":{"type":"string","example":"admin-secret"}}}},"application/json":{"schema":{"type":"object","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"type":"string","example":"client_credentials"},"client_id":{"type":"string","example":"wsq-admin"},"client_secret":{"type":"string","example":"admin-secret"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string"},"expires_in":{"type":"integer"},"scope":{"type":"string"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/me":{"get":{"tags":["auth"],"operationId":"me","summary":"Return the authenticated principal (Test Auth target)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string"},"role":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products":{"get":{"tags":["products"],"operationId":"listProducts","summary":"List products (paginated, filterable, sortable)","parameters":[{"name":"page","in":"query","required":true,"schema":{"type":"integer","minimum":1,"example":1}},{"name":"pageSize","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":100,"example":10}},{"name":"X-Tenant-Id","in":"header","required":true,"schema":{"type":"integer","example":42}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}},{"name":"category","in":"query","required":false,"schema":{"type":"string"}},{"name":"minPrice","in":"query","required":false,"schema":{"type":"number"}},{"name":"inStock","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","example":"-price"}},{"name":"fields","in":"query","required":false,"schema":{"type":"string","example":"id,name,price"},"description":"Sparse fieldset"},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"example":"json"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductList"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["products"],"operationId":"createProduct","summary":"Create a product (admin)","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Duplicate sku","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products/{id}":{"get":{"tags":["products"],"operationId":"getProduct","summary":"Fetch one product (supports ETag / If-None-Match)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","example":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"304":{"description":"Not modified"},"400":{"description":"Bad id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["products"],"operationId":"replaceProduct","summary":"Replace a product (admin; supports If-Match optimistic concurrency)","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"412":{"description":"Precondition failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["products"],"operationId":"updateProduct","summary":"Partially update a product (admin)","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Relay Mechanical Keyboard (rev B)"},"price":{"type":"number","minimum":0,"example":139},"category":{"type":"string","example":"keyboards"},"inStock":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["products"],"operationId":"deleteProduct","summary":"Delete a product (admin)","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products/bulk":{"post":{"tags":["products"],"operationId":"bulkCreateProducts","summary":"Bulk create products (admin; JSON array body)","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductInput"},"example":[{"name":"Bulk A","price":5,"category":"accessories","sku":"RLY-BLA-701"},{"name":"Bulk B","price":6,"category":"accessories","sku":"RLY-BLB-702"}]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"count":{"type":"integer"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products/{id}/image":{"post":{"tags":["products"],"operationId":"uploadProductImage","summary":"Upload a product image (admin; multipart/form-data, field \"file\")","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","example":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","example":"BASE64_OR_DATA_URL"},"filename":{"type":"string","example":"hero.png"},"caption":{"type":"string","example":"hero shot"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"caption":{"type":"string"}},"required":["file"]}}}},"responses":{"201":{"description":"Uploaded","content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"integer"},"filename":{"type":"string"},"size":{"type":"integer"},"contentType":{"type":"string"}}}}}},"400":{"description":"Missing/invalid file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders":{"post":{"tags":["orders"],"operationId":"createOrder","summary":"Place an order (any authenticated user) -> signed self-contained orderToken, trackable on wsqdemo.com/track","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderInput"}}}},"responses":{"201":{"description":"Order confirmed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown sku","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/lookup":{"get":{"tags":["orders"],"operationId":"lookupOrder","summary":"Public order tracking by signed token (no auth; the token is the proof)","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"},"description":"orderToken returned by POST /orders"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"Missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/jobs/export":{"post":{"tags":["system"],"operationId":"startExport","summary":"Start an async export job (admin) -> 202 Accepted + poll URL","security":[{"bearerAuth":[]}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"poll":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/jobs/{id}":{"get":{"tags":["system"],"operationId":"getJob","summary":"Poll an async job status","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","example":"job_1"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}