{ "openapi": "3.1.0", "info": { "title": "SC Market OpenAPI Definition", "version": "1.0.0", "description": "The API for the SC Market site" }, "paths": { "/api/starmap/route/{from}/{to}": { "get": { "summary": "Get route between locations", "description": "Get a route between two starmap locations", "operationId": "getStarmapRoute", "tags": [ "Starmap" ], "parameters": [ { "name": "from", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Starting location" }, { "name": "to", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Destination location" } ], "responses": { "200": { "description": "Route retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StarmapRoute" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/starmap/route/{identifier}": { "get": { "summary": "Get celestial object", "description": "Get information about a celestial object by identifier", "operationId": "getCelestialObject", "tags": [ "Starmap" ], "parameters": [ { "name": "identifier", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Celestial object identifier" } ], "responses": { "200": { "description": "Celestial object retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StarmapObject" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/starmap/search/{query}": { "get": { "summary": "Search starmap", "description": "Search for locations in the starmap", "operationId": "searchStarmap", "tags": [ "Starmap" ], "parameters": [ { "name": "query", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Search query" } ], "responses": { "200": { "description": "Search results retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StarmapSearchResult" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/profile/auth/sync-handle": { "post": { "summary": "Sync RSI handle from Spectrum profile", "deprecated": false, "description": "Sync the user's RSI handle and display name from their current Spectrum profile. This updates the handle to match what's currently set in their RSI account. User must already be verified.", "operationId": "syncRSIHandle", "tags": [ "Profiles" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": {}, "required": [] } } } }, "responses": { "200": { "description": "RSI handle successfully synced from Spectrum", "content": { "application/json": { "schema": { "properties": { "data": { "$ref": "#/components/schemas/GetCurrentUserProfileSuccess" } }, "required": [ "data" ], "type": "object" } } } }, "400": { "description": "User not eligible for handle sync", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "User must be already verified with a Spectrum ID to sync handle" }, "status": { "type": "string", "example": "error" } }, "required": [ "message", "status" ], "type": "object" } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "402": { "description": "Handle sync failed", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "Could not fetch current Spectrum profile information" }, "status": { "type": "string", "example": "error" } }, "required": [ "message", "status" ], "type": "object" } } } }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/profile/auth/unlink": { "post": { "summary": "Unlink Star Citizen account", "deprecated": false, "description": "Unlink the user's Star Citizen account, returning them to unverified status and resetting usernames to default values based on their Discord ID.", "operationId": "unlinkStarCitizenAccount", "tags": [ "Profiles" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": {}, "required": [] } } } }, "responses": { "200": { "description": "Star Citizen account successfully unlinked", "content": { "application/json": { "schema": { "properties": { "data": { "$ref": "#/components/schemas/GetCurrentUserProfileSuccess" } }, "required": [ "data" ], "type": "object" } } } }, "400": { "description": "User not eligible for account unlink", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "User is not currently verified with a Star Citizen account" }, "status": { "type": "string", "example": "error" } }, "required": [ "message", "status" ], "type": "object" } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/profile": { "put": { "summary": "Update user profile", "deprecated": false, "description": "Update user profile settings including locale preference", "operationId": "updateProfile", "tags": [ "Profiles" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProfileUpdateBody" } } } }, "responses": { "200": { "description": "OK - Profile successfully updated", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "message": { "type": "string", "example": "Locale updated successfully" }, "locale": { "type": "string", "enum": [ "en", "es", "uk", "zh-CN", "fr", "de", "ja" ], "example": "en" } }, "required": [ "message", "locale" ] }, "status": { "type": "string", "example": "success" } }, "required": [ "data", "status" ], "type": "object", "title": "UpdateProfileSuccess" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] }, "get": { "summary": "Get current user profile", "deprecated": false, "description": "Retrieve the complete profile information for the authenticated user including contractors, settings, and preferences", "operationId": "getCurrentUserProfile", "tags": [ "Profiles" ], "parameters": [], "responses": { "200": { "description": "OK - User profile retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GetCurrentUserProfileSuccess" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/profile/avatar": { "post": { "summary": "Upload user profile avatar", "deprecated": false, "description": "Upload a new avatar image for the authenticated user's profile. The image must be in PNG, JPG, or WEBP format and less than 1MB. The image will be processed through content moderation. Send multipart/form-data with 'avatar' field containing the image file.", "operationId": "uploadProfileAvatar", "tags": [ "Profiles" ], "parameters": [], "responses": { "200": { "description": "Avatar uploaded successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "result": { "type": "string", "example": "Avatar uploaded successfully" }, "resource_id": { "type": "string" }, "url": { "type": "string", "format": "uri" } }, "required": [ "result", "resource_id", "url" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/profile/banner": { "post": { "summary": "Upload user profile banner", "deprecated": false, "description": "Upload a new banner image for the authenticated user's profile. The image must be in PNG, JPG, or WEBP format and less than 2.5MB. The image will be processed through content moderation. Send multipart/form-data with 'banner' field containing the image file.", "operationId": "uploadProfileBanner", "tags": [ "Profiles" ], "parameters": [], "responses": { "200": { "description": "Banner uploaded successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "result": { "type": "string", "example": "Banner uploaded successfully" }, "resource_id": { "type": "string" }, "url": { "type": "string", "format": "uri" } }, "required": [ "result", "resource_id", "url" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/profile/blocklist": { "get": { "summary": "Get user's blocklist", "description": "Retrieve the list of users blocked by the current user", "operationId": "getUserBlocklist", "tags": [ "Profiles" ], "responses": { "200": { "description": "OK - Blocklist retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "blocked_id": { "type": "string", "format": "uuid" }, "created_at": { "type": "string", "format": "date-time" }, "reason": { "type": "string" }, "blocked_user": { "type": "object", "properties": { "username": { "type": "string" }, "display_name": { "type": "string" }, "avatar": { "type": "string" } } } } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [ { "userAuth": [] } ] } }, "/api/profile/blocklist/block": { "post": { "summary": "Block a user", "description": "Add a user to the current user's blocklist", "operationId": "blockUser", "tags": [ "Profiles" ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "username": { "type": "string", "description": "Username of the user to block" }, "reason": { "type": "string", "description": "Optional reason for blocking" } }, "required": [ "username" ] } } } }, "responses": { "200": { "description": "OK - User blocked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "message": { "type": "string" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "Not Found - User not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } } } } } }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [ { "userAuth": [] } ] } }, "/api/profile/blocklist/unblock/{username}": { "delete": { "summary": "Unblock a user", "description": "Remove a user from the current user's blocklist", "operationId": "unblockUser", "tags": [ "Profiles" ], "parameters": [ { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Username of the user to unblock" } ], "responses": { "200": { "description": "OK - User unblocked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "message": { "type": "string" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "Not Found - User not found or not blocked", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } } } } } }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [ { "userAuth": [] } ] } }, "/api/profile/email": { "post": { "tags": [ "Email" ], "summary": "Add email address", "description": "Add an email address to your account and select which notification types to enable. A verification email will be sent.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddEmailRequest" } } } }, "responses": { "201": { "description": "Email address added successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddEmailResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "patch": { "tags": [ "Email" ], "summary": "Update email address", "description": "Update your email address. The new address will need to be verified.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateEmailRequest" } } } }, "responses": { "200": { "description": "Email address updated successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddEmailResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "delete": { "tags": [ "Email" ], "summary": "Remove email address", "description": "Remove your email address and all email notification preferences.", "responses": { "200": { "description": "Email address removed successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/profile/email/verify": { "post": { "tags": [ "Email" ], "summary": "Request verification email", "description": "Request a new verification email to be sent.", "responses": { "200": { "description": "Verification email sent", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/profile/email/verify/{token}": { "get": { "tags": [ "Email" ], "summary": "Verify email address", "description": "Verify email address using verification token. Redirects to frontend.", "parameters": [ { "name": "token", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Email verification token" } ], "responses": { "302": { "description": "Redirects to frontend with success/error query parameter" } } } }, "/api/notification/{notification_id}": { "patch": { "summary": "Update notification read status", "description": "Mark a specific notification as read or unread", "operationId": "updateNotification", "tags": [ "Notifications" ], "parameters": [ { "name": "notification_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the notification to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificationUpdateBody" } } } }, "responses": { "200": { "description": "Notification updated successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for notification operations. Anonymous users: 10 req/min, Authenticated users: 30 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "delete": { "summary": "Delete a specific notification", "description": "Remove a single notification by ID", "operationId": "deleteNotification", "tags": [ "Notifications" ], "parameters": [ { "name": "notification_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the notification to delete" } ], "responses": { "200": { "description": "Notification deleted successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for notification operations. Anonymous users: 10 req/min, Authenticated users: 30 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/notification/": { "patch": { "summary": "Bulk update notifications", "description": "Update all notifications for the authenticated user (e.g., mark all as read)", "operationId": "bulkUpdateNotifications", "tags": [ "Notifications" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificationBulkUpdateBody" } } } }, "responses": { "200": { "description": "Notifications updated successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkActionResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "delete": { "summary": "Bulk delete notifications", "description": "Delete multiple notifications by their IDs, or delete all notifications if no IDs provided", "operationId": "bulkDeleteNotifications", "tags": [ "Notifications" ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "notification_ids": { "type": "array", "items": { "type": "string" }, "description": "Array of notification IDs to delete. If omitted or empty, all notifications will be deleted." } } } } } }, "responses": { "200": { "description": "Notifications deleted successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkActionResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/notification/{page}": { "get": { "summary": "Get paginated notifications for user", "description": "Retrieve paginated notifications for the authenticated user with pagination metadata and total unread count matching the current filters", "operationId": "getPaginatedNotifications", "tags": [ "Notifications" ], "parameters": [ { "name": "page", "in": "path", "required": true, "schema": { "type": "integer", "minimum": 0 }, "description": "Page number (0-based)" }, { "name": "pageSize", "in": "query", "required": false, "description": "Number of notifications per page (1-100, default: 20)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }, { "name": "action", "in": "query", "required": false, "description": "Filter notifications by action type. See NotificationActionType schema for available values. Examples: 'order_message', 'offer_message', 'order_create', 'market_item_bid'", "schema": { "allOf": [ { "$ref": "#/components/schemas/NotificationActionType" } ] } }, { "name": "entityId", "in": "query", "required": false, "description": "Filter notifications by entity ID (e.g., order ID, market listing ID). The entity type is determined by the action filter.", "schema": { "type": "string", "format": "uuid" } }, { "name": "scope", "in": "query", "required": false, "description": "Filter notifications by scope: 'individual' for personal notifications, 'organization' for org notifications, 'all' for all notifications.", "schema": { "type": "string", "enum": [ "individual", "organization", "all" ], "default": "all" } }, { "name": "contractorId", "in": "query", "required": false, "description": "Filter notifications by specific organization/contractor ID. Only applies when scope is 'organization'.", "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Paginated notifications retrieved successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedNotificationsResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/push/subscribe": { "post": { "summary": "Subscribe to push notifications", "description": "Register a push subscription for the authenticated user. The subscription allows the server to send push notifications to the user's device.", "operationId": "subscribePush", "tags": [ "Push Notifications" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PushSubscriptionData" } } } }, "responses": { "201": { "description": "Successfully subscribed to push notifications", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PushSubscriptionResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "get": { "summary": "Get push subscriptions", "description": "Get all push subscriptions for the authenticated user. Returns a list of all active push subscriptions associated with the user's account.", "operationId": "getPushSubscriptions", "tags": [ "Push Notifications" ], "responses": { "200": { "description": "Successfully retrieved push subscriptions", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "subscriptions": { "type": "array", "items": { "type": "object", "properties": { "subscription_id": { "type": "string", "format": "uuid", "description": "Unique identifier for the subscription" }, "user_id": { "type": "string", "format": "uuid", "description": "User ID that owns this subscription" }, "endpoint": { "type": "string", "description": "Push service endpoint URL" }, "p256dh": { "type": "string", "description": "P-256 ECDH public key (base64 encoded)" }, "auth": { "type": "string", "description": "Authentication secret (base64 encoded)" }, "user_agent": { "type": "string", "nullable": true, "description": "User agent string when subscription was created" }, "created_at": { "type": "string", "format": "date-time", "description": "When the subscription was created" }, "updated_at": { "type": "string", "format": "date-time", "description": "When the subscription was last updated" } }, "required": [ "subscription_id", "user_id", "endpoint", "p256dh", "auth", "created_at", "updated_at" ] } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/push/subscribe/{subscription_id}": { "delete": { "summary": "Unsubscribe from push notifications", "description": "Remove a push subscription for the authenticated user. The user must own the subscription.", "operationId": "unsubscribePush", "tags": [ "Push Notifications" ], "parameters": [ { "name": "subscription_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "Unique identifier for the subscription" } ], "responses": { "200": { "description": "Successfully unsubscribed from push notifications", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Successfully unsubscribed from push notifications" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "User does not own this subscription", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "example": "You do not own this subscription" } } } } } }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/push/preferences": { "get": { "summary": "Get push notification preferences", "description": "Get all push notification preferences for the authenticated user. Returns preferences for all notification action types, defaulting to enabled if not explicitly set.", "operationId": "getPushPreferences", "tags": [ "Push Notifications" ], "responses": { "200": { "description": "Successfully retrieved push notification preferences", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PushPreferencesResponse" } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "patch": { "summary": "Update push notification preferences", "description": "Update push notification preferences. Supports both single preference updates (for backwards compatibility) and batch updates via a preferences array. This allows users to enable or disable push notifications for specific notification types, and update multiple preferences atomically to avoid race conditions.", "operationId": "updatePushPreference", "tags": [ "Push Notifications" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/PushPreferenceUpdateBody" }, { "$ref": "#/components/schemas/PushPreferencesBatchUpdateBody" } ] } } } }, "responses": { "200": { "description": "Successfully updated push notification preferences", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Successfully updated 5 push notification preferences" }, "preferences": { "type": "array", "description": "Array of updated preferences (for batch updates)", "items": { "type": "object", "properties": { "action": { "type": "string" }, "enabled": { "type": "boolean" }, "contractor_id": { "type": "string", "format": "uuid", "nullable": true } } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/email/preferences": { "get": { "tags": [ "Email" ], "summary": "Get email notification preferences", "description": "Get all email notification preferences for the authenticated user.", "responses": { "200": { "description": "Email preferences retrieved successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmailPreferencesResponse" } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } }, "patch": { "tags": [ "Email" ], "summary": "Update email notification preferences", "description": "Update email notification preferences for one or more notification types.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateEmailPreferencesRequest" } } } }, "responses": { "200": { "description": "Preferences updated successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "preferences": { "type": "array", "items": { "$ref": "#/components/schemas/EmailPreference" } }, "message": { "type": "string" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/email/unsubscribe/{token}": { "post": { "tags": [ "Email" ], "summary": "Unsubscribe from email notifications", "description": "Unsubscribe from email notifications using unsubscribe token. Redirects to frontend.", "parameters": [ { "name": "token", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Unsubscribe token" } ], "responses": { "302": { "description": "Redirects to frontend unsubscribe page" } } } }, "/api/market/stats": { "get": { "tags": [ "Market" ], "summary": "Get market order statistics", "description": "Returns statistics about orders including total count and value. Use format=grafana to get Grafana-compatible format.", "parameters": [ { "name": "format", "in": "query", "description": "Response format - use 'grafana' for Grafana JSON datasource format", "required": false, "schema": { "type": "string", "enum": [ "grafana" ] } } ], "responses": { "200": { "description": "Successfully retrieved order statistics. Returns Grafana format if format=grafana is specified.", "content": { "application/json": { "schema": { "oneOf": [ { "type": "array", "description": "Grafana format - array of time series objects", "items": { "$ref": "#/components/schemas/GrafanaTimeSeries" } }, { "$ref": "#/components/schemas/OrderStats" } ] } } } } } } }, "/api/market/listings/stats": { "post": { "tags": [ "Market" ], "summary": "Get stats for multiple market listings", "description": "Get statistics for multiple market listings. User must have permission to view stats for all requested listings.", "operationId": "getMarketListingsStats", "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "listing_ids": { "type": "array", "items": { "type": "string" }, "description": "Array of market listing IDs to get stats for" } }, "required": [ "listing_ids" ] } } } }, "responses": { "200": { "description": "Successfully retrieved listing statistics", "content": { "application/json": { "schema": { "type": "object", "properties": { "stats": { "type": "array", "items": { "type": "object", "properties": { "listing_id": { "type": "string" }, "order_count": { "type": "number", "description": "Number of active orders for this listing" }, "offer_count": { "type": "number", "description": "Number of active offers for this listing" }, "view_count": { "type": "number", "description": "Number of views for this listing" } }, "required": [ "listing_id", "order_count", "offer_count", "view_count" ] } } }, "required": [ "stats" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/market/listing/{listing_id}": { "put": { "summary": "Update a market listing", "description": "Update various properties of a market listing", "tags": [ "Market", "Market Listing" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListingUpdateRequest" } } } }, "responses": { "200": { "description": "Listing updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateListingResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Invalid listing": { "value": { "error": "Invalid listing" } }, "Missing fields": { "value": { "error": "Missing required fields" } }, "Invalid status": { "value": { "error": "Invalid status" } }, "Invalid quantity": { "value": { "error": "Invalid quantity" } }, "Invalid bid increment": { "value": { "error": "Invalid bid increment!" } }, "Invalid item": { "value": { "error": "Invalid item name" } }, "Invalid photo": { "value": { "error": "Invalid photo!" } }, "Archived listing": { "value": { "error": "Cannot update archived listing" } }, "Auction update": { "value": { "error": "Cannot update auction listings" } }, "Aggregate update": { "value": { "error": "Can't update details for aggregate listing" } }, "Auction price": { "value": { "error": "Cannot edit price of auction" } }, "Non-auction bid": { "value": { "error": "Cannot set bid increment for non auction" } } } } } }, "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Unauthorized contractor": { "value": { "error": "You are not authorized to update listings on behalf of this contractor!" } }, "Unauthorized user": { "value": { "error": "You are not authorized to update this listing!" } } } } } } } } }, "/api/market/listing/{listing_id}/update_quantity": { "post": { "summary": "Update listing quantity", "description": "Update the available quantity of a market listing", "tags": [ "Market", "Market Listing" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateQuantityRequest" } } } }, "responses": { "200": { "description": "Quantity updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateQuantityResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Invalid listing": { "value": { "error": "Invalid listing" } }, "Missing fields": { "value": { "error": "Missing required fields" } }, "Invalid quantity": { "value": { "error": "Invalid quantity" } }, "Archived listing": { "value": { "error": "Cannot update archived listing" } } } } } }, "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Unauthorized contractor": { "value": { "error": "You are not authorized to update listings on behalf of this contractor!" } }, "Unauthorized user": { "value": { "error": "You are not authorized to update this listing!" } } } } } } } } }, "/api/market/listing/{listing_id}/refresh": { "post": { "summary": "Refresh listing expiration", "description": "Reset the expiration date of a market listing to the current date. Can only be done if the current expiration is within 3 days of being one month old.", "tags": [ "Market", "Market Listing" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to refresh" } ], "responses": { "200": { "description": "Listing expiration refreshed successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefreshListingResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Invalid listing": { "value": { "error": "Invalid listing" } }, "Archived listing": { "value": { "error": "Cannot update archived listing" } }, "Too soon": { "value": { "error": "Too soon to refresh" } } } } } }, "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Unauthorized contractor": { "value": { "error": "You are not authorized to update listings on behalf of this contractor!" } }, "Unauthorized user": { "value": { "error": "You are not authorized to update this listing!" } } } } } } } } }, "/api/market/listings/{listing_id}": { "get": { "summary": "Get market listing details", "description": "Returns detailed information about a specific market listing", "tags": [ "Market", "Market Listing" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to retrieve" } ], "responses": { "200": { "description": "Successfully retrieved listing details", "content": { "application/json": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/UniqueListing" }, { "$ref": "#/components/schemas/AggregateListing" } ] } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Invalid listing": { "value": { "error": "Invalid listing" } } } } } } } } }, "/api/market/listing/{listing_id}/orders": { "get": { "summary": "Get paginated orders for a market listing", "description": "Returns paginated orders associated with a specific market listing", "tags": [ "Market", "Market Listing" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to get orders for" }, { "name": "page", "in": "query", "required": false, "schema": { "type": "number", "minimum": 1, "default": 1 }, "description": "Page number (1-based)" }, { "name": "pageSize", "in": "query", "required": false, "schema": { "type": "number", "minimum": 1, "maximum": 100, "default": 20 }, "description": "Number of orders per page" }, { "name": "status", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "not-started,in-progress", "fulfilled,cancelled" ] }, "description": "Filter orders by status" }, { "name": "sortBy", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "timestamp", "status" ], "default": "timestamp" }, "description": "Field to sort by" }, { "name": "sortOrder", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "asc", "desc" ], "default": "desc" }, "description": "Sort order" } ], "responses": { "200": { "description": "Successfully retrieved listing orders", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListingOrdersResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Invalid listing": { "value": { "error": "Invalid listing" } } } } } }, "404": { "description": "Listing not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/market/purchase": { "post": { "summary": "Purchase market listings", "description": "Create a purchase offer for one or more market listings", "tags": [ "Market" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PurchaseRequest" } } } }, "responses": { "200": { "description": "Purchase offer created successfully", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "result": { "type": "string", "enum": [ "Success" ] }, "offer_id": { "type": "string" }, "session_id": { "type": "string" }, "discord_invite": { "type": "string", "nullable": true } }, "required": [ "result", "offer_id", "session_id", "discord_invite" ] } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for critical operations. Anonymous users: 1 req/min, Authenticated users: 2 req/min, Admin users: 5 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/market/listings/{listing_id}/bids": { "post": { "summary": "Place a bid on an auction listing", "description": "Place or update a bid on an auction listing", "operationId": "placeBidOnAuction", "tags": [ "Market", "Auctions" ], "security": [ { "verifiedUser": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MarketBidRequest" } } } }, "responses": { "200": { "description": "Bid placed successfully", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "result": { "type": "string", "enum": [ "Success" ] } }, "required": [ "result" ] } }, "required": [ "data" ], "title": "PlaceBidResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Missing fields": { "value": { "error": "Missing required fields" } }, "Invalid listing": { "value": { "error": "Invalid listing" } }, "Invalid bid": { "value": { "error": "Invalid bid amount!" } }, "Own item": { "value": { "error": "You cannot buy your own item!" } } } } } }, "500": { "description": "Server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Internal error": { "value": { "error": "Internal server error" } }, "Auction ended": { "value": { "error": "Auction is over" } } } } } } }, "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/api/market/listings": { "post": { "summary": "Create a new market listing", "description": "Create a new market listing with optional auction settings", "operationId": "createMarketListing", "tags": [ "Market" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MarketListingCreateRequest" } } } }, "responses": { "200": { "description": "Listing created successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MarketListingComplete" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for critical operations. Anonymous users: 1 req/min, Authenticated users: 2 req/min, Admin users: 5 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "get": { "summary": "Search market listings", "description": "Search for market listings with various filters and status options", "operationId": "searchMarketListings", "tags": [ "Market" ], "parameters": [ { "name": "item_type", "in": "query", "schema": { "type": "string", "nullable": true } }, { "name": "sale_type", "in": "query", "schema": { "type": "string", "nullable": true } }, { "name": "minCost", "in": "query", "schema": { "type": "string" } }, { "name": "maxCost", "in": "query", "schema": { "type": "string", "nullable": true } }, { "name": "quantityAvailable", "in": "query", "schema": { "type": "string" } }, { "name": "query", "in": "query", "schema": { "type": "string" } }, { "name": "sort", "in": "query", "schema": { "type": "string", "enum": [ "date-old", "date-new", "rating", "title", "price-low", "price-high", "quantity-low", "quantity-high", "activity" ] } }, { "name": "index", "in": "query", "schema": { "type": "string", "default": "0" } }, { "name": "page_size", "in": "query", "schema": { "type": "string", "default": 16, "maximum": 96 } }, { "name": "user_seller", "in": "query", "schema": { "type": "string" } }, { "name": "contractor_seller", "in": "query", "schema": { "type": "string" } }, { "name": "listing_type", "in": "query", "schema": { "type": "string", "nullable": true } }, { "name": "statuses", "in": "query", "schema": { "type": "string", "nullable": true }, "description": "Comma-separated list of statuses to include (e.g., 'active', 'active,inactive', 'active,inactive,archived')" } ], "responses": { "200": { "description": "Search completed successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "total": { "type": "integer" }, "listings": { "type": "array", "items": { "$ref": "#/components/schemas/MarketListingSearchResult" } } }, "required": [ "total", "listings" ] } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/market/listing/{listing_id}/photos": { "post": { "summary": "Upload photos for a market listing", "description": "Upload up to 5 photos for a specific market listing. Photos are stored in CDN and linked to the listing. If the total number of photos would exceed 5, the oldest photos will be automatically removed to maintain the limit.", "operationId": "uploadListingPhotos", "tags": [ "Market" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to upload photos for" } ], "responses": { "200": { "description": "Photos uploaded successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhotoUploadResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/market/listings/{listing_id}/views": { "post": { "summary": "Track a view on a market listing", "description": "Records a view on a market listing for analytics purposes", "operationId": "trackMarketListingView", "deprecated": false, "tags": [ "Market" ], "parameters": [ { "name": "listing_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the listing to track view for" } ], "responses": { "200": { "description": "View tracked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/market/mine": { "get": { "summary": "Get my market listings", "description": "Get all market listings created by the authenticated user or their organization with optional search and filtering", "tags": [ "Market", "Market Listing" ], "parameters": [ { "name": "contractor_id", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Contractor ID to get listings for (user must be a member)" }, { "name": "query", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Search query to filter listings by title or description" }, { "name": "statuses", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated list of statuses" }, { "name": "sale_type", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "unique", "aggregate", "multiple", "auction" ] }, "description": "Filter by sale type" }, { "name": "item_type", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by item type" }, { "name": "listing_type", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "unique", "aggregate", "multiple" ] }, "description": "Filter by listing type" }, { "name": "sort", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Sort method" }, { "name": "index", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 }, "description": "Starting index for pagination" }, { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 96, "default": 16 }, "description": "Number of results per page" }, { "name": "minCost", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Minimum price filter" }, { "name": "maxCost", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Maximum price filter" }, { "name": "quantityAvailable", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Minimum quantity available" } ], "responses": { "200": { "description": "Successfully retrieved listings", "content": { "application/json": { "schema": { "type": "object", "properties": { "listings": { "type": "array", "items": { "type": "object" } }, "total": { "type": "integer" } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/market/user/{username}": { "get": { "summary": "Get user's active market listings", "description": "Returns all active market listings for a specific user", "operationId": "getUserListings", "tags": [ "Market" ], "parameters": [ { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Username of the seller whose listings to retrieve" } ], "responses": { "200": { "description": "User's listings retrieved successfully", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/MarketListingComplete" } } } } }, "400": { "description": "Invalid username provided", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } } }, "/api/market/contractor/{spectrum_id}": { "get": { "summary": "Get contractor's market listings", "description": "Returns active market listings for a contractor. If user is a member of the contractor organization, includes internal listings.", "operationId": "getContractorPublicListings", "tags": [ "Market" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Spectrum ID of the contractor organization" } ], "responses": { "200": { "description": "Contractor listings retrieved successfully", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/MarketListingComplete" } } } } }, "400": { "description": "Invalid contractor ID provided", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } } }, "/api/market/aggregates/buyorders": { "get": { "summary": "Get market buy orders", "description": "Returns all market buy orders grouped by game item aggregates", "operationId": "getMarketBuyOrders", "tags": [ "Market", "Aggregates" ], "responses": { "200": { "description": "Buy orders retrieved successfully", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/MarketAggregateComplete" } } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } } }, "/api/market/aggregate/{game_item_id}/chart": { "get": { "summary": "Get buy order chart data", "description": "Returns 30 days of OHLC (Open/High/Low/Close) price and volume data for buy orders of a specific game item", "operationId": "getGameItemBuyOrderChart", "tags": [ "Market", "Aggregates", "Charts" ], "parameters": [ { "name": "game_item_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the game item to get chart data for" } ], "responses": { "200": { "description": "Chart data retrieved successfully", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/BuyOrderChartDataPoint" } } } } }, "400": { "description": "Invalid game item ID provided", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } } }, "/api/market/item/{name}": { "get": { "summary": "Get game item description by name", "description": "Returns detailed information about a game item by its name", "operationId": "getGameItemByName", "tags": [ "Market", "Game Items" ], "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Name of the game item to retrieve" } ], "responses": { "200": { "description": "Game item retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GameItemDescription" } } } }, "400": { "description": "Game item not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Item not found": { "value": { "error": "Game item not found" } } } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "Internal error": { "value": { "error": "Internal server error" } } } } } } } } }, "/api/market/seller/analytics": { "get": { "summary": "Get seller listing analytics", "description": "Returns analytics data for the authenticated user's market listings and services", "operationId": "getSellerAnalytics", "deprecated": false, "tags": [ "Market" ], "parameters": [ { "name": "period", "in": "query", "description": "Time period for analytics (7d, 30d, 90d)", "schema": { "type": "string", "enum": [ "7d", "30d", "90d" ] } } ], "responses": { "200": { "description": "Analytics retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "market_listings": { "type": "number" }, "services": { "type": "number" }, "total_market_views": { "type": "number" }, "total_service_views": { "type": "number" }, "time_period": { "type": "string" }, "user_id": { "type": "string" } }, "required": [ "market_listings", "services", "total_market_views", "total_service_views", "time_period", "user_id" ] } }, "required": [ "data" ] } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/recruiting/posts": { "get": { "summary": "Get recruiting posts", "deprecated": false, "description": "Retrieve a paginated list of recruiting posts with search and filtering capabilities", "operationId": "getRecruitingPosts", "tags": [ "RecruitingPosts", "Recruiting" ], "parameters": [ { "name": "index", "in": "query", "description": "Page index (0-based)", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 } }, { "name": "sorting", "in": "query", "description": "Sort method", "required": false, "schema": { "type": "string", "enum": [ "rating", "name", "activity", "all-time", "members", "date", "post-date", "rating-reverse", "name-reverse", "activity-reverse", "all-time-reverse", "members-reverse", "date-reverse", "post-date-reverse" ], "default": "name" } }, { "name": "query", "in": "query", "description": "Search query", "required": false, "schema": { "type": "string" } }, { "name": "fields", "in": "query", "description": "Comma-separated list of fields to search", "required": false, "schema": { "type": "string" } }, { "name": "rating", "in": "query", "description": "Minimum rating filter", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 } }, { "name": "pageSize", "in": "query", "description": "Number of items per page", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 15 } } ], "responses": { "200": { "description": "OK - Successfully retrieved recruiting posts", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "total": { "type": "integer", "minimum": 0, "description": "Total number of posts matching the query" }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/RecruitingPost" }, "description": "Array of recruiting posts" } }, "required": [ "total", "items" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } }, "post": { "summary": "Create a recruiting post", "deprecated": false, "description": "Create a new recruiting post for a contractor", "operationId": "createRecruitingPost", "tags": [ "RecruitingPosts", "Recruiting" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateRecruitingPostRequest" } } } }, "responses": { "201": { "description": "Created - Recruiting post successfully created", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/RecruitingPost" } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/recruiting/posts/{post_id}": { "get": { "summary": "Get recruiting post by ID", "deprecated": false, "description": "Retrieve a specific recruiting post by its ID", "operationId": "getRecruitingPostById", "tags": [ "RecruitingPosts", "Recruiting" ], "parameters": [ { "name": "post_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The ID of the recruiting post" } ], "responses": { "200": { "description": "OK - Successfully retrieved recruiting post", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/RecruitingPost" } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/recruiting/posts/{post_id}/comments": { "get": { "summary": "Get recruiting post comments", "deprecated": false, "description": "Retrieve all comments for a specific recruiting post", "operationId": "getRecruitingPostComments", "tags": [ "RecruitingPosts", "RecruitingPostComments", "Recruiting" ], "parameters": [ { "name": "post_id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "The ID of the recruiting post" } ], "responses": { "200": { "description": "OK - Successfully retrieved comments", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/RecruitingComment" } } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/recruiting/contractors/{spectrum_id}/posts": { "get": { "summary": "Get recruiting post by contractor", "deprecated": false, "description": "Retrieve the recruiting post for a specific contractor", "operationId": "getRecruitingPostByContractor", "tags": [ "RecruitingPosts", "Recruiting" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "The Spectrum ID of the contractor" } ], "responses": { "200": { "description": "OK - Successfully retrieved recruiting post", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/RecruitingPost" } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/comments/{comment_id}/reply": { "post": { "summary": "Reply to a comment", "description": "Create a reply to an existing comment", "operationId": "replyToComment", "tags": [ "Comments" ], "parameters": [ { "name": "comment_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Comment ID to reply to" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentReplyRequest" } } } }, "responses": { "200": { "description": "Reply created successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Comment" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/comments/{comment_id}/delete": { "post": { "summary": "Delete a comment", "description": "Delete a comment (author or admin only)", "operationId": "deleteComment", "tags": [ "Comments" ], "parameters": [ { "name": "comment_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Comment ID to delete" } ], "responses": { "200": { "description": "Comment deleted successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Success" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/comments/{comment_id}/update": { "post": { "summary": "Update a comment", "description": "Update a comment's content (author or admin only)", "operationId": "updateComment", "tags": [ "Comments" ], "parameters": [ { "name": "comment_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Comment ID to update" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentUpdateRequest" } } } }, "responses": { "200": { "description": "Comment updated successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Success" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/comments/{comment_id}/upvote": { "post": { "summary": "Upvote a comment", "description": "Upvote a comment (toggles if already upvoted)", "operationId": "upvoteComment", "tags": [ "Comments" ], "parameters": [ { "name": "comment_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Comment ID to upvote" } ], "responses": { "200": { "description": "Comment upvoted successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Success" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/comments/{comment_id}/downvote": { "post": { "summary": "Downvote a comment", "description": "Downvote a comment (toggles if already downvoted)", "operationId": "downvoteComment", "tags": [ "Comments" ], "parameters": [ { "name": "comment_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Comment ID to downvote" } ], "responses": { "200": { "description": "Comment downvoted successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Success" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/chats/orders/{order_id}": { "get": { "summary": "Get a chat by order ID", "deprecated": false, "description": "Retrieve chat details for a specific order. Rate limited: Anonymous users (10 req/min), Authenticated users (30 req/min), Admin users (100 req/min).", "operationId": "getChatByOrderId", "tags": [ "Chats" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Related order for chat", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Chat" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/chats/offers/{session_id}": { "get": { "summary": "Get a chat by offer session ID", "deprecated": false, "description": "", "operationId": "getChatByOfferSessionId", "tags": [ "Chats" ], "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Related offer session for chat", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Chat" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/chats/{chat_id}/messages": { "post": { "summary": "Send a message", "deprecated": false, "description": "", "operationId": "sendMessage", "tags": [ "Chats" ], "parameters": [ { "name": "chat_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of chat", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "MessageCreated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/chats": { "post": { "summary": "Creates a chat", "deprecated": false, "description": "", "operationId": "createChat", "tags": [ "Chats" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChatBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "ChatCreated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for common write operations. Anonymous users: 15 req/min, Authenticated users: 40 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] }, "get": { "summary": "Get my chats", "deprecated": false, "description": "", "operationId": "getChats", "tags": [ "Chats" ], "parameters": [], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Chat" } } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/chats/{chat_id}": { "get": { "summary": "Get a chat by ID", "deprecated": false, "description": "", "operationId": "getChatById", "tags": [ "Chats" ], "parameters": [ { "name": "chat_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of chat", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Chat" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/contractors/auth/link": { "post": { "summary": "Verify a contractor with the site", "deprecated": false, "description": "", "operationId": "authLink", "tags": [ "Contractor", "Contractors" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "title": "contractor", "type": "string", "maxLength": 50, "minLength": 3 } }, "required": [ "contractor" ] } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "OrgRegistered" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for critical operations. Anonymous users: 1 req/min, Authenticated users: 2 req/min, Admin users: 5 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/contractors/": { "post": { "summary": "Create a new contractor", "deprecated": false, "description": "", "operationId": "createContractor", "tags": [ "Contractor", "Contractors" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContractorBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "CreateANewOrderCreated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for critical operations. Anonymous users: 1 req/min, Authenticated users: 2 req/min, Admin users: 5 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/contractors/search/{query}": { "get": { "summary": "Search contractors", "deprecated": false, "description": "", "operationId": "searchContractors", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "query", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/MinimalContractor" } } }, "required": [ "data" ], "type": "object", "title": "SearchContractorsOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/contractors/invites/{invite_id}": { "get": { "summary": "Fetch details about a contractor invite", "deprecated": false, "description": "", "operationId": "getInviteCode", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "invite_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "spectrum_id": { "nullable": false, "type": "string", "minLength": 3 } } } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/invites/{invite_id}/accept": { "post": { "summary": "Accept a contractor invite code", "deprecated": false, "description": "", "operationId": "acceptCodeInvite", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "invite_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/members/search/{query}": { "get": { "summary": "Search contractor members", "deprecated": false, "description": "", "operationId": "searchContractorMembers", "tags": [ "Contractor", "Contractors", "Contractor Members" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "", "example": "" }, { "name": "query", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/MinimalUser" } } }, "required": [ "data" ], "type": "object", "title": "SearchContractorMembersOk" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } } }, "/api/contractors/{spectrum_id}/members/csv": { "get": { "summary": "Export contractor members as CSV", "deprecated": false, "description": "Download contractor members list as CSV", "operationId": "getContractorMembersCsv", "tags": [ "Contractor", "Contractors", "Contractor Members" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/csv": {} }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/customers": { "get": { "summary": "Get Contractor Customers", "deprecated": false, "description": "", "operationId": "getContractorCustomers", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/MinimalUser" } } }, "required": [ "data" ], "type": "object", "title": "SearchContractorMembersOk" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } } }, "/api/contractors/{spectrum_id}/reviews": { "get": { "summary": "Get contractor reviews", "deprecated": false, "description": "", "operationId": "getContractorReviews", "tags": [ "Order Reviews" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "type": "object", "properties": { "content": { "title": "content", "type": "string", "maxLength": 1000 }, "rating": { "title": "rating", "type": "number", "minimum": 0, "multipleOf": 0.5 }, "role": { "title": "role", "type": "string", "enum": [ "contractor", "customer" ] }, "contractor_author": { "title": "contractor_author", "$ref": "#/components/schemas/MinimalContractor", "nullable": true }, "user_author": { "title": "user_author", "$ref": "#/components/schemas/MinimalUser", "nullable": true } }, "required": [ "content", "rating", "role" ] } } }, "required": [ "data" ], "type": "object", "title": "SearchContractorMembersOk" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } } }, "/api/contractors/{spectrum_id}/audit-logs": { "get": { "summary": "Get contractor audit logs", "deprecated": false, "description": "Retrieve a paginated list of audit log entries for this contractor. Only accessible by contractor members. Automatically filtered to show only logs for this contractor.", "operationId": "getContractorAuditLogs", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "Contractor spectrum ID" }, { "name": "page", "in": "query", "description": "Page number (1-based)", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 } }, { "name": "page_size", "in": "query", "description": "Number of audit log entries per page", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }, { "name": "action", "in": "query", "description": "Filter by action type (e.g., 'org.archived')", "required": false, "schema": { "type": "string" } }, { "name": "actor_id", "in": "query", "description": "Filter by actor user ID", "required": false, "schema": { "type": "string", "format": "uuid" } }, { "name": "start_date", "in": "query", "description": "Filter logs after this date (ISO 8601 format)", "required": false, "schema": { "type": "string", "format": "date-time" } }, { "name": "end_date", "in": "query", "description": "Filter logs before this date (ISO 8601 format)", "required": false, "schema": { "type": "string", "format": "date-time" } } ], "responses": { "200": { "description": "Audit logs retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AuditLogsResponse" } }, "required": [ "data" ] } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}": { "get": { "summary": "Get a contractor", "deprecated": false, "description": "", "operationId": "getContractor", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "$ref": "#/components/schemas/Contractor" } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } }, "delete": { "summary": "Archive a contractor", "deprecated": false, "description": "Archive the specified contractor. This action removes members, revokes invites, cancels open orders, and hides the contractor from discovery while preserving historical data.", "operationId": "archiveContractor", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "Contractor spectrum ID" } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": false, "properties": { "reason": { "type": "string", "maxLength": 500, "description": "Optional reason describing why the contractor was archived." } } } } } }, "responses": { "204": { "description": "Contractor archived successfully", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for critical operations. Anonymous users: 1 req/min, Authenticated users: 2 req/min, Admin users: 5 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] }, "put": { "summary": "Update a contractor", "deprecated": false, "description": "Update contractor details. Note: avatar_url and banner_url are no longer supported. Use /avatar and /banner upload endpoints instead.", "operationId": "updateContractor", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "$ref": "#/components/schemas/ContractorUpdateBody" } } } }, "responses": { "201": { "description": "Updated - Resource successfully updated", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/members/{username}": { "get": { "summary": "Check if user is member of contractor", "deprecated": false, "description": "Check if a specific user is a member of the contractor", "operationId": "checkContractorMembership", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "Contractor spectrum ID" }, { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Username to check" } ], "responses": { "200": { "description": "OK - Membership status retrieved", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "is_member": { "type": "boolean" }, "user_id": { "type": "string" }, "username": { "type": "string" }, "roles": { "type": "array", "items": { "type": "string" } } }, "required": [ "is_member", "user_id", "username", "roles" ] } }, "required": [ "data" ] } } } }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [] }, "delete": { "summary": "Kick a contractor member", "deprecated": false, "description": "", "operationId": "kickContractorMember", "tags": [ "Contractor", "Contractors", "Contractor Members" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "204": { "description": "Deleted - Resource successfully deleted", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/members": { "get": { "summary": "Get contractor members (paginated)", "deprecated": false, "description": "Get a paginated list of contractor members with search and filtering capabilities", "operationId": "getContractorMembers", "tags": [ "Contractor", "Contractors", "Contractor Members" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "Contractor spectrum ID" }, { "name": "page", "in": "query", "description": "Page number (0-based)", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 } }, { "name": "page_size", "in": "query", "description": "Number of items per page", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }, { "name": "search", "in": "query", "description": "Search by username", "required": false, "schema": { "type": "string" } }, { "name": "sort", "in": "query", "description": "Sort field", "required": false, "schema": { "type": "string", "enum": [ "username", "role" ], "default": "username" } }, { "name": "role_filter", "in": "query", "description": "Filter by role ID", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK - Successful request with paginated members", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "total": { "type": "integer" }, "page": { "type": "integer" }, "page_size": { "type": "integer" }, "members": { "type": "array", "items": { "type": "object", "properties": { "user_id": { "type": "string" }, "username": { "type": "string" }, "roles": { "type": "array", "items": { "type": "string" } }, "avatar": { "type": "string" } }, "required": [ "user_id", "username", "roles", "avatar" ] } } }, "required": [ "total", "page", "page_size", "members" ] } }, "required": [ "data" ] } } } }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [] }, "post": { "summary": "Invite members to contractor", "deprecated": false, "description": "", "operationId": "contractorInviteMembers", "tags": [ "Contractor", "Contractors", "Contractor Members" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "maxLength": 1000 }, "usernames": { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 50 } } } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "$ref": "#/components/schemas/ContractorInviteCode" } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/roles": { "post": { "summary": "Create a contractor role", "deprecated": false, "description": "", "operationId": "createContractorRole", "tags": [ "Contractor", "Contractors", "Contractor Roles" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContractorRoleBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/roles/{role_id}": { "put": { "summary": "Update a contractor role", "deprecated": false, "description": "", "operationId": "updateContractorRole", "tags": [ "Contractor", "Contractors", "Contractor Roles" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "role_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContractorRoleUpdateBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] }, "delete": { "summary": "Delete a contractor role", "deprecated": false, "description": "", "operationId": "deleteContractorRole", "tags": [ "Contractor", "Contractors", "Contractor Roles" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "role_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "204": { "description": "Deleted - Resource successfully deleted", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/roles/{role_id}/members/{username}": { "post": { "summary": "Give a user a contractor role", "deprecated": false, "description": "", "operationId": "giveContractorRole", "tags": [ "Contractor", "Contractors", "Contractor Roles" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "role_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] }, "delete": { "summary": "Remove a contractor role from a user", "deprecated": false, "description": "", "operationId": "removeContractorRole", "tags": [ "Contractor", "Contractors", "Contractor Roles" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "role_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "204": { "description": "Deleted - Resource successfully deleted", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/transfer-ownership": { "post": { "summary": "Transfer organization ownership", "deprecated": false, "description": "Transfer ownership of an organization to another member. Only the current owner can perform this action.", "operationId": "transferOwnership", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "Contractor spectrum ID" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "username": { "type": "string", "description": "Username of the member to transfer ownership to", "example": "newowner" } }, "required": [ "username" ] } } } }, "responses": { "200": { "description": "OK - Ownership successfully transferred", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "result": { "type": "string", "example": "Success" }, "message": { "type": "string", "example": "Ownership transferred to newowner" } }, "required": [ "result", "message" ] } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/avatar": { "post": { "summary": "Upload organization avatar", "deprecated": false, "description": "Upload a new avatar image for the organization. The image must be in PNG, JPG, or WEBP format and less than 1MB. The image will be processed through content moderation. User must have manage_org_details permission. Send multipart/form-data with 'avatar' field containing the image file.", "operationId": "uploadOrganizationAvatar", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Organization spectrum ID" } ], "responses": { "200": { "description": "Avatar uploaded successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "result": { "type": "string", "example": "Avatar uploaded successfully" }, "resource_id": { "type": "string" }, "url": { "type": "string", "format": "uri" } }, "required": [ "result", "resource_id", "url" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/contractors/{spectrum_id}/banner": { "post": { "summary": "Upload organization banner", "deprecated": false, "description": "Upload a new banner image for the organization. The image must be in PNG, JPG, or WEBP format and less than 2.5MB. The image will be processed through content moderation. User must have manage_org_details permission. Send multipart/form-data with 'banner' field containing the image file.", "operationId": "uploadOrganizationBanner", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Organization spectrum ID" } ], "responses": { "200": { "description": "Banner uploaded successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "result": { "type": "string", "example": "Banner uploaded successfully" }, "resource_id": { "type": "string" }, "url": { "type": "string", "format": "uri" } }, "required": [ "result", "resource_id", "url" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/contractors/{spectrum_id}/webhooks": { "post": { "summary": "Create a webhook for a contractor", "deprecated": false, "description": "", "operationId": "createContractorWebhook", "tags": [ "OrderWebhook", "Contractor Webhooks" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "$ref": "#/components/schemas/OrderWebhook" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] }, "get": { "summary": "Get contractor webhooks", "deprecated": false, "description": "", "operationId": "getContractorWebhooks", "tags": [ "OrderWebhook", "Contractor Webhooks" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/OrderWebhook" } } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/webhooks/{webhook_id}": { "delete": { "summary": "Delete a contractor webhook", "deprecated": false, "description": "Remove a webhook from the contractor", "operationId": "deleteContractorWebhook", "tags": [ "OrderWebhook", "Contractor Webhooks" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "webhook_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "204": { "description": "Deleted - Resource successfully deleted", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/invites": { "post": { "summary": "Create contractor invite", "deprecated": false, "description": "", "operationId": "createContractorInvite", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "max_uses": { "title": "max_uses", "type": "integer", "minimum": 0 } }, "required": [] } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "$ref": "#/components/schemas/ContractorInviteCode" } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] }, "get": { "summary": "Get contractor invites", "deprecated": false, "description": "", "operationId": "getContractorInvites", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ContractorInviteCode" } } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/invites/{invite_id}": { "delete": { "summary": "Get a contractor invite by ID", "deprecated": false, "description": "", "operationId": "getContractorInviteByID", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "invite_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ContractorInviteCode" } } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/accept": { "post": { "summary": "Accept a contractor invite", "deprecated": false, "description": "", "operationId": "acceptContractorInvite", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/decline": { "post": { "summary": "Decline a contractor invite", "deprecated": false, "description": "", "operationId": "declineContractorInvite", "tags": [ "ContractorInvite", "Contractor Invites" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors": { "get": { "summary": "Get paginated contractors list", "description": "Get a paginated list of contractors with search, filtering, and sorting capabilities", "operationId": "getContractors", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "index", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 }, "description": "Page index for pagination" }, { "name": "pageSize", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }, "description": "Number of items per page" }, { "name": "sorting", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "name", "name-reverse", "rating", "rating-reverse", "created_at", "created_at-reverse", "members", "members-reverse", "member_count", "date", "date-reverse" ], "default": "name" }, "description": "Field to sort by" }, { "name": "reverseSort", "in": "query", "required": false, "schema": { "type": "boolean", "default": false }, "description": "Reverse the sort order" }, { "name": "query", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Search query to filter contractors by name or description" }, { "name": "fields", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated list of fields to filter by" }, { "name": "rating", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by minimum rating" } ], "responses": { "200": { "description": "Contractors list retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "total": { "type": "integer", "description": "Total number of contractors matching the criteria" }, "items": { "type": "array", "items": { "type": "object", "properties": { "contractor_id": { "type": "string" }, "spectrum_id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "avatar": { "type": "string", "nullable": true }, "banner": { "type": "string", "nullable": true }, "site_url": { "type": "string", "nullable": true }, "locale": { "type": "string", "nullable": true }, "market_order_template": { "type": "string", "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "fields": { "type": "array", "items": { "type": "string" }, "description": "Contractor specialization fields" }, "rating": { "type": "number", "nullable": true, "description": "Average contractor rating" }, "roles": { "type": "array", "items": { "type": "object", "properties": { "role_id": { "type": "string" }, "name": { "type": "string" }, "position": { "type": "number" }, "permissions": { "type": "object" } } }, "description": "Available contractor roles" } }, "required": [ "contractor_id", "spectrum_id", "name", "created_at", "updated_at", "fields", "roles" ] } } }, "required": [ "total", "items" ] } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/contractors/{spectrum_id}/settings/discord": { "get": { "summary": "Get Discord settings for contractor", "description": "Get Discord server and channel settings for a contractor", "operationId": "getContractorDiscordSettings", "tags": [ "Contractor", "Contractors", "Discord" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Contractor spectrum ID" } ], "responses": { "200": { "description": "Discord settings retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "guild_avatar": { "type": "string", "nullable": true, "description": "Discord server avatar URL" }, "guild_name": { "type": "string", "nullable": true, "description": "Discord server name" }, "channel_name": { "type": "string", "nullable": true, "description": "Discord channel name" }, "official_server_id": { "type": "string", "nullable": true, "description": "Official Discord server ID" }, "discord_thread_channel_id": { "type": "string", "nullable": true, "description": "Discord thread channel ID" } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [ { "bearerAuth": [] } ] } }, "/api/contractors/{spectrum_id}/settings/discord/use_official": { "post": { "summary": "Use the official server for Discord webhooks", "deprecated": false, "description": "", "operationId": "useOfficialDiscordContractor", "tags": [ "OrderWebhook", "Contractor Webhooks", "Discord" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/leave": { "post": { "summary": "Leave a contractor you are a member of", "deprecated": false, "description": "", "operationId": "leaveContractor", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} } }, "security": [] } }, "/api/contractors/{spectrum_id}/blocklist": { "get": { "summary": "Get organization's blocklist", "description": "Retrieve the list of users blocked by the organization", "operationId": "getOrgBlocklist", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Organization spectrum ID" } ], "responses": { "200": { "description": "OK - Blocklist retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "blocked_id": { "type": "string", "format": "uuid" }, "created_at": { "type": "string", "format": "date-time" }, "reason": { "type": "string" }, "blocked_user": { "type": "object", "properties": { "username": { "type": "string" }, "display_name": { "type": "string" }, "avatar": { "type": "string" } } } } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/contractors/{spectrum_id}/blocklist/block": { "post": { "summary": "Block a user for organization", "description": "Add a user to the organization's blocklist", "operationId": "blockUserForOrg", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Organization spectrum ID" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "username": { "type": "string", "description": "Username of the user to block" }, "reason": { "type": "string", "description": "Optional reason for blocking" } }, "required": [ "username" ] } } } }, "responses": { "200": { "description": "OK - User blocked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "message": { "type": "string" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/contractors/{spectrum_id}/blocklist/unblock/{username}": { "delete": { "summary": "Unblock a user for organization", "description": "Remove a user from the organization's blocklist", "operationId": "unblockUserForOrg", "tags": [ "Contractor", "Contractors" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Organization spectrum ID" }, { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Username of the user to unblock" } ], "responses": { "200": { "description": "OK - User unblocked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "message": { "type": "string" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [ { "userAuth": [] } ] } }, "/api/contracts": { "post": { "summary": "Create a public contract", "deprecated": false, "description": "", "operationId": "createPublicContract", "tags": [ "PublicContracts", "Public Contracts" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublicContractBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": { "contract_id": { "nullable": false, "title": "contract_id", "type": "string" } } } }, "required": [ "data" ], "type": "object", "title": "CreateANewOrderCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} } }, "security": [] }, "get": { "summary": "Get public contracts", "deprecated": false, "description": "", "operationId": "getPublicContracts", "tags": [ "PublicContracts", "Public Contracts" ], "parameters": [], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/PublicContract" }, "type": "array", "title": "Public Contracts" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } } }, "/api/contracts/{contract_id}/offers": { "post": { "summary": "Create an offer on a public contract", "deprecated": false, "description": "", "operationId": "createContractOffer", "tags": [ "PublicContracts", "Public Contracts", "Offers" ], "parameters": [ { "name": "contract_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublicContractOfferBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": { "session_id": { "nullable": false, "title": "session_id", "type": "string" } } } }, "required": [ "data" ], "type": "object", "title": "CreateANewOrderCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} } }, "security": [] } }, "/api/contracts/{contract_id}": { "get": { "summary": "Get a public contract", "deprecated": false, "description": "", "operationId": "getPublicContract", "tags": [ "PublicContracts", "Public Contracts" ], "parameters": [ { "name": "contract_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublicContract" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } } }, "/api/orders/": { "post": { "summary": "Create a new order", "deprecated": false, "description": "Create a new order with the specified details.", "operationId": "createANewOrder", "tags": [ "Orders", "Offers" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OrderBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": { "discord_invite": { "nullable": true, "title": "discord_invite", "type": "string" }, "session_id": { "nullable": false, "title": "session_id", "type": "string" } } } }, "required": [ "data" ], "type": "object", "title": "CreateANewOrderCreated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/orders/search": { "get": { "summary": "Search orders", "deprecated": false, "description": "Search orders with various filters.", "operationId": "searchOrders", "tags": [ "Orders" ], "parameters": [ { "name": "contractor", "in": "query", "description": "The Spectrum ID of the contracting org", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "assigned", "in": "query", "description": "The assigned user's username", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "customer", "in": "query", "description": "The customer's username", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "sort_method", "in": "query", "description": "The method to sort results by", "required": false, "schema": { "type": "string", "enum": [ "title", "customer_name", "status", "timestamp", "contractor_name" ], "default": "timestamp" } }, { "name": "status", "in": "query", "description": "The current status of the order", "required": false, "schema": { "type": "string", "enum": [ "fulfilled", "in-progress", "not-started", "cancelled", "active", "past" ] } }, { "name": "index", "in": "query", "description": "The page index of the search", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 } }, { "name": "page_size", "in": "query", "description": "The page size for the search", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 25, "default": 5 } }, { "name": "reverse_sort", "in": "query", "description": "Whether to reverse the sort", "required": false, "schema": { "type": "boolean", "default": false } }, { "name": "buyer_username", "in": "query", "description": "Filter by buyer (customer) username (for seller view)", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "seller_username", "in": "query", "description": "Filter by seller username (contractor spectrum_id or assigned user username) (for buyer view)", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "has_market_listings", "in": "query", "description": "Filter orders that have market listings attached", "required": false, "schema": { "type": "boolean" } }, { "name": "has_service", "in": "query", "description": "Filter orders that have a service attached", "required": false, "schema": { "type": "boolean" } }, { "name": "cost_min", "in": "query", "description": "Minimum cost filter", "required": false, "schema": { "type": "integer", "minimum": 0 } }, { "name": "cost_max", "in": "query", "description": "Maximum cost filter", "required": false, "schema": { "type": "integer", "minimum": 0 } }, { "name": "date_from", "in": "query", "description": "Filter orders created after this date (ISO 8601 format)", "required": false, "schema": { "type": "string", "format": "date-time" } }, { "name": "date_to", "in": "query", "description": "Filter orders created before this date (ISO 8601 format)", "required": false, "schema": { "type": "string", "format": "date-time" } } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/OrderStub" } }, "item_count": { "type": "integer", "minimum": 0 } } } }, "required": [ "data" ], "type": "object", "title": "SearchOrdersOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/orders/contractor/{spectrum_id}/metrics": { "get": { "summary": "Get contractor order metrics", "deprecated": false, "description": "Returns aggregated metrics for orders placed with a specific contractor.", "operationId": "getContractorOrderMetrics", "tags": [ "Orders" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string", "minLength": 3, "maxLength": 50 }, "description": "The Spectrum ID of the contractor", "example": "SCMARKET" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "total_orders": { "type": "integer", "description": "Total number of orders" }, "total_value": { "type": "integer", "description": "Total value of all orders" }, "active_value": { "type": "integer", "description": "Total value of active orders (not-started + in-progress)" }, "completed_value": { "type": "integer", "description": "Total value of completed orders (fulfilled)" }, "status_counts": { "type": "object", "properties": { "not-started": { "type": "integer" }, "in-progress": { "type": "integer" }, "fulfilled": { "type": "integer" }, "cancelled": { "type": "integer" } }, "description": "Count of orders by status" }, "recent_activity": { "type": "object", "properties": { "orders_last_7_days": { "type": "integer" }, "orders_last_30_days": { "type": "integer" }, "value_last_7_days": { "type": "integer" }, "value_last_30_days": { "type": "integer" } }, "description": "Recent activity metrics" }, "top_customers": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string" }, "order_count": { "type": "integer" }, "total_value": { "type": "integer" } } }, "description": "Top customers by order count" } }, "required": [ "total_orders", "total_value", "active_value", "completed_value", "status_counts", "recent_activity" ], "title": "ContractorOrderMetrics" } }, "required": [ "data" ], "type": "object", "title": "GetContractorOrderMetricsOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/orders/contractor/{spectrum_id}/data": { "get": { "summary": "Get comprehensive contractor order data", "deprecated": false, "description": "Returns comprehensive order data including metrics, trend data, and recent orders for a specific contractor.", "operationId": "getContractorOrderData", "tags": [ "Orders" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The Spectrum ID of the contractor", "example": "SCMARKET" }, { "name": "include_trends", "in": "query", "description": "Whether to include pre-computed trend data", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "assigned_only", "in": "query", "description": "Whether to only include assigned orders (for user trends)", "required": false, "schema": { "type": "boolean", "default": false } } ], "responses": { "200": { "description": "Comprehensive contractor order data", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "data": { "type": "object", "properties": { "metrics": { "type": "object", "properties": { "total_orders": { "type": "number" }, "total_value": { "type": "number" }, "active_value": { "type": "number" }, "completed_value": { "type": "number" }, "status_counts": { "type": "object", "properties": { "not-started": { "type": "number" }, "in-progress": { "type": "number" }, "fulfilled": { "type": "number" }, "cancelled": { "type": "number" } } }, "recent_activity": { "type": "object", "properties": { "orders_last_7_days": { "type": "number" }, "orders_last_30_days": { "type": "number" }, "value_last_7_days": { "type": "number" }, "value_last_30_days": { "type": "number" } } }, "top_customers": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string" }, "order_count": { "type": "number" }, "total_value": { "type": "number" } } } }, "trend_data": { "type": "object", "properties": { "daily_orders": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "daily_value": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "value": { "type": "number" } } } }, "status_trends": { "type": "object", "properties": { "not-started": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "in-progress": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "fulfilled": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "cancelled": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } } } } } } } }, "recent_orders": { "type": "array", "items": { "type": "object", "properties": { "order_id": { "type": "string" }, "timestamp": { "type": "string" }, "status": { "type": "string" }, "cost": { "type": "number" }, "title": { "type": "string" } } } } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/orders/user/data": { "get": { "summary": "Get comprehensive user order data", "deprecated": false, "description": "Returns comprehensive order data including metrics, trend data, and recent orders for the current user's assigned orders.", "operationId": "getUserOrderData", "tags": [ "Orders" ], "parameters": [ { "name": "include_trends", "in": "query", "description": "Whether to include pre-computed trend data", "required": false, "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Comprehensive user order data", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "data": { "type": "object", "properties": { "metrics": { "type": "object", "properties": { "total_orders": { "type": "number" }, "total_value": { "type": "number" }, "active_value": { "type": "number" }, "completed_value": { "type": "number" }, "status_counts": { "type": "object", "properties": { "not-started": { "type": "number" }, "in-progress": { "type": "number" }, "fulfilled": { "type": "number" }, "cancelled": { "type": "number" } } }, "recent_activity": { "type": "object", "properties": { "orders_last_7_days": { "type": "number" }, "orders_last_30_days": { "type": "number" }, "value_last_7_days": { "type": "number" }, "value_last_30_days": { "type": "number" } } }, "top_customers": { "type": "array", "items": { "type": "object", "properties": { "username": { "type": "string" }, "order_count": { "type": "number" }, "total_value": { "type": "number" } } } }, "trend_data": { "type": "object", "properties": { "daily_orders": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "daily_value": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "value": { "type": "number" } } } }, "status_trends": { "type": "object", "properties": { "not-started": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "in-progress": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "fulfilled": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } }, "cancelled": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "count": { "type": "number" } } } } } } } } } }, "recent_orders": { "type": "array", "items": { "type": "object", "properties": { "order_id": { "type": "string" }, "timestamp": { "type": "string" }, "status": { "type": "string" }, "cost": { "type": "number" }, "title": { "type": "string" } } } } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/orders/{order_id}/review": { "post": { "summary": "Leave a review on an order", "deprecated": false, "description": "Leave a review on a completed order.", "operationId": "postReview", "tags": [ "Order Reviews" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "title": "content", "type": "string", "maxLength": 1000 }, "rating": { "title": "rating", "type": "number", "minimum": 1, "maximum": 5, "multipleOf": 1 }, "role": { "title": "role", "type": "string", "enum": [ "contractor", "customer" ] } }, "required": [ "content", "rating", "role" ] } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "PostReviewCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/orders/{order_id}/reviews/{review_id}/request-revision": { "post": { "summary": "Request revision for a review", "description": "Request a revision for an existing review. Rate limited to prevent spam.", "operationId": "requestReviewRevision", "tags": [ "Order Reviews" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "review_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "maxLength": 500, "description": "Optional message explaining why the revision is requested" } } } } } }, "responses": { "200": { "description": "Revision requested successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "review_id": { "type": "string" }, "revision_requested": { "type": "boolean" }, "revision_requested_at": { "type": "string", "format": "date-time" }, "revision_message": { "type": "string", "nullable": true } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/orders/{order_id}/reviews/{review_id}": { "put": { "summary": "Update a review after revision request", "description": "Update a review after a revision has been requested. Rate limited to prevent spam.", "operationId": "updateOrderReview", "tags": [ "Order Reviews" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "review_id", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "type": "string", "minLength": 10, "maxLength": 2000 }, "rating": { "type": "number", "minimum": 1, "maximum": 5, "multipleOf": 1 } }, "required": [ "content", "rating" ] } } } }, "responses": { "200": { "description": "Review updated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "review_id": { "type": "string" }, "last_modified_at": { "type": "string", "format": "date-time" }, "revision_requested": { "type": "boolean" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } } }, "/api/orders/{order_id}": { "put": { "summary": "Update an order", "deprecated": false, "description": "Update an existing order. Rate limited to prevent abuse.", "operationId": "updateOrder", "tags": [ "Orders" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "title": "status", "$ref": "#/components/schemas/OrderStatus" }, "assigned_to": { "title": "assigned_to", "type": "string", "nullable": true }, "contractor": { "title": "contractor", "type": "string" } }, "required": [] } } } }, "responses": { "200": { "description": "OK - Resource successfully updated", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "UpdateTheStatusForOrderOk" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } } }, "get": { "summary": "Get an order by ID", "deprecated": false, "description": "Retrieve a specific order by its ID. Rate limited to prevent abuse.", "operationId": "getOrderById", "tags": [ "Orders" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Order" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} } }, "security": [] } }, "/api/orders/{order_id}/applicants": { "post": { "summary": "Apply to an open contract", "deprecated": true, "description": "Deprecated - Use public contract offers. Rate limited to prevent spam.", "operationId": "postApply", "tags": [ "Order Applicants" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "maxLength": 1000 } }, "required": [ "message" ] } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "PostApplyCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/orders/{order_id}/applicants/contractors/{spectrum_id}": { "post": { "summary": "Accept a contractor application on an order", "deprecated": true, "description": "Deprecated - Use public contract offers. Rate limited to prevent spam.", "operationId": "acceptContractorApplicationOnOrder", "tags": [ "Order Applicants" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "properties": {}, "type": "object" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object" } }, "required": [ "data" ], "type": "object", "title": "AcceptAnApplicationOnOrderCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/orders/{order_id}/applicants/users/{username}": { "post": { "summary": "Accept a user application on an order", "deprecated": true, "description": "Deprecated - Use public contract offers. Rate limited to prevent spam.", "operationId": "acceptUserApplicationOnOrder", "tags": [ "Order Applicants" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" }, { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "properties": {}, "type": "object" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object" } }, "required": [ "data" ], "type": "object", "title": "AcceptAnApplicationOnOrderCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/orders/{order_id}/thread": { "post": { "summary": "Create a new thread for the order", "deprecated": false, "description": "Creates a new thread if the order doesn't already have one. Rate limited to prevent spam.", "operationId": "createOrderThread", "tags": [ "Order Threads" ], "parameters": [ { "name": "order_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "CreateANewOrderThreadCreated" } } }, "headers": {} }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} } }, "security": [] } }, "/api/offers/{session_id}/thread": { "post": { "summary": "Create a new thread for the offer", "deprecated": false, "description": "Creates a new thread if the offer doesn't already have one.", "operationId": "createOfferThread", "tags": [ "Offers" ], "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The ID of the offer", "example": "" } ], "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": { "data": { "title": "data", "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "CreateANewOrderThreadCreated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/offers/search": { "get": { "summary": "Search offers", "deprecated": false, "description": "Search offers with various filters.", "operationId": "searchOffers", "tags": [ "Offers" ], "parameters": [ { "name": "contractor", "in": "query", "description": "The Spectrum ID of the contracting org", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "assigned", "in": "query", "description": "The assigned user's username", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "customer", "in": "query", "description": "The customer's username", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "sort_method", "in": "query", "description": "The method to sort results by", "required": false, "schema": { "type": "string", "enum": [ "title", "customer_name", "status", "timestamp", "contractor_name" ], "default": "timestamp" } }, { "name": "status", "in": "query", "description": "The current status of the order", "required": false, "schema": { "type": "string", "enum": [ "to-seller", "to-customer", "accepted", "rejected" ] } }, { "name": "index", "in": "query", "description": "The page index of the search", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 } }, { "name": "page_size", "in": "query", "description": "The page size for the search", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 25, "default": 5 } }, { "name": "reverse_sort", "in": "query", "description": "Whether to reverse the sort", "required": false, "schema": { "type": "boolean", "default": false } }, { "name": "buyer_username", "in": "query", "description": "Filter by buyer (customer) username (for seller view)", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "seller_username", "in": "query", "description": "Filter by seller username (contractor spectrum_id or assigned user username) (for buyer view)", "required": false, "schema": { "type": "string", "minLength": 3, "maxLength": 50 } }, { "name": "has_market_listings", "in": "query", "description": "Filter offers that have market listings attached", "required": false, "schema": { "type": "boolean" } }, { "name": "has_service", "in": "query", "description": "Filter offers that have a service attached", "required": false, "schema": { "type": "boolean" } }, { "name": "cost_min", "in": "query", "description": "Minimum cost filter", "required": false, "schema": { "type": "integer", "minimum": 0 } }, { "name": "cost_max", "in": "query", "description": "Maximum cost filter", "required": false, "schema": { "type": "integer", "minimum": 0 } }, { "name": "date_from", "in": "query", "description": "Filter offers created after this date (ISO 8601 format)", "required": false, "schema": { "type": "string", "format": "date-time" } }, { "name": "date_to", "in": "query", "description": "Filter offers created before this date (ISO 8601 format)", "required": false, "schema": { "type": "string", "format": "date-time" } } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/OrderStub" } }, "item_count": { "type": "integer", "minimum": 0 } } } }, "required": [ "data" ], "type": "object", "title": "SearchOrdersOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/offers/merge": { "post": { "summary": "Merge offer sessions", "deprecated": false, "description": "Merge multiple offer sessions from the same customer into a single new merged offer session. All source offer sessions will be closed.", "operationId": "mergeOfferSessions", "tags": [ "Offers" ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "offer_session_ids": { "type": "array", "items": { "type": "string", "format": "uuid" }, "description": "Array of offer session IDs to merge (minimum 2)", "minItems": 2 } }, "required": [ "offer_session_ids" ] } } } }, "responses": { "200": { "description": "OK - Offer sessions successfully merged", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "result": { "type": "string", "example": "Success" }, "merged_offer_session": { "type": "object", "description": "The new merged offer session" }, "source_offer_session_ids": { "type": "array", "items": { "type": "string", "format": "uuid" }, "description": "IDs of the offer sessions that were merged" }, "message": { "type": "string", "example": "Successfully merged 3 offer sessions into new merged offer" } }, "required": [ "result", "merged_offer_session", "source_offer_session_ids", "message" ] } }, "required": [ "data" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "409": { "description": "The request could not be completed due to a conflict with the current state of the resource. Resolve the conflict and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Conflict" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/offer/{session_id}": { "get": { "summary": "Get an offer by ID", "deprecated": false, "description": "Retrieve offer session details by ID.", "operationId": "getOfferById", "tags": [ "Offers" ], "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OfferSessionDetails" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] }, "put": { "summary": "Update an offer", "deprecated": false, "description": "Update offer details or status.", "operationId": "updateAnOffer", "tags": [ "Offers" ], "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "anyOf": [ { "$ref": "#/components/schemas/CounterOfferBody" }, { "title": "OfferStatusBody", "type": "object", "properties": { "status": { "title": "status", "$ref": "#/components/schemas/OfferStatus" } } } ] } } } }, "responses": { "200": { "description": "OK - Resource successfully updated", "content": { "application/json": { "schema": { "properties": { "data": { "type": "object", "properties": {} } }, "required": [ "data" ], "type": "object", "title": "UpdateTheStatusForAnOrderOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/services": { "post": { "summary": "Create a new service", "deprecated": false, "description": "", "operationId": "createService", "tags": [ "Services" ], "parameters": [], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServiceBody" } } } }, "responses": { "201": { "description": "Created - Resource successfully created", "content": { "application/json": { "schema": { "properties": {}, "type": "object", "title": "CreateServiceCreated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/services/user/{username}": { "get": { "summary": "Get services by user", "deprecated": false, "description": "", "operationId": "getServicesByUser", "tags": [ "Services" ], "parameters": [ { "name": "username", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The username of the user", "example": "Khuzdul" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Service" } } }, "required": [ "data" ], "type": "object", "title": "GetServicesByUserOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/services/public": { "get": { "summary": "Get public services with pagination", "deprecated": false, "description": "Get paginated list of active services with optional filtering and sorting", "operationId": "getPublicServices", "tags": [ "Services" ], "parameters": [ { "name": "page", "in": "query", "description": "Page number (0-based)", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0 } }, { "name": "pageSize", "in": "query", "description": "Number of items per page", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }, { "name": "search", "in": "query", "description": "Search term for service name and description", "required": false, "schema": { "type": "string" } }, { "name": "kind", "in": "query", "description": "Filter by service kind", "required": false, "schema": { "type": "string" } }, { "name": "minCost", "in": "query", "description": "Minimum cost filter", "required": false, "schema": { "type": "number", "minimum": 0 } }, { "name": "maxCost", "in": "query", "description": "Maximum cost filter", "required": false, "schema": { "type": "number", "minimum": 0 } }, { "name": "paymentType", "in": "query", "description": "Filter by payment type", "required": false, "schema": { "type": "string", "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ] } }, { "name": "sortBy", "in": "query", "description": "Field to sort by", "required": false, "schema": { "type": "string", "enum": [ "timestamp", "cost", "service_name" ], "default": "timestamp" } }, { "name": "sortOrder", "in": "query", "description": "Sort order", "required": false, "schema": { "type": "string", "enum": [ "asc", "desc" ], "default": "desc" } } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Service" } }, "pagination": { "type": "object", "properties": { "currentPage": { "type": "integer" }, "pageSize": { "type": "integer" }, "totalItems": { "type": "integer" }, "totalPages": { "type": "integer" }, "hasNextPage": { "type": "boolean" }, "hasPreviousPage": { "type": "boolean" } }, "required": [ "currentPage", "pageSize", "totalItems", "totalPages", "hasNextPage", "hasPreviousPage" ] } }, "required": [ "data", "pagination" ], "type": "object", "title": "GetPublicServicesOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/services/contractor/{spectrum_id}": { "get": { "summary": "Get services by contractor", "deprecated": false, "description": "", "operationId": "getServicesByContractor", "tags": [ "Services" ], "parameters": [ { "name": "spectrum_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "The Spectrum ID of the contractor", "example": "SCMARKET" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Service" } } }, "required": [ "data" ], "type": "object", "title": "GetServicesByContractorOk" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } } } }, "/api/services/{service_id}": { "put": { "summary": "Update a service", "deprecated": false, "description": "", "operationId": "updateService", "tags": [ "Services" ], "parameters": [ { "name": "service_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServiceBody" } } } }, "responses": { "204": { "description": "Updated - Resource successfully updated", "content": { "application/json": { "schema": { "properties": {}, "type": "object", "title": "UpdateServiceUpdated" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] }, "get": { "summary": "Get a service by ID", "deprecated": false, "description": "", "operationId": "getServiceById", "tags": [ "Services" ], "parameters": [ { "name": "service_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "", "example": "" } ], "responses": { "200": { "description": "OK - Successful request with response body", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Service" } } }, "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "security": [] } }, "/api/services/{service_id}/photos": { "post": { "summary": "Upload photos for a service", "description": "Upload up to 5 photos for a specific service. Photos are stored in CDN and linked to the service. If the total number of photos would exceed 5, the oldest photos will be automatically removed to maintain the limit.", "operationId": "uploadServicePhotos", "tags": [ "Services" ], "parameters": [ { "name": "service_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the service to upload photos for" } ], "responses": { "200": { "description": "Photos uploaded successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhotoUploadResponse" } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } } } }, "/api/services/{service_id}/view": { "post": { "summary": "Track a view on a service", "description": "Records a view on a service for analytics purposes", "operationId": "trackServiceView", "deprecated": false, "tags": [ "Services" ], "parameters": [ { "name": "service_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the service to track view for" } ], "responses": { "200": { "description": "View tracked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/services/seller/analytics": { "get": { "summary": "Get seller service analytics", "description": "Returns analytics data for the authenticated user's services", "operationId": "getServiceAnalytics", "deprecated": false, "tags": [ "Services" ], "parameters": [ { "name": "period", "in": "query", "description": "Time period for analytics (7d, 30d, 90d)", "schema": { "type": "string", "enum": [ "7d", "30d", "90d" ] } } ], "responses": { "200": { "description": "Analytics retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "services": { "type": "number" }, "total_service_views": { "type": "number" }, "time_period": { "type": "string" }, "user_id": { "type": "string" } }, "required": [ "services", "total_service_views", "time_period", "user_id" ] } }, "required": [ "data" ] } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } }, "500": { "description": "The server encountered an unexpected condition that prevented it from fulfilling the request. Please try again later.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServerError" } } }, "headers": {} } }, "security": [] } }, "/api/tokens/": { "post": { "summary": "Create a new API token", "description": "Create a new API token with specified scopes and contractor access. Users must have manage org permissions for any contractors specified.", "operationId": "createApiToken", "tags": [ "Tokens" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "name", "scopes" ], "properties": { "name": { "type": "string", "description": "Name for the API token", "example": "My API Token" }, "description": { "type": "string", "description": "Optional description for the API token", "example": "Token for automated market operations" }, "scopes": { "type": "array", "items": { "type": "string", "enum": [ "profile:read", "profile:write", "market:read", "market:write", "market:purchase", "market:photos", "orders:read", "orders:write", "orders:reviews", "contractors:read", "contractors:write", "contractors:members", "contractors:webhooks", "contractors:blocklist", "orgs:read", "orgs:write", "orgs:manage", "services:read", "services:write", "services:photos", "offers:read", "offers:write", "chats:read", "chats:write", "notifications:read", "notifications:write", "moderation:read", "moderation:write", "admin:read", "admin:write", "admin:spectrum", "admin:stats", "readonly", "full", "admin" ] }, "description": "Array of scopes for the token. Admin scopes (admin:*, admin) and moderation scopes (moderation:*) are only available to admin users.", "example": [ "market:read", "orders:write" ] }, "expires_at": { "type": "string", "format": "date-time", "description": "Optional expiration date for the token", "example": "2024-12-31T23:59:59Z" }, "contractor_spectrum_ids": { "type": "array", "items": { "type": "string" }, "description": "Optional array of contractor Spectrum IDs that this token can access", "example": [ "ORG-12345", "ORG-67890" ] } } } } } }, "responses": { "201": { "description": "Token created successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "token": { "type": "string", "description": "The actual token value (only shown on creation)", "example": "scm_live_abc123..." }, "data": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "scopes": { "type": "array", "items": { "type": "string" } }, "contractor_spectrum_ids": { "type": "array", "items": { "type": "string" } }, "expires_at": { "type": "string", "nullable": true }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "get": { "summary": "List user's API tokens", "description": "Retrieve all API tokens belonging to the authenticated user", "operationId": "listApiTokens", "tags": [ "Tokens" ], "responses": { "200": { "description": "List of tokens", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "scopes": { "type": "array", "items": { "type": "string" } }, "contractor_spectrum_ids": { "type": "array", "items": { "type": "string" } }, "expires_at": { "type": "string", "nullable": true }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "last_used_at": { "type": "string", "nullable": true } } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "/api/tokens/{tokenId}": { "get": { "summary": "Get specific API token details", "description": "Retrieve details for a specific API token belonging to the authenticated user", "operationId": "getApiToken", "tags": [ "Tokens" ], "parameters": [ { "name": "tokenId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the token to retrieve" } ], "responses": { "200": { "description": "Token details", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "scopes": { "type": "array", "items": { "type": "string" } }, "contractor_spectrum_ids": { "type": "array", "items": { "type": "string" } }, "expires_at": { "type": "string", "nullable": true }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "last_used_at": { "type": "string", "nullable": true } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "put": { "summary": "Update API token", "description": "Update an existing API token's properties including scopes, expiration, and contractor access", "operationId": "updateApiToken", "tags": [ "Tokens" ], "parameters": [ { "name": "tokenId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the token to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "description": "Name for the API token", "example": "My Updated API Token" }, "description": { "type": "string", "description": "Optional description for the API token", "example": "Updated token description" }, "scopes": { "type": "array", "items": { "type": "string", "enum": [ "profile:read", "profile:write", "market:read", "market:write", "market:purchase", "market:photos", "orders:read", "orders:write", "orders:reviews", "contractors:read", "contractors:write", "contractors:members", "contractors:webhooks", "contractors:blocklist", "orgs:read", "orgs:write", "orgs:manage", "services:read", "services:write", "services:photos", "offers:read", "offers:write", "chats:read", "chats:write", "notifications:read", "notifications:write", "moderation:read", "moderation:write", "admin:read", "admin:write", "admin:spectrum", "admin:stats", "readonly", "full", "admin" ] }, "description": "Array of scopes for the token. Admin scopes (admin:*, admin) and moderation scopes (moderation:*) are only available to admin users.", "example": [ "market:read", "orders:write" ] }, "expires_at": { "type": "string", "format": "date-time", "description": "Optional expiration date for the token", "example": "2024-12-31T23:59:59Z" }, "contractor_spectrum_ids": { "type": "array", "items": { "type": "string" }, "description": "Optional array of contractor Spectrum IDs that this token can access. Set to null to remove all contractor access.", "example": [ "ORG-12345", "ORG-67890" ] } } } } } }, "responses": { "200": { "description": "Token updated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "scopes": { "type": "array", "items": { "type": "string" } }, "contractor_spectrum_ids": { "type": "array", "items": { "type": "string" } }, "expires_at": { "type": "string", "nullable": true }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "403": { "description": "The server understood the request, but refuses to authorize it. Ensure the client has appropriate permissions.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Forbidden" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "delete": { "summary": "Revoke API token", "description": "Permanently revoke an API token, making it unusable", "operationId": "revokeApiToken", "tags": [ "Tokens" ], "parameters": [ { "name": "tokenId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the token to revoke" } ], "responses": { "200": { "description": "Token revoked successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "message": { "type": "string", "example": "Token revoked successfully" } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "/api/tokens/{tokenId}/extend": { "post": { "summary": "Extend API token expiration", "description": "Extend the expiration date of an existing API token", "operationId": "extendApiToken", "tags": [ "Tokens" ], "parameters": [ { "name": "tokenId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the token to extend" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "expires_at" ], "properties": { "expires_at": { "type": "string", "format": "date-time", "description": "New expiration date for the token", "example": "2025-12-31T23:59:59Z" } } } } } }, "responses": { "200": { "description": "Token expiration extended successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "message": { "type": "string", "example": "Token expiration extended" } } } } } } } }, "400": { "description": "The server could not understand the request due to invalid syntax. The client should modify the request and try again.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BadRequest" } } }, "headers": {} }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for write operations. Anonymous users: 5 req/min, Authenticated users: 10 req/min, Admin users: 30 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "/api/tokens/{tokenId}/stats": { "get": { "summary": "Get API token usage statistics", "description": "Retrieve usage statistics for a specific API token", "operationId": "getApiTokenStats", "tags": [ "Tokens" ], "parameters": [ { "name": "tokenId", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID of the token to get stats for" } ], "responses": { "200": { "description": "Token statistics", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "created_at": { "type": "string" }, "last_used_at": { "type": "string", "nullable": true }, "expires_at": { "type": "string", "nullable": true } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "404": { "description": "The server cannot find the requested resource. The endpoint may be invalid or the resource may no longer exist.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotFound" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "/api/tokens/scopes": { "get": { "summary": "Get available scopes", "description": "Retrieve list of available scopes for the authenticated user. Scopes are automatically filtered based on user role (admin-only scopes are excluded for non-admin users).", "operationId": "getAvailableScopes", "tags": [ "Tokens" ], "responses": { "200": { "description": "List of available scopes", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "properties": { "scopes": { "type": "array", "items": { "type": "string" }, "description": "Array of scope names available to the current user" } } } } } } } }, "401": { "description": "Authentication is required to access the requested resource. The client must include the appropriate credentials.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Unauthorized" } } }, "headers": {} }, "429": { "description": "Rate limit exceeded for read operations. Anonymous users: 60 req/min, Authenticated users: 60 req/min, Admin users: 100 req/min.", "headers": { "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RateLimitError" } } } } }, "X-RateLimit-Limit": { "description": "Maximum number of requests allowed per time window", "schema": { "type": "integer", "example": 60 } }, "X-RateLimit-Remaining": { "description": "Number of requests remaining in current time window", "schema": { "type": "integer", "example": 45 } }, "X-RateLimit-Reset": { "description": "Unix timestamp when the rate limit resets", "schema": { "type": "integer", "example": 1640995200 } }, "X-RateLimit-Retry-After": { "description": "Seconds to wait before retrying (only present when rate limited)", "schema": { "type": "integer", "example": 30 } } } }, "/variant-types": { "get": { "operationId": "GetAllVariantTypes", "responses": { "200": { "description": "List of variant types with validation rules", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VariantTypesResponse" } } } } }, "description": "Get all variant types\n\nReturns a list of all available variant types with their validation rules.\nVariant types define the attributes that can be used when creating item variants,\nincluding quality_tier, quality_value, crafted_source, and blueprint_tier.\n\nResults are ordered by display_order for consistent UI presentation.", "summary": "List all variant types", "tags": [ "Variant Types V2" ], "security": [], "parameters": [] } }, "/variant-types/{variant_type_id}": { "get": { "operationId": "GetVariantTypeById", "responses": { "200": { "description": "Variant type details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VariantTypeResponse" } } } } }, "description": "Get variant type by ID\n\nReturns detailed information about a specific variant type including\nvalidation rules (min_value, max_value, allowed_values) and display configuration.", "summary": "Get variant type details", "tags": [ "Variant Types V2" ], "security": [], "parameters": [ { "description": "Variant type ID to retrieve", "in": "path", "name": "variant_type_id", "required": true, "schema": { "type": "string" } } ] } }, "/listings/search": { "get": { "operationId": "SearchListings", "responses": { "200": { "description": "Search results with pagination metadata", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchListingsResponse" } } } } }, "description": "Search listings with filters\n\nSearches active listings using full-text search, quality tier filters, price filters,\nand game item filters. Results are paginated and include price/quality ranges.", "summary": "Search market listings", "tags": [ "Listings V2" ], "security": [], "parameters": [ { "description": "Optional full-text search query", "in": "query", "name": "text", "required": false, "schema": { "type": "string" } }, { "description": "Optional game item ID filter", "in": "query", "name": "game_item_id", "required": false, "schema": { "type": "string" } }, { "description": "Optional minimum quality tier (1-5)", "in": "query", "name": "quality_tier_min", "required": false, "schema": { "format": "double", "type": "number" } }, { "description": "Optional maximum quality tier (1-5)", "in": "query", "name": "quality_tier_max", "required": false, "schema": { "format": "double", "type": "number" } }, { "description": "Optional minimum price filter", "in": "query", "name": "price_min", "required": false, "schema": { "format": "double", "type": "number" } }, { "description": "Optional maximum price filter", "in": "query", "name": "price_max", "required": false, "schema": { "format": "double", "type": "number" } }, { "description": "Page number (default: 1)", "in": "query", "name": "page", "required": false, "schema": { "default": 1, "format": "double", "type": "number" } }, { "description": "Results per page (default: 20, max: 100)", "in": "query", "name": "page_size", "required": false, "schema": { "default": 20, "format": "double", "type": "number" } } ] } }, "/listings": { "post": { "operationId": "CreateListing", "responses": { "200": { "description": "Created listing object", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Listing" } } } } }, "description": "Create a new listing with variants\n\nCreates a listing with stock lots and variant pricing in a single atomic transaction.\nSupports both unified pricing (one price for all variants) and per-variant pricing.", "summary": "Create listing", "tags": [ "Listings V2" ], "security": [], "parameters": [], "requestBody": { "description": "Listing creation request with title, description, game item, pricing mode, and lots", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateListingRequest", "description": "Listing creation request with title, description, game item, pricing mode, and lots" } } } } } }, "/listings/{listing_id}": { "get": { "operationId": "GetListingDetail", "responses": { "200": { "description": "Listing detail with variant breakdown", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListingDetailResponse" } } } } }, "description": "Get listing detail with variant breakdown\n\nReturns comprehensive listing information including seller details, game item info,\nand a breakdown of all variants with their attributes, quantities, and prices.", "summary": "Get listing details", "tags": [ "Listings V2" ], "security": [], "parameters": [ { "description": "Listing ID to retrieve", "in": "path", "name": "listing_id", "required": true, "schema": { "type": "string" } } ] } }, "/health": { "get": { "operationId": "GetHealth", "responses": { "200": { "description": "Ok", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } }, "description": "Health check endpoint", "summary": "Check API health status", "tags": [ "Health" ], "security": [], "parameters": [] } } }, "components": { "schemas": { "AvailabilityEntry": { "type": "object", "properties": { "start": { "type": "integer", "minimum": 0 }, "finish": { "type": "integer", "minimum": 0 } }, "required": [ "start", "finish" ] }, "OrderAvailability": { "type": "object", "properties": { "customer": { "type": "array", "items": { "$ref": "#/components/schemas/AvailabilityEntry" } }, "assigned": { "type": "array", "items": { "$ref": "#/components/schemas/AvailabilityEntry" } } }, "required": [ "customer", "assigned" ] }, "OrderUserApplicant": { "type": "object", "properties": { "user": { "type": "string" } }, "required": [ "user" ] }, "OrderContractorApplicant": { "type": "object", "properties": { "contractor": { "type": "string" } }, "required": [ "contractor" ] }, "OrderReview": { "properties": { "user_author": { "$ref": "#/components/schemas/MinimalUser", "title": "OrderReview.user_author" }, "contractor_author": { "$ref": "#/components/schemas/MinimalContractor", "title": "OrderReview.contractor_author" }, "content": { "title": "OrderReview.content", "type": "string" }, "timestamp": { "title": "OrderReview.timestamp", "type": "number" }, "review_id": { "title": "OrderReview.review_id", "type": "string" }, "order_id": { "title": "OrderReview.order_id", "type": "string" }, "rating": { "title": "OrderReview.rating", "type": "number" } }, "required": [ "user_author", "contractor_author", "content", "timestamp", "review_id", "order_id", "rating" ], "additionalProperties": false, "title": "OrderReview", "type": "object" }, "Rating": { "properties": { "avg_rating": { "title": "Rating.avg_rating", "type": "number" }, "rating_count": { "title": "Rating.rating_count", "type": "integer", "minimum": 0 }, "streak": { "title": "Rating.streak", "type": "integer", "minimum": 0 }, "total_orders": { "title": "Rating.total_orders", "type": "integer", "minimum": 0 } }, "required": [ "avg_rating", "rating_count", "streak", "total_orders" ], "additionalProperties": false, "title": "Rating", "type": "object" }, "MinimalUser": { "properties": { "username": { "title": "MinimalUser.username", "type": "string", "minLength": 3, "maxLength": 30 }, "display_name": { "title": "MinimalUser.display_name", "type": "string", "minLength": 3, "maxLength": 50 }, "avatar": { "title": "MinimalUser.avatar", "type": "string" }, "rating": { "$ref": "#/components/schemas/Rating", "title": "Contractor.rating" }, "discord_profile": { "properties": { "id": { "title": "MinimalUser.discord_profile.id", "type": "string" }, "discriminator": { "title": "MinimalUser.discord_profile.discriminator", "type": "string" }, "username": { "title": "MinimalUser.discord_profile.username", "type": "string" } }, "required": [ "id", "discriminator", "username" ], "additionalProperties": false, "title": "MinimalUser.discord_profile", "type": "object", "nullable": true } }, "required": [ "username", "display_name", "avatar", "rating" ], "additionalProperties": false, "title": "MinimalUser", "type": "object" }, "MinimalContractor": { "properties": { "avatar": { "title": "MinimalContractor.avatar", "type": "string" }, "name": { "title": "MinimalContractor.name", "type": "string", "minLength": 3, "maxLength": 50 }, "spectrum_id": { "title": "MinimalContractor.spectrum_id", "type": "string", "minLength": 3 }, "rating": { "$ref": "#/components/schemas/Rating", "title": "Contractor.rating" } }, "required": [ "avatar", "name", "spectrum_id", "rating" ], "additionalProperties": false, "title": "MinimalContractor", "type": "object" }, "ServiceStatus": { "enum": [ "active", "inactive" ], "title": "ServiceStatus", "type": "string" }, "Service": { "properties": { "service_id": { "title": "Service.service_id", "type": "string" }, "service_name": { "title": "Service.service_name", "type": "string" }, "service_description": { "title": "Service.service_description", "type": "string" }, "title": { "type": "string", "title": "Service.title" }, "rush": { "title": "Service.rush", "type": "boolean" }, "description": { "title": "Order.description", "type": "string" }, "kind": { "type": "string", "title": "Service.kind" }, "collateral": { "title": "Service.collateral", "type": "number", "minimum": 0 }, "offer": { "title": "Service.offer", "type": "number", "minimum": 0 }, "payment_type": { "enum": [ "one-time", "daily", "hourly" ], "title": "Order.payment_type", "type": "string" }, "departure": { "title": "OrderBody.departure", "type": "string", "nullable": true, "maxLength": 30 }, "destination": { "title": "OrderBody.destination", "type": "string", "nullable": true, "maxLength": 30 }, "cost": { "title": "Service.cost", "type": "number", "minimum": 0 }, "user": { "title": "Service.user", "type": "string", "nullable": true }, "contractor": { "title": "Service.contractor", "type": "string", "nullable": true }, "status": { "$ref": "#/components/schemas/ServiceStatus", "title": "Service.status" }, "timestamp": { "title": "Order.timestamp", "type": "string" }, "photos": { "type": "array", "items": { "type": "string", "format": "url" } } }, "required": [ "order_id", "status", "kind", "cost", "rush", "assigned_to", "contractor", "customer", "title", "description", "timestamp", "comments", "applicants", "payment_type", "offer_session_id" ], "additionalProperties": false, "title": "Order", "type": "object" }, "BadRequest": { "properties": { "errors": { "items": { "properties": { "message": { "type": "string" } }, "required": [ "message" ], "type": "object" }, "type": "array" }, "message": { "type": "string" } }, "required": [ "message" ], "type": "object" }, "Conflict": { "properties": { "message": { "default": "Conflict", "enum": [ "Conflict" ], "type": "string" } }, "required": [ "message" ], "type": "object" }, "Forbidden": { "properties": { "message": { "default": "Forbidden", "enum": [ "Forbidden" ], "type": "string" } }, "required": [ "message" ], "type": "object" }, "NotFound": { "properties": { "message": { "default": "Not Found", "enum": [ "Not Found" ], "type": "string" } }, "required": [ "message" ], "type": "object" }, "Unauthorized": { "properties": { "message": { "default": "Unauthorized", "enum": [ "Unauthorized" ], "type": "string" } }, "required": [ "message" ], "type": "object" }, "ServerError": { "properties": { "message": { "default": "Internal Server Error", "enum": [ "Internal Server Error" ], "type": "string" } }, "required": [ "message" ], "type": "object" }, "PhotoUploadResponse": { "type": "object", "title": "PhotoUploadResponse", "properties": { "result": { "type": "string", "description": "Success message", "example": "Photos uploaded successfully" }, "photos": { "type": "array", "items": { "type": "object", "properties": { "resource_id": { "type": "string", "description": "Unique identifier for the uploaded photo" }, "url": { "type": "string", "format": "uri", "description": "CDN URL for the uploaded photo" } }, "required": [ "resource_id", "url" ] } } }, "required": [ "result", "photos" ] }, "PhotoUploadError": { "type": "object", "title": "PhotoUploadError", "properties": { "error": { "type": "string", "description": "Error message describing what went wrong" } }, "required": [ "error" ] }, "RateLimitError": { "type": "object", "title": "RateLimitError", "properties": { "error": { "type": "string", "enum": [ "RATE_LIMIT_EXCEEDED" ], "description": "Error type identifier", "example": "RATE_LIMIT_EXCEEDED" }, "message": { "type": "string", "description": "Human-readable error message", "example": "Rate limit exceeded. Too many requests in the specified time window." }, "retryAfter": { "type": "integer", "description": "Seconds to wait before retrying", "example": 30 }, "limit": { "type": "integer", "description": "Maximum requests allowed per time window", "example": 60 }, "remaining": { "type": "integer", "description": "Requests remaining in current window", "example": 0 }, "resetTime": { "type": "integer", "description": "Unix timestamp when rate limit resets", "example": 1640995200 }, "userTier": { "type": "string", "enum": [ "anonymous", "authenticated", "admin" ], "description": "User tier that triggered the rate limit", "example": "authenticated" }, "endpoint": { "type": "string", "description": "Endpoint that was rate limited", "example": "/api/orders" } }, "required": [ "error", "message", "retryAfter", "limit", "remaining", "resetTime", "userTier", "endpoint" ] }, "StarmapRoute": { "type": "object", "properties": { "distance": { "type": "number", "description": "Route distance" }, "duration": { "type": "number", "description": "Travel time in seconds" }, "waypoints": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "coordinates": { "type": "object", "properties": { "x": { "type": "number" }, "y": { "type": "number" }, "z": { "type": "number" } } } } } } } }, "StarmapObject": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "type": { "type": "string" }, "coordinates": { "type": "object", "properties": { "x": { "type": "number" }, "y": { "type": "number" }, "z": { "type": "number" } } }, "description": { "type": "string", "nullable": true } } }, "StarmapSearchResult": { "type": "object", "properties": { "results": { "type": "array", "items": { "$ref": "#/components/schemas/StarmapObject" } } } }, "Message": { "properties": { "author": { "title": "Message.author", "nullable": true, "type": "string" }, "content": { "title": "Message.content", "type": "string" }, "timestamp": { "title": "Message.timestamp", "type": "number" } }, "required": [ "author", "content", "timestamp" ], "additionalProperties": false, "title": "Message", "type": "object" }, "MessageBody": { "properties": { "content": { "title": "MessageBody.content", "type": "string" } }, "required": [ "content" ], "additionalProperties": false, "title": "MessageBody", "type": "object" }, "Chat": { "properties": { "chat_id": { "title": "Chat.chat_id", "type": "string" }, "participants": { "items": { "properties": { "username": { "title": "Chat.participants.[].username", "type": "string" }, "avatar": { "title": "Chat.participants.[].avatar", "type": "string" } }, "required": [ "username", "avatar" ], "additionalProperties": false, "title": "Chat.participants.[]", "type": "object" }, "title": "Chat.participants", "type": "array" }, "messages": { "items": { "$ref": "#/components/schemas/Message", "title": "Chat.messages.[]" }, "title": "Chat.messages", "type": "array" }, "order_id": { "title": "Chat.order_id", "nullable": true, "type": "string" } }, "required": [ "chat_id", "participants", "messages", "order_id" ], "additionalProperties": false, "title": "Chat", "type": "object" }, "ChatBody": { "properties": { "users": { "items": { "title": "ChatBody.users.[]", "type": "string" }, "title": "ChatBody.users", "type": "array" } }, "required": [ "users" ], "additionalProperties": false, "title": "ChatBody", "type": "object" }, "ProfileUpdateBody": { "properties": { "locale": { "title": "ProfileUpdateBody.locale", "type": "string", "enum": [ "en", "es", "uk", "zh-CN", "fr", "de", "ja" ], "description": "User's preferred locale/language" } }, "required": [ "locale" ], "additionalProperties": false, "title": "ProfileUpdateBody", "type": "object" }, "GetCurrentUserProfileSuccess": { "type": "object", "title": "GetCurrentUserProfileSuccess", "description": "Current user profile returned by getCurrentUserProfile, syncRSIHandle, and unlinkStarCitizenAccount", "properties": { "user_id": { "type": "string", "format": "uuid", "description": "Unique identifier for the user" }, "username": { "type": "string", "description": "Username" }, "display_name": { "type": "string", "description": "Display name" }, "profile_description": { "type": "string", "description": "User profile description" }, "role": { "type": "string", "enum": [ "user", "admin" ], "description": "User role" }, "banned": { "type": "boolean", "description": "Whether the user is banned" }, "balance": { "type": "number", "description": "User balance" }, "created_at": { "type": "string", "format": "date-time", "description": "Account creation timestamp" }, "official_server_id": { "type": "string", "nullable": true, "description": "Discord official server ID" }, "discord_thread_channel_id": { "type": "string", "nullable": true, "description": "Discord thread channel ID" }, "market_order_template": { "type": "string", "description": "Default market order template" }, "locale": { "type": "string", "enum": [ "en", "es", "uk", "zh-CN", "fr", "de", "ja" ], "description": "Preferred locale" }, "contractors": { "type": "array", "description": "Contractors the user belongs to", "items": { "type": "object", "properties": { "contractor_id": { "type": "string", "format": "uuid" }, "spectrum_id": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string" }, "avatar": { "type": "string" }, "banner": { "type": "string" }, "size": { "type": "number" }, "role": { "type": "string" } } } }, "avatar": { "type": "string", "format": "uri", "description": "Avatar URL" }, "banner": { "type": "string", "format": "uri", "description": "Banner URL" }, "settings": { "type": "object", "description": "User settings", "properties": { "discord_order_share": { "type": "boolean" }, "discord_public": { "type": "boolean" } } }, "rating": { "type": "object", "description": "User rating summary", "properties": { "average": { "type": "number" }, "count": { "type": "number" } } }, "discord_profile": { "type": "object", "nullable": true, "description": "Linked Discord profile", "properties": { "username": { "type": "string", "nullable": true }, "discriminator": { "type": "string", "nullable": true }, "id": { "type": "string", "nullable": true } } } }, "required": [ "user_id", "username", "display_name", "profile_description", "role", "banned", "balance", "created_at", "locale", "contractors", "avatar", "banner", "settings", "rating", "discord_profile", "market_order_template" ] }, "AddEmailRequest": { "type": "object", "title": "AddEmailRequest", "description": "Request to add email address with notification preferences", "properties": { "email": { "type": "string", "format": "email", "description": "Email address to add" }, "notificationTypeIds": { "type": "array", "description": "Array of notification action type IDs to enable", "items": { "type": "integer" } } }, "required": [ "email" ] }, "AddEmailResponse": { "type": "object", "title": "AddEmailResponse", "properties": { "email_id": { "type": "string", "format": "uuid", "description": "Unique identifier for the email record" }, "email": { "type": "string", "format": "email", "description": "Email address" }, "email_verified": { "type": "boolean", "description": "Whether the email is verified" }, "preferences_created": { "type": "integer", "description": "Number of notification preferences created" }, "message": { "type": "string", "description": "Success message" } }, "required": [ "email_id", "email", "email_verified", "preferences_created", "message" ] }, "UpdateEmailRequest": { "type": "object", "title": "UpdateEmailRequest", "properties": { "email": { "type": "string", "format": "email", "description": "New email address" } }, "required": [ "email" ] }, "EmailPreference": { "type": "object", "title": "EmailPreference", "description": "Email notification preference for a specific action type", "properties": { "preference_id": { "type": "string", "format": "uuid" }, "action_type_id": { "type": "integer", "description": "Notification action type ID" }, "action_name": { "type": "string", "nullable": true, "description": "Notification action name (e.g., 'order_create')" }, "enabled": { "type": "boolean", "description": "Whether email notifications are enabled" }, "frequency": { "type": "string", "enum": [ "immediate", "daily", "weekly" ], "description": "Email frequency" }, "digest_time": { "type": "string", "nullable": true, "format": "time", "description": "Time for daily/weekly digests (HH:MM:SS format)" }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "required": [ "preference_id", "action_type_id", "enabled", "frequency", "created_at", "updated_at" ] }, "EmailPreferencesResponse": { "type": "object", "title": "EmailPreferencesResponse", "properties": { "preferences": { "type": "array", "items": { "$ref": "#/components/schemas/EmailPreference" } }, "email": { "type": "object", "nullable": true, "properties": { "email_id": { "type": "string", "format": "uuid" }, "email": { "type": "string", "format": "email" }, "email_verified": { "type": "boolean" }, "is_primary": { "type": "boolean" } }, "required": [ "email_id", "email", "email_verified", "is_primary" ] } }, "required": [ "preferences", "email" ] }, "UpdateEmailPreferencesRequest": { "type": "object", "title": "UpdateEmailPreferencesRequest", "properties": { "preferences": { "type": "array", "items": { "type": "object", "properties": { "action_type_id": { "type": "integer" }, "enabled": { "type": "boolean" }, "frequency": { "type": "string", "enum": [ "immediate", "daily", "weekly" ] }, "digest_time": { "type": "string", "nullable": true, "format": "time" } }, "required": [ "action_type_id" ] } } }, "required": [ "preferences" ] }, "AuditLogEntry": { "type": "object", "title": "AuditLogEntry", "properties": { "audit_log_id": { "type": "string", "format": "uuid", "description": "Unique identifier for the audit log entry" }, "action": { "type": "string", "description": "Action that was performed (e.g., 'org.archived')", "example": "org.archived" }, "actor_id": { "type": "string", "format": "uuid", "nullable": true, "description": "User ID of the actor who performed the action" }, "actor": { "$ref": "#/components/schemas/MinimalUser", "nullable": true, "description": "User details of the actor (if actor_id exists)" }, "subject_type": { "type": "string", "description": "Type of entity the action was performed on", "example": "contractor" }, "subject_id": { "type": "string", "description": "ID of the entity the action was performed on" }, "metadata": { "type": "object", "description": "Additional metadata about the action", "additionalProperties": true }, "created_at": { "type": "string", "format": "date-time", "description": "Timestamp when the action was performed" } }, "required": [ "audit_log_id", "action", "subject_type", "subject_id", "metadata", "created_at" ] }, "AuditLogsResponse": { "type": "object", "title": "AuditLogsResponse", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/AuditLogEntry" } }, "total": { "type": "integer", "description": "Total number of audit log entries matching the filters" }, "page": { "type": "integer", "description": "Current page number" }, "page_size": { "type": "integer", "description": "Number of items per page" } }, "required": [ "items", "total", "page", "page_size" ] }, "ContractorInviteCode": { "properties": { "invite_id": { "title": "ContractorInviteCode.invite_id", "type": "string" }, "max_uses": { "title": "ContractorInviteCode.max_uses", "type": "integer", "minimum": 0 }, "times_used": { "title": "ContractorInviteCode.times_used", "type": "integer", "minimum": 0 } }, "required": [ "invite_id", "max_uses", "times_used" ], "additionalProperties": false, "title": "ContractorInviteCode", "type": "object" }, "ContractorRole": { "properties": { "contractor_id": { "title": "ContractorRole.contractor_id", "type": "string" }, "name": { "title": "ContractorRole.name", "type": "string", "minLength": 3 }, "position": { "title": "ContractorRole.position", "type": "integer", "minimum": 1 }, "role_id": { "title": "ContractorRole.role_id", "type": "string" }, "manage_roles": { "title": "ContractorRole.manage_roles", "type": "boolean" }, "manage_orders": { "title": "ContractorRole.manage_orders", "type": "boolean" }, "kick_members": { "title": "ContractorRole.kick_members", "type": "boolean" }, "manage_invites": { "title": "ContractorRole.manage_invites", "type": "boolean" }, "manage_org_details": { "title": "ContractorRole.manage_org_details", "type": "boolean" }, "manage_stock": { "title": "ContractorRole.manage_stock", "type": "boolean" }, "manage_market": { "title": "ContractorRole.manage_market", "type": "boolean" }, "manage_recruiting": { "title": "ContractorRole.manage_recruiting", "type": "boolean" }, "manage_webhooks": { "title": "ContractorRole.manage_webhooks", "type": "boolean" } }, "required": [ "contractor_id", "name", "position", "role_id", "manage_roles", "manage_orders", "kick_members", "manage_invites", "manage_org_details", "manage_stock", "manage_market", "manage_recruiting", "manage_webhooks" ], "additionalProperties": false, "title": "ContractorRole", "type": "object" }, "OrderWebhook": { "properties": { "name": { "title": "OrderWebhook.name", "type": "string", "minLength": 3, "maxLength": 100 }, "webhook_url": { "title": "OrderWebhook.webhook_url", "type": "string", "minLength": 3, "maxLength": 1000 }, "actions": { "title": "OrderWebhook.actions", "type": "array", "minItems": 0, "items": { "type": "string" }, "maxLength": 30 } }, "required": [ "name", "webhook_url", "actions" ], "additionalProperties": false, "title": "ContractorRoleBody", "type": "object" }, "ContractorRoleBody": { "properties": { "name": { "title": "ContractorRoleBody.name", "type": "string", "minLength": 3, "maxLength": 100 }, "manage_roles": { "title": "ContractorRoleBody.manage_roles", "type": "boolean" }, "manage_orders": { "title": "ContractorRoleBody.manage_orders", "type": "boolean" }, "kick_members": { "title": "ContractorRoleBody.kick_members", "type": "boolean" }, "manage_invites": { "title": "ContractorRoleBody.manage_invites", "type": "boolean" }, "manage_org_details": { "title": "ContractorRoleBody.manage_org_details", "type": "boolean" }, "manage_stock": { "title": "ContractorRoleBody.manage_stock", "type": "boolean" }, "manage_market": { "title": "ContractorRoleBody.manage_market", "type": "boolean" }, "manage_recruiting": { "title": "ContractorRoleBody.manage_recruiting", "type": "boolean" }, "manage_webhooks": { "title": "ContractorRoleBody.manage_webhooks", "type": "boolean" }, "manage_blocklist": { "title": "ContractorRoleBody.manage_blocklist", "type": "boolean" } }, "required": [ "name", "manage_roles", "manage_orders", "kick_members", "manage_invites", "manage_org_details", "manage_stock", "manage_market", "manage_recruiting", "manage_webhooks", "manage_blocklist" ], "additionalProperties": false, "title": "ContractorRoleBody", "type": "object" }, "ContractorRoleUpdateBody": { "properties": { "name": { "title": "ContractorRoleUpdateBody.name", "type": "string", "minLength": 3, "maxLength": 100 }, "position": { "title": "ContractorRoleUpdateBody.position", "type": "integer", "minimum": 1 }, "manage_roles": { "title": "ContractorRoleUpdateBody.manage_roles", "type": "boolean" }, "manage_orders": { "title": "ContractorRoleUpdateBody.manage_orders", "type": "boolean" }, "kick_members": { "title": "ContractorRoleUpdateBody.kick_members", "type": "boolean" }, "manage_invites": { "title": "ContractorRoleUpdateBody.manage_invites", "type": "boolean" }, "manage_org_details": { "title": "ContractorRoleUpdateBody.manage_org_details", "type": "boolean" }, "manage_stock": { "title": "ContractorRoleUpdateBody.manage_stock", "type": "boolean" }, "manage_market": { "title": "ContractorRoleUpdateBody.manage_market", "type": "boolean" }, "manage_recruiting": { "title": "ContractorRoleUpdateBody.manage_recruiting", "type": "boolean" }, "manage_webhooks": { "title": "ContractorRoleUpdateBody.manage_webhooks", "type": "boolean" }, "manage_blocklist": { "title": "ContractorRoleUpdateBody.manage_blocklist", "type": "boolean" }, "claim_orders": { "title": "ContractorRoleUpdateBody.claim_orders", "type": "boolean" }, "manage_theme": { "title": "ContractorRoleUpdateBody.manage_theme", "type": "boolean" } }, "required": [ "name", "position", "manage_roles", "manage_orders", "kick_members", "manage_invites", "manage_org_details", "manage_stock", "manage_market", "manage_recruiting", "manage_webhooks", "manage_blocklist", "claim_orders", "manage_theme" ], "additionalProperties": false, "title": "ContractorRoleUpdateBody", "type": "object" }, "ContractorKindIconKey": { "type": "string", "title": "ContractorKindIconKey", "enum": [ "combat", "freight", "refuel", "repair", "mining", "transport", "exploration", "escort", "salvage", "refining", "construction", "social", "roleplay", "medical", "intelligence" ], "description": "Contractor specialization/field key used for icons and filtering" }, "Contractor": { "properties": { "kind": { "enum": [ "independent", "organization" ], "title": "Contractor.kind", "type": "string" }, "avatar": { "title": "Contractor.avatar", "type": "string" }, "banner": { "title": "Contractor.banner", "type": "string" }, "site_url": { "title": "Contractor.site_url", "type": "string" }, "rating": { "$ref": "#/components/schemas/Rating", "title": "Contractor.rating" }, "size": { "title": "Contractor.size", "type": "integer", "minimum": 0 }, "name": { "title": "Contractor.name", "type": "string", "minLength": 3, "maxLength": 100 }, "description": { "title": "Contractor.description", "type": "string", "minLength": 0, "maxLength": 2000 }, "fields": { "items": { "$ref": "#/components/schemas/ContractorKindIconKey", "title": "Contractor.fields.[]" }, "title": "Contractor.fields", "type": "array" }, "spectrum_id": { "title": "Contractor.spectrum_id", "type": "string" }, "market_order_template": { "title": "Contractor.market_order_template", "type": "string" }, "members": { "items": { "properties": { "username": { "title": "Contractor.members.[].username", "type": "string" }, "roles": { "items": { "title": "Contractor.members.[].roles.[]", "type": "string" }, "title": "Contractor.members.[].roles", "type": "array" } }, "required": [ "username", "roles" ], "additionalProperties": false, "title": "Contractor.members.[]", "type": "object" }, "title": "Contractor.members", "type": "array" }, "roles": { "items": { "$ref": "#/components/schemas/ContractorRole", "title": "Contractor.roles.[]" }, "title": "Contractor.roles", "type": "array" }, "default_role": { "title": "Contractor.default_role", "type": "string" }, "owner_role": { "title": "Contractor.owner_role", "type": "string" }, "balance": { "title": "Contractor.balance", "type": "number" }, "locale": { "title": "Contractor.locale", "type": "string", "enum": [ "en", "es", "uk", "zh-CN", "fr", "de", "ja" ], "description": "Preferred locale for the contractor" } }, "required": [ "kind", "avatar", "banner", "rating", "size", "name", "description", "fields", "spectrum_id", "members" ], "additionalProperties": false, "title": "Contractor", "type": "object" }, "ContractorBody": { "properties": { "logo": { "title": "ContractorBody.logo", "type": "string" }, "banner": { "title": "ContractorBody.banner", "type": "string" }, "name": { "title": "ContractorBody.name", "type": "string", "minLength": 3, "maxLength": 100 }, "description": { "title": "ContractorBody.description", "type": "string", "minLength": 0, "maxLength": 2000 }, "identifier": { "title": "ContractorBody.identifier", "type": "string", "minLength": 3, "maxLength": 30 }, "language_codes": { "title": "ContractorBody.language_codes", "type": "array", "description": "Optional ISO 639-1 language codes for org communication preferences", "items": { "type": "string", "enum": [ "en", "es", "fr", "de", "it", "pt", "ru", "zh", "ja", "ko", "ar", "hi", "nl", "pl", "tr", "sv", "da", "no", "fi", "cs", "hu", "ro", "el", "he", "th", "vi", "id", "ms", "uk", "sk" ] } } }, "required": [ "logo", "banner", "name", "description", "identifier" ], "additionalProperties": false, "title": "ContractorBody", "type": "object" }, "ContractorUpdateBody": { "properties": { "site_url": { "title": "ContractorUpdateBody.site_url", "type": "string" }, "name": { "title": "ContractorUpdateBody.name", "type": "string", "minLength": 3, "maxLength": 100 }, "description": { "title": "ContractorUpdateBody.description", "type": "string", "minLength": 0, "maxLength": 2000 }, "market_order_template": { "title": "ContractorUpdateBody.market_order_template", "type": "string", "minLength": 0, "maxLength": 2000 }, "tags": { "title": "ContractorUpdateBody.tags", "type": "array", "items": { "type": "string", "enum": [ "combat", "freight", "refuel", "repair", "mining", "transport", "exploration", "escort", "salvage", "refining", "construction", "social", "roleplay", "medical", "intelligence" ] } }, "locale": { "title": "ContractorUpdateBody.locale", "type": "string", "enum": [ "en", "es", "uk", "zh-CN", "fr", "de", "ja" ], "description": "Preferred locale for the contractor" } }, "required": [], "additionalProperties": false, "title": "ContractorBody", "type": "object" }, "ContractorMemberSearchBody": { "properties": { "spectrum_id": { "title": "ContractorMemberSearchBody.spectrum_id", "type": "string", "maxLength": 50, "minLength": 3 }, "query": { "title": "ContractorMemberSearchBody.query", "type": "string", "minLength": 3, "maxLength": 50 } }, "required": [ "spectrum_id", "query" ], "additionalProperties": false, "title": "ContractorMemberSearchBody", "type": "object" }, "OrderStatus": { "enum": [ "fulfilled", "in-progress", "not-started", "cancelled" ], "title": "OrderStatus", "type": "string" }, "OrderBody": { "properties": { "title": { "title": "OrderBody.title", "type": "string", "maxLength": 100, "minLength": 1 }, "rush": { "title": "OrderBody.rush", "type": "boolean" }, "description": { "title": "OrderBody.description", "type": "string", "maxLength": 2000 }, "kind": { "enum": [ "Escort", "Transport", "Construction", "Support", "Resource Acquisition", "Rental", "Custom", "Delivery", "Medical", "Intelligence Services" ], "title": "OrderBody.kind", "type": "string" }, "collateral": { "title": "OrderBody.collateral", "type": "integer", "minimum": 0 }, "departure": { "title": "OrderBody.departure", "type": "string", "nullable": true, "maxLength": 30 }, "destination": { "title": "OrderBody.destination", "type": "string", "nullable": true, "maxLength": 30 }, "cost": { "title": "OrderBody.cost", "type": "integer", "minimum": 0 }, "contractor": { "title": "OrderBody.contractor", "type": "string", "nullable": true }, "assigned_to": { "title": "OrderBody.assigned_to", "type": "string", "nullable": true }, "service_id": { "title": "OrderBody.service_id", "type": "string", "nullable": true }, "payment_type": { "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ], "title": "OrderBody.payment_type", "type": "string" } }, "required": [ "title", "rush", "description", "kind", "collateral", "departure", "destination", "cost", "payment_type" ], "additionalProperties": false, "title": "OrderBody", "type": "object" }, "OrderStub": { "properties": { "order_id": { "title": "OrderStub.order_id", "type": "string" }, "contractor": { "$ref": "#/components/schemas/MinimalContractor", "nullable": true, "title": "OrderStub.contractor" }, "assigned_to": { "$ref": "#/components/schemas/MinimalUser", "nullable": true, "title": "OrderStub.assigned_to" }, "customer": { "$ref": "#/components/schemas/MinimalUser", "title": "OrderStub.customer" }, "status": { "$ref": "#/components/schemas/OrderStatus", "title": "OrderStub.status" }, "timestamp": { "title": "OrderStub.timestamp", "type": "string" }, "service_name": { "title": "OrderStub.service_name", "type": "string", "nullable": true }, "cost": { "title": "OrderStub.cost", "type": "integer", "minimum": 0 }, "title": { "title": "OrderStub.title", "type": "string", "minLength": 1, "maxLength": 100 }, "payment_type": { "title": "OrderStub.payment_type", "type": "string", "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ] }, "count": { "title": "OrderStub.count", "type": "integer", "minimum": 0 } }, "required": [ "order_id", "contractor", "assigned_to", "customer", "status", "timestamp", "service_name", "cost", "title", "payment_type", "count" ], "additionalProperties": false, "title": "OrderStub", "type": "object" }, "OrderApplicant": { "properties": { "order_id": { "title": "OrderApplicant.order_id", "type": "string" }, "user_applicant": { "$ref": "#/components/schemas/MinimalUser", "nullable": true, "title": "OrderApplicant.user_applicant" }, "org_applicant": { "$ref": "#/components/schemas/MinimalContractor", "nullable": true, "title": "OrderApplicant.org_applicant" }, "timestamp": { "title": "OrderApplicant.timestamp", "type": "number" }, "message": { "title": "OrderApplicant.message", "type": "string" } }, "required": [ "order_id", "user_applicant", "org_applicant", "timestamp", "message" ], "additionalProperties": false, "title": "OrderApplicant", "type": "object" }, "OfferMarketListing": { "properties": { "quantity": { "title": "OfferMarketListing.quantity", "type": "number" }, "listing_id": { "title": "OfferMarketListing.listing_id", "type": "string" }, "listing": { "$ref": "#/components/schemas/UniqueListing", "title": "OfferMarketListing.listing" } }, "required": [ "quantity", "listing_id", "listing" ], "additionalProperties": false, "title": "OfferMarketListing", "type": "object" }, "Order": { "properties": { "order_id": { "title": "Order.order_id", "type": "string" }, "status": { "$ref": "#/components/schemas/OrderStatus", "title": "Order.status" }, "kind": { "type": "string" }, "cost": { "title": "Order.cost", "type": "number", "minimum": 0 }, "rush": { "title": "Order.rush", "type": "boolean" }, "assigned_to": { "title": "Order.assigned_to", "type": "string", "nullable": true }, "contractor": { "title": "Order.contractor", "type": "string", "nullable": true }, "customer": { "title": "Order.customer", "type": "string" }, "title": { "title": "Order.title", "type": "string" }, "description": { "title": "Order.description", "type": "string" }, "discord_thread_id": { "title": "Order.discord_thread_id", "type": "string", "nullable": true }, "discord_server_id": { "title": "Order.discord_server_id", "type": "string", "nullable": true }, "discord_invite": { "title": "Order.discord_invite", "type": "string", "nullable": true }, "timestamp": { "title": "Order.timestamp", "type": "string" }, "applicants": { "items": { "$ref": "#/components/schemas/OrderApplicant", "title": "Order.applicants.[]" }, "title": "Order.applicants", "type": "array" }, "market_listings": { "items": { "$ref": "#/components/schemas/OfferMarketListing", "title": "Order.market_listings.[]" }, "title": "Order.market_listings", "type": "array" }, "customer_review": { "$ref": "#/components/schemas/OrderReview", "title": "Order.customer_review" }, "contractor_review": { "$ref": "#/components/schemas/OrderReview", "title": "Order.customer_review" }, "template_id": { "title": "Order.template_id", "type": "string", "nullable": true }, "payment_type": { "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ], "title": "Order.payment_type", "type": "string" }, "availability": { "title": "Order.availability", "$ref": "#/components/schemas/OrderAvailability" }, "offer_session_id": { "title": "Order.offer_session_id", "type": "string", "nullable": true } }, "required": [ "order_id", "status", "kind", "cost", "rush", "assigned_to", "contractor", "customer", "title", "description", "timestamp", "comments", "applicants", "payment_type", "offer_session_id" ], "additionalProperties": false, "title": "Order", "type": "object" }, "UUID": { "type": "string", "format": "uuid", "description": "A universally unique identifier" }, "Timestamp": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp" }, "Price": { "type": "number", "minimum": 0, "description": "Price in the smallest currency unit (e.g., cents)" }, "Quantity": { "type": "integer", "minimum": 0, "description": "Available quantity" }, "ListingTitle": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Listing title" }, "ListingDescription": { "type": "string", "minLength": 1, "maxLength": 2000, "description": "Listing description" }, "ItemType": { "type": "string", "description": "Type of game item" }, "GameItemId": { "type": "string", "nullable": true, "description": "Game item identifier" }, "SaleType": { "type": "string", "enum": [ "unique", "aggregate", "multiple", "auction" ], "description": "Type of sale" }, "ListingStatus": { "type": "string", "enum": [ "active", "inactive", "archived" ], "description": "Listing status" }, "ListingType": { "type": "string", "enum": [ "unique", "aggregate", "multiple" ], "description": "Type of listing" }, "RatingInfo": { "type": "object", "properties": { "total_rating": { "type": "number", "description": "Total rating points" }, "avg_rating": { "type": "number", "description": "Average rating" }, "rating_count": { "type": "integer", "nullable": true, "description": "Number of ratings" }, "rating_streak": { "type": "integer", "nullable": true, "description": "Current rating streak" } }, "required": [ "total_rating", "avg_rating" ] }, "SellerInfo": { "type": "object", "properties": { "user_seller": { "type": "string", "nullable": true, "description": "Username of the user seller" }, "contractor_seller": { "type": "string", "nullable": true, "description": "Spectrum ID of the contractor seller" } } }, "GrafanaTimeSeries": { "type": "object", "title": "GrafanaTimeSeries", "properties": { "target": { "type": "string", "description": "Metric name/series identifier", "example": "total_orders" }, "datapoints": { "type": "array", "description": "Array of [value, timestamp_in_ms] pairs", "items": { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2 }, "example": [ [ 150, 1704067200000 ] ] } }, "required": [ "target", "datapoints" ] }, "OrderStats": { "type": "object", "properties": { "total_orders": { "type": "number", "description": "Total number of orders" }, "total_order_value": { "type": "number", "description": "Total value of all orders" }, "week_orders": { "type": "number", "description": "Number of orders in the last week" }, "week_order_value": { "type": "number", "description": "Total value of orders in the last week" } }, "required": [ "total_orders", "total_order_value" ] }, "MarketListing": { "type": "object", "description": "A market listing with complete information", "properties": { "listing_id": { "$ref": "#/components/schemas/UUID", "description": "Unique identifier for the listing" }, "sale_type": { "$ref": "#/components/schemas/SaleType", "description": "Type of sale for this listing" }, "price": { "$ref": "#/components/schemas/Price", "description": "Current price of the listing" }, "quantity_available": { "$ref": "#/components/schemas/Quantity", "description": "Number of items available for sale" }, "status": { "$ref": "#/components/schemas/ListingStatus", "description": "Current status of the listing" }, "internal": { "type": "boolean", "description": "Whether this is an internal listing (only visible to organization members)" }, "user_seller_id": { "$ref": "#/components/schemas/UUID", "nullable": true, "description": "ID of the user seller (if sold by a user)" }, "contractor_seller_id": { "$ref": "#/components/schemas/UUID", "nullable": true, "description": "ID of the contractor seller (if sold by a contractor)" }, "timestamp": { "$ref": "#/components/schemas/Timestamp", "description": "When the listing was created" }, "expiration": { "$ref": "#/components/schemas/Timestamp", "nullable": true, "description": "When the listing expires" }, "title": { "$ref": "#/components/schemas/ListingTitle", "description": "Title of the listing" }, "description": { "$ref": "#/components/schemas/ListingDescription", "description": "Detailed description of the listing" }, "item_type": { "$ref": "#/components/schemas/ItemType", "description": "Type of game item being sold" }, "game_item_id": { "$ref": "#/components/schemas/GameItemId", "description": "Specific game item identifier" }, "photos": { "type": "array", "items": { "type": "string", "description": "URL to a photo" }, "maxItems": 10, "description": "Array of photo URLs for the listing" } }, "required": [ "listing_id", "sale_type", "price", "quantity_available", "status", "internal", "timestamp", "title", "description", "item_type" ], "additionalProperties": false }, "CreateMarketListingRequest": { "type": "object", "description": "Request to create a new market listing", "properties": { "sale_type": { "$ref": "#/components/schemas/SaleType", "description": "Type of sale for the new listing" }, "price": { "$ref": "#/components/schemas/Price", "description": "Price for the listing" }, "quantity_available": { "type": "integer", "minimum": 1, "description": "Number of items available for sale" }, "title": { "$ref": "#/components/schemas/ListingTitle", "description": "Title for the listing" }, "description": { "$ref": "#/components/schemas/ListingDescription", "description": "Detailed description of the listing" }, "item_type": { "$ref": "#/components/schemas/ItemType", "description": "Type of game item being sold" }, "game_item_id": { "$ref": "#/components/schemas/GameItemId", "description": "Specific game item identifier" }, "photos": { "type": "array", "items": { "type": "string", "description": "URL to a photo" }, "maxItems": 10, "description": "Array of photo URLs for the listing" }, "expiration_days": { "type": "integer", "minimum": 1, "maximum": 30, "default": 7, "description": "Number of days until the listing expires" } }, "required": [ "sale_type", "price", "quantity_available", "title", "description", "item_type" ], "additionalProperties": false }, "UpdateMarketListingRequest": { "type": "object", "description": "Request to update an existing market listing", "properties": { "price": { "$ref": "#/components/schemas/Price", "description": "New price for the listing" }, "quantity_available": { "$ref": "#/components/schemas/Quantity", "description": "New available quantity" }, "title": { "$ref": "#/components/schemas/ListingTitle", "description": "New title for the listing" }, "description": { "$ref": "#/components/schemas/ListingDescription", "description": "New description for the listing" }, "status": { "$ref": "#/components/schemas/ListingStatus", "description": "New status for the listing" }, "photos": { "type": "array", "items": { "type": "string", "description": "URL to a photo" }, "maxItems": 10, "description": "New array of photo URLs for the listing" }, "item_type": { "type": "string", "description": "New item type for the listing" }, "item_name": { "type": "string", "nullable": true, "description": "New item name for the listing" }, "minimum_bid_increment": { "type": "number", "minimum": 0, "description": "New minimum bid increment for auction listings" }, "internal": { "type": "boolean", "description": "Whether the listing is internal (contractor only)" } }, "additionalProperties": false }, "MarketBid": { "type": "object", "title": "MarketBid", "properties": { "bid_id": { "type": "string", "format": "uuid", "title": "MarketBid.bid_id" }, "listing_id": { "type": "string", "format": "uuid", "title": "MarketBid.listing_id" }, "bidder": { "type": "object", "properties": { "user_id": { "type": "string", "nullable": true }, "contractor_id": { "type": "string", "nullable": true }, "username": { "type": "string" }, "display_name": { "type": "string" } }, "title": "MarketBid.bidder" }, "bid_amount": { "type": "number", "minimum": 0, "title": "MarketBid.bid_amount" }, "timestamp": { "type": "string", "format": "date-time", "title": "MarketBid.timestamp" } }, "required": [ "bid_id", "listing_id", "bidder", "bid_amount", "timestamp" ], "additionalProperties": false }, "CreateBidRequest": { "type": "object", "title": "CreateBidRequest", "properties": { "bid_amount": { "type": "number", "minimum": 0, "title": "CreateBidRequest.bid_amount" } }, "required": [ "bid_amount" ], "additionalProperties": false }, "MarketSearchParams": { "type": "object", "title": "MarketSearchParams", "properties": { "query": { "type": "string", "title": "MarketSearchParams.query" }, "statuses": { "type": "string", "title": "MarketSearchParams.statuses", "description": "Comma-separated list of statuses (e.g., 'active,inactive')" }, "sale_type": { "type": "string", "enum": [ "unique", "aggregate", "multiple", "auction" ], "title": "MarketSearchParams.sale_type" }, "item_type": { "type": "string", "title": "MarketSearchParams.item_type" }, "quantity_available": { "type": "string", "title": "MarketSearchParams.quantity_available" }, "min_price": { "type": "number", "minimum": 0, "title": "MarketSearchParams.min_price" }, "max_price": { "type": "number", "minimum": 0, "title": "MarketSearchParams.max_price" }, "user_seller_id": { "type": "string", "title": "MarketSearchParams.user_seller_id" }, "contractor_seller_id": { "type": "string", "title": "MarketSearchParams.contractor_seller_id" }, "page": { "type": "integer", "minimum": 0, "default": 0, "title": "MarketSearchParams.page" }, "pageSize": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20, "title": "MarketSearchParams.pageSize" } }, "additionalProperties": false }, "ListingUpdateRequest": { "type": "object", "title": "ListingUpdateRequest", "properties": { "status": { "type": "string", "enum": [ "active", "inactive", "archived" ], "description": "New status for the listing" }, "title": { "type": "string", "description": "New title for the listing" }, "description": { "type": "string", "description": "New description for the listing" }, "item_type": { "type": "string", "description": "Type of the item" }, "item_name": { "type": "string", "description": "Name of the game item" }, "price": { "type": "integer", "description": "New price for the listing", "minimum": 0 }, "quantity_available": { "type": "integer", "minimum": 0, "description": "New quantity available" }, "photos": { "type": "array", "items": { "type": "string" }, "description": "List of photo URLs" }, "minimum_bid_increment": { "type": "integer", "minimum": 1, "description": "Minimum increment for auction bids" } } }, "UpdateListingResponse": { "type": "object", "title": "UpdateListingResponse", "properties": { "result": { "type": "string", "enum": [ "Success" ] } }, "required": [ "result" ] }, "ErrorResponse": { "type": "object", "title": "ErrorResponse", "properties": { "error": { "type": "string" } }, "required": [ "error" ] }, "UpdateQuantityRequest": { "type": "object", "title": "UpdateQuantityRequest", "properties": { "quantity_available": { "type": "number", "minimum": 0, "description": "New quantity available for the listing" } }, "required": [ "quantity_available" ] }, "UpdateQuantityResponse": { "type": "object", "title": "UpdateQuantityResponse", "properties": { "result": { "type": "string", "enum": [ "Success" ] } }, "required": [ "result" ] }, "RefreshListingResponse": { "type": "object", "title": "RefreshListingResponse", "properties": { "result": { "type": "string", "enum": [ "Success" ] } }, "required": [ "result" ] }, "MarketListingSeller": { "type": "object", "title": "MarketListingSeller", "properties": { "user": { "$ref": "#/components/schemas/MinimalUser", "nullable": true }, "contractor": { "$ref": "#/components/schemas/MinimalContractor", "nullable": true } } }, "MarketListingBase": { "type": "object", "title": "MarketListingBase", "properties": { "listing_id": { "type": "string" }, "sale_type": { "type": "string", "enum": [ "unique", "multiple", "auction", "aggregate" ] }, "price": { "type": "number" }, "quantity_available": { "type": "number" }, "status": { "type": "string", "enum": [ "active", "inactive", "archived" ] }, "timestamp": { "type": "string", "format": "date-time" }, "expiration": { "type": "string", "format": "date-time" }, "seller": { "$ref": "#/components/schemas/MarketListingSeller" } }, "required": [ "listing_id", "sale_type", "price", "quantity_available", "status", "timestamp", "expiration", "seller" ] }, "UniqueListing": { "type": "object", "title": "UniqueListing", "allOf": [ { "$ref": "#/components/schemas/MarketListingBase" }, { "properties": { "title": { "type": "string" }, "description": { "type": "string" }, "item_type": { "type": "string" }, "photos": { "type": "array", "items": { "type": "string" } }, "game_item": { "type": "object", "properties": { "name": { "type": "string" }, "icon_url": { "type": "string" } }, "nullable": true }, "view_count": { "type": "number", "description": "Total number of views for this listing", "minimum": 0 } } } ] }, "AggregateListingStats": { "type": "object", "title": "AggregateListingStats", "properties": { "minimum_price": { "type": "number" }, "maximum_price": { "type": "number" }, "average_price": { "type": "number" }, "total_quantity": { "type": "number" } } }, "AggregateListing": { "type": "object", "title": "AggregateListing", "allOf": [ { "$ref": "#/components/schemas/MarketListingBase" }, { "properties": { "stats": { "$ref": "#/components/schemas/AggregateListingStats" }, "game_item": { "type": "object", "properties": { "name": { "type": "string" }, "icon_url": { "type": "string" } } } } } ] }, "MarketListingComplete": { "type": "object", "title": "MarketListingComplete", "properties": { "listing_id": { "type": "string", "title": "MarketListingComplete.listing_id" }, "price": { "type": "number", "minimum": 0, "title": "MarketListingComplete.price" }, "sale_type": { "type": "string", "enum": [ "sale", "auction", "aggregate", "multiple" ], "title": "MarketListingComplete.sale_type" }, "quantity_available": { "type": "integer", "minimum": 0, "title": "MarketListingComplete.quantity_available" }, "status": { "type": "string", "enum": [ "active", "inactive", "archived" ], "title": "MarketListingComplete.status" }, "title": { "type": "string", "title": "MarketListingComplete.title" }, "description": { "type": "string", "title": "MarketListingComplete.description" }, "item_type": { "type": "string", "title": "MarketListingComplete.item_type" }, "internal": { "type": "boolean", "title": "MarketListingComplete.internal" }, "seller": { "type": "object", "properties": { "user": { "type": "object", "nullable": true, "properties": { "user_id": { "type": "string" }, "username": { "type": "string" }, "avatar_url": { "type": "string", "nullable": true } } }, "contractor": { "type": "object", "nullable": true, "properties": { "contractor_id": { "type": "string" }, "name": { "type": "string" }, "spectrum_id": { "type": "string" }, "logo_url": { "type": "string", "nullable": true } } } } }, "photos": { "type": "array", "items": { "type": "object", "properties": { "resource_id": { "type": "string" }, "url": { "type": "string" } } } }, "auction_details": { "type": "object", "nullable": true, "properties": { "minimum_bid_increment": { "type": "number" }, "end_time": { "type": "string", "format": "date-time" }, "status": { "type": "string", "enum": [ "active", "inactive" ] }, "current_bid": { "type": "object", "nullable": true, "properties": { "amount": { "type": "number" }, "bidder": { "type": "object", "properties": { "user_id": { "type": "string" }, "username": { "type": "string" }, "avatar_url": { "type": "string", "nullable": true } } } } } } }, "game_item": { "type": "object", "nullable": true, "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "type": { "type": "string" }, "description": { "type": "string" } } }, "created_at": { "type": "string", "format": "date-time", "title": "MarketListingComplete.created_at" }, "updated_at": { "type": "string", "format": "date-time", "title": "MarketListingComplete.updated_at" } }, "required": [ "listing_id", "price", "sale_type", "quantity_available", "status", "title", "description", "item_type", "internal", "photos", "created_at", "updated_at" ], "additionalProperties": false }, "ListingOrdersPagination": { "type": "object", "title": "ListingOrdersPagination", "properties": { "currentPage": { "type": "number" }, "pageSize": { "type": "number" }, "totalItems": { "type": "number" }, "totalPages": { "type": "number" }, "hasNextPage": { "type": "boolean" }, "hasPreviousPage": { "type": "boolean" } }, "required": [ "currentPage", "pageSize", "totalItems", "totalPages", "hasNextPage", "hasPreviousPage" ] }, "ListingOrdersResponse": { "type": "object", "title": "ListingOrdersResponse", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Order" } }, "pagination": { "$ref": "#/components/schemas/ListingOrdersPagination" } }, "required": [ "data", "pagination" ] }, "PurchaseRequest": { "type": "object", "title": "PurchaseRequest", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/OfferBodyMarketListing" }, "minItems": 1 }, "note": { "type": "string", "description": "Optional note from buyer to seller" }, "offer": { "type": "number", "minimum": 0, "description": "Optional custom offer amount in aUEC" } }, "required": [ "items" ] }, "MarketBidRequest": { "type": "object", "title": "MarketBidRequest", "properties": { "listing_id": { "type": "string", "title": "MarketBidRequest.listing_id" }, "bid": { "type": "number", "minimum": 0, "title": "MarketBidRequest.bid" } }, "required": [ "listing_id", "bid" ], "additionalProperties": false }, "MarketListingCreateRequest": { "type": "object", "title": "MarketListingCreateRequest", "properties": { "price": { "type": "number", "minimum": 0, "title": "MarketListingCreateRequest.price" }, "title": { "type": "string", "minLength": 1, "maxLength": 100, "title": "MarketListingCreateRequest.title" }, "description": { "type": "string", "minLength": 1, "maxLength": 2000, "title": "MarketListingCreateRequest.description" }, "sale_type": { "type": "string", "enum": [ "sale", "auction" ], "title": "MarketListingCreateRequest.sale_type" }, "item_type": { "type": "string", "title": "MarketListingCreateRequest.item_type" }, "item_name": { "type": "string", "nullable": true, "title": "MarketListingCreateRequest.item_name" }, "quantity_available": { "type": "integer", "minimum": 1, "title": "MarketListingCreateRequest.quantity_available" }, "photos": { "type": "array", "items": { "type": "string", "format": "uri" }, "title": "MarketListingCreateRequest.photos", "description": "Array of photo URLs. If empty or not provided, a default placeholder photo will be used." }, "minimum_bid_increment": { "type": "number", "minimum": 0, "title": "MarketListingCreateRequest.minimum_bid_increment" }, "status": { "type": "string", "enum": [ "active", "inactive" ], "title": "MarketListingCreateRequest.status" }, "end_time": { "type": "string", "nullable": true, "format": "date-time", "title": "MarketListingCreateRequest.end_time" } }, "required": [ "price", "title", "description", "sale_type", "item_type", "quantity_available", "minimum_bid_increment", "status" ] }, "MarketListingSearchResult": { "type": "object", "description": "A market listing as returned in search results", "properties": { "listing_id": { "$ref": "#/components/schemas/UUID", "description": "Unique identifier for the listing" }, "listing_type": { "$ref": "#/components/schemas/ListingType", "description": "Type of listing" }, "item_type": { "$ref": "#/components/schemas/ItemType", "description": "Type of game item" }, "item_name": { "type": "string", "nullable": true, "description": "Name of the specific game item" }, "game_item_id": { "$ref": "#/components/schemas/GameItemId", "description": "Specific game item identifier" }, "sale_type": { "$ref": "#/components/schemas/SaleType", "description": "Type of sale" }, "price": { "$ref": "#/components/schemas/Price", "description": "Current price" }, "expiration": { "$ref": "#/components/schemas/Timestamp", "nullable": true, "description": "When the listing expires" }, "minimum_price": { "$ref": "#/components/schemas/Price", "description": "Minimum price (for auctions)" }, "maximum_price": { "$ref": "#/components/schemas/Price", "description": "Maximum price (for auctions)" }, "quantity_available": { "$ref": "#/components/schemas/Quantity", "description": "Available quantity" }, "timestamp": { "$ref": "#/components/schemas/Timestamp", "description": "When the listing was created" }, "details_id": { "$ref": "#/components/schemas/UUID", "description": "ID of the listing details" }, "status": { "$ref": "#/components/schemas/ListingStatus", "description": "Current status" }, "title": { "$ref": "#/components/schemas/ListingTitle", "description": "Listing title" }, "photo": { "type": "string", "description": "URL to the primary photo" }, "internal": { "type": "boolean", "description": "Whether this is an internal listing" }, "auction_end_time": { "$ref": "#/components/schemas/Timestamp", "nullable": true, "description": "When the auction ends (for auction listings)" }, "total_rating": { "type": "number", "description": "Total rating points for the seller" }, "avg_rating": { "type": "number", "description": "Average rating for the seller" }, "rating_count": { "type": "integer", "nullable": true, "description": "Number of ratings for the seller" }, "rating_streak": { "type": "integer", "nullable": true, "description": "Current rating streak for the seller" }, "user_seller": { "type": "string", "nullable": true, "description": "Username of the user seller" }, "contractor_seller": { "type": "string", "nullable": true, "description": "Spectrum ID of the contractor seller" }, "total_orders": { "type": "integer", "nullable": true, "description": "Total number of orders for the seller" }, "total_assignments": { "type": "integer", "nullable": true, "description": "Total number of assignments for the seller" }, "response_rate": { "type": "number", "nullable": true, "description": "Response rate percentage for the seller" } }, "required": [ "listing_id", "listing_type", "item_type", "sale_type", "price", "quantity_available", "timestamp", "status", "title", "photo", "internal", "total_rating", "avg_rating" ], "additionalProperties": false }, "BuyOrder": { "type": "object", "title": "BuyOrder", "description": "Market buy order for an aggregate listing", "properties": { "buy_order_id": { "type": "string", "description": "Unique buy order ID" }, "aggregate_id": { "type": "string", "description": "Game item ID (aggregate)" }, "quantity": { "type": "number", "description": "Requested quantity" }, "price": { "type": "number", "description": "Price per unit" }, "buyer": { "$ref": "#/components/schemas/MinimalUser", "description": "Buyer user summary" }, "expiry": { "type": "string", "format": "date-time", "description": "Order expiry timestamp" } }, "required": [ "buy_order_id", "aggregate_id", "quantity", "price", "buyer", "expiry" ] }, "MarketAggregateComplete": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "aggregate" ], "description": "Type of the market listing" }, "details": { "type": "object", "description": "Item details" }, "aggregate_id": { "type": "string", "description": "Game item ID for the aggregate" }, "photos": { "type": "array", "items": { "type": "string", "description": "CDN URLs for item images" } }, "buy_orders": { "type": "array", "items": { "$ref": "#/components/schemas/BuyOrder" }, "description": "List of buy orders for this item" }, "listings": { "type": "array", "items": { "$ref": "#/components/schemas/MarketListingBase" }, "description": "List of related listings" } }, "required": [ "type", "details", "aggregate_id", "photos", "buy_orders", "listings" ], "additionalProperties": false, "title": "MarketAggregateComplete" }, "BuyOrderChartDataPoint": { "type": "object", "properties": { "high": { "type": "number", "description": "Highest price during the day" }, "low": { "type": "number", "description": "Lowest price during the day" }, "close": { "type": "number", "description": "Closing price of the day" }, "open": { "type": "number", "description": "Opening price of the day" }, "timestamp": { "type": "number", "description": "Unix timestamp for the day" }, "volume": { "type": "number", "description": "Total quantity of orders during the day" } }, "required": [ "high", "low", "close", "open", "timestamp", "volume" ], "additionalProperties": false, "title": "BuyOrderChartDataPoint" }, "GameItemDescription": { "type": "object", "title": "GameItemDescription", "properties": { "id": { "type": "string", "description": "Unique identifier for the game item" }, "name": { "type": "string", "description": "Name of the game item" }, "type": { "type": "string", "description": "Type/category of the game item" }, "description": { "type": "string", "description": "Description of the game item" }, "image_url": { "type": "string", "nullable": true, "description": "URL to the item's image" } }, "required": [ "id", "name", "type", "description" ], "additionalProperties": false }, "Notification": { "type": "object", "title": "Notification", "description": "A notification object containing information about a system event", "properties": { "read": { "type": "boolean", "description": "Whether the notification has been read by the user" }, "notification_id": { "type": "string", "format": "uuid", "description": "Unique identifier for the notification" }, "action": { "type": "string", "description": "The type of action that triggered this notification", "allOf": [ { "$ref": "#/components/schemas/NotificationActionType" } ] }, "actors": { "type": "array", "description": "List of users who performed the action that triggered this notification", "items": { "type": "object", "properties": { "username": { "type": "string" }, "avatar": { "type": "string" } } } }, "entity_type": { "type": "string", "description": "The type of entity this notification relates to", "allOf": [ { "$ref": "#/components/schemas/NotificationEntityType" } ] }, "entity": { "type": "object", "description": "The actual entity object this notification relates to (order, offer, etc.)" }, "timestamp": { "type": "string", "format": "date-time", "description": "When the notification was created" } }, "required": [ "read", "notification_id", "action", "actors", "entity_type", "entity", "timestamp" ], "example": { "read": false, "notification_id": "123e4567-e89b-12d3-a456-426614174000", "action": "order_message", "actors": [ { "username": "john_doe", "avatar": "https://example.com/avatar.jpg" } ], "entity_type": "orders", "entity": { "order_id": "456e7890-e89b-12d3-a456-426614174000", "title": "Sample Order" }, "timestamp": "2025-01-22T06:14:41.058Z" } }, "NotificationUpdateBody": { "type": "object", "title": "NotificationUpdateBody", "properties": { "read": { "type": "boolean", "description": "Whether the notification should be marked as read" } }, "required": [ "read" ] }, "NotificationDeleteBody": { "type": "object", "title": "NotificationDeleteBody", "properties": { "notification_ids": { "type": "array", "items": { "type": "string" }, "description": "Array of notification IDs to delete" } }, "required": [ "notification_ids" ] }, "PaginatedNotificationsResponse": { "type": "object", "title": "PaginatedNotificationsResponse", "properties": { "notifications": { "type": "array", "items": { "$ref": "#/components/schemas/Notification" } }, "pagination": { "type": "object", "properties": { "currentPage": { "type": "integer" }, "pageSize": { "type": "integer" }, "total": { "type": "integer" }, "totalPages": { "type": "integer" }, "hasNextPage": { "type": "boolean" }, "hasPreviousPage": { "type": "boolean" } }, "required": [ "currentPage", "pageSize", "total", "totalPages", "hasNextPage", "hasPreviousPage" ] }, "unread_count": { "type": "integer", "description": "Total number of unread notifications matching the current search criteria" } }, "required": [ "notifications", "pagination", "unread_count" ] }, "SuccessResponse": { "type": "object", "title": "SuccessResponse", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" } }, "required": [ "success", "message" ] }, "DeleteMultipleResponse": { "type": "object", "title": "DeleteMultipleResponse", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "deleted_count": { "type": "integer" } }, "required": [ "success", "message", "deleted_count" ] }, "BulkActionResponse": { "type": "object", "title": "BulkActionResponse", "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "affected_count": { "type": "integer" } }, "required": [ "success", "message", "affected_count" ] }, "NotificationBulkUpdateBody": { "type": "object", "title": "NotificationBulkUpdateBody", "properties": { "read": { "type": "boolean", "description": "Whether all notifications should be marked as read" } }, "required": [ "read" ] }, "NotificationActionType": { "type": "string", "title": "NotificationActionType", "description": "Available notification action types for filtering and identification", "enum": [ "order_create", "order_assigned", "order_status_fulfilled", "order_status_in_progress", "order_status_not_started", "order_status_cancelled", "order_comment", "order_review", "order_review_revision_requested", "order_contractor_applied", "public_order_create", "order_message", "offer_create", "counter_offer_create", "offer_message", "market_item_bid", "market_item_offer", "market_bid_accepted", "market_bid_declined", "market_offer_accepted", "market_offer_declined", "contractor_invite", "admin_alert" ], "example": "order_message" }, "NotificationEntityType": { "type": "string", "title": "NotificationEntityType", "description": "Available notification entity types", "enum": [ "orders", "order_reviews", "order_comments", "order_applicants", "offer_sessions", "market_listing", "market_bids", "market_offers", "contractor_invites", "admin_alerts" ], "example": "orders" }, "PushSubscriptionData": { "type": "object", "title": "PushSubscriptionData", "description": "Push subscription data from the browser", "properties": { "endpoint": { "type": "string", "description": "Push service endpoint URL" }, "keys": { "type": "object", "description": "Encryption keys for push notifications", "properties": { "p256dh": { "type": "string", "description": "P-256 ECDH public key (base64 encoded)" }, "auth": { "type": "string", "description": "Authentication secret (base64 encoded)" } }, "required": [ "p256dh", "auth" ] }, "userAgent": { "type": "string", "description": "User agent string (optional)" } }, "required": [ "endpoint", "keys" ] }, "PushSubscriptionResponse": { "type": "object", "title": "PushSubscriptionResponse", "properties": { "subscription_id": { "type": "string", "format": "uuid", "description": "Unique identifier for the subscription" }, "message": { "type": "string", "description": "Success message" } }, "required": [ "subscription_id", "message" ] }, "PushPreference": { "type": "object", "title": "PushPreference", "description": "Push notification preference for a specific action type", "properties": { "action": { "type": "string", "description": "Notification action type (e.g., 'order_create', 'order_message')" }, "enabled": { "type": "boolean", "description": "Whether push notifications are enabled for this action type" } }, "required": [ "action", "enabled" ] }, "PushPreferencesResponse": { "type": "object", "title": "PushPreferencesResponse", "properties": { "preferences": { "type": "array", "description": "Array of push notification preferences", "items": { "$ref": "#/components/schemas/PushPreference" } } }, "required": [ "preferences" ] }, "PushPreferenceUpdateBody": { "type": "object", "title": "PushPreferenceUpdateBody", "description": "Single preference update (for backwards compatibility)", "properties": { "action": { "type": "string", "description": "Notification action type to update" }, "enabled": { "type": "boolean", "description": "Whether to enable or disable push notifications for this action" }, "contractor_id": { "type": "string", "format": "uuid", "nullable": true, "description": "Optional contractor ID for organization-scoped preferences" } }, "required": [ "action", "enabled" ] }, "PushPreferenceUpdateItem": { "type": "object", "title": "PushPreferenceUpdateItem", "properties": { "action": { "type": "string", "description": "Notification action type to update" }, "enabled": { "type": "boolean", "description": "Whether to enable or disable push notifications for this action" }, "contractor_id": { "type": "string", "format": "uuid", "nullable": true, "description": "Optional contractor ID for organization-scoped preferences" } }, "required": [ "action", "enabled" ] }, "PushPreferencesBatchUpdateBody": { "type": "object", "title": "PushPreferencesBatchUpdateBody", "description": "Batch update multiple preferences at once", "properties": { "preferences": { "type": "array", "description": "Array of preferences to update", "items": { "$ref": "#/components/schemas/PushPreferenceUpdateItem" }, "minItems": 1 } }, "required": [ "preferences" ] }, "RecruitingPost": { "type": "object", "title": "RecruitingPost", "properties": { "post_id": { "type": "string", "format": "uuid", "title": "RecruitingPost.post_id" }, "contractor": { "$ref": "#/components/schemas/Contractor", "title": "RecruitingPost.contractor" }, "title": { "type": "string", "maxLength": 200, "title": "RecruitingPost.title" }, "body": { "type": "string", "maxLength": 5000, "title": "RecruitingPost.body" }, "timestamp": { "type": "string", "format": "date-time", "title": "RecruitingPost.timestamp" }, "upvotes": { "type": "integer", "minimum": 0, "title": "RecruitingPost.upvotes" }, "downvotes": { "type": "integer", "minimum": 0, "title": "RecruitingPost.downvotes" } }, "required": [ "post_id", "contractor", "title", "body", "timestamp", "upvotes", "downvotes" ], "additionalProperties": false }, "CreateRecruitingPostRequest": { "type": "object", "title": "CreateRecruitingPostRequest", "properties": { "title": { "type": "string", "maxLength": 200, "minLength": 1, "title": "CreateRecruitingPostRequest.title" }, "body": { "type": "string", "maxLength": 5000, "minLength": 1, "title": "CreateRecruitingPostRequest.body" }, "contractor": { "type": "string", "minLength": 3, "maxLength": 50, "title": "CreateRecruitingPostRequest.contractor" } }, "required": [ "title", "body", "contractor" ], "additionalProperties": false }, "UpdateRecruitingPostRequest": { "type": "object", "title": "UpdateRecruitingPostRequest", "properties": { "title": { "type": "string", "maxLength": 200, "minLength": 1, "title": "UpdateRecruitingPostRequest.title" }, "body": { "type": "string", "maxLength": 5000, "minLength": 1, "title": "UpdateRecruitingPostRequest.body" } }, "required": [ "title", "body" ], "additionalProperties": false }, "RecruitingComment": { "type": "object", "title": "RecruitingComment", "properties": { "comment_id": { "type": "string", "format": "uuid", "title": "RecruitingComment.comment_id" }, "author": { "$ref": "#/components/schemas/MinimalUser", "title": "RecruitingComment.author" }, "content": { "type": "string", "maxLength": 2000, "title": "RecruitingComment.content" }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/RecruitingComment" }, "title": "RecruitingComment.replies" }, "timestamp": { "type": "string", "format": "date-time", "title": "RecruitingComment.timestamp" }, "upvotes": { "type": "integer", "minimum": 0, "title": "RecruitingComment.upvotes" }, "downvotes": { "type": "integer", "minimum": 0, "title": "RecruitingComment.downvotes" }, "deleted": { "type": "boolean", "title": "RecruitingComment.deleted" } }, "required": [ "comment_id", "author", "content", "timestamp", "upvotes", "downvotes", "deleted" ], "additionalProperties": false }, "CreateCommentRequest": { "type": "object", "title": "CreateCommentRequest", "properties": { "content": { "type": "string", "maxLength": 2000, "minLength": 1, "title": "CreateCommentRequest.content" } }, "required": [ "content" ], "additionalProperties": false }, "VoteRequest": { "type": "object", "title": "VoteRequest", "properties": { "vote_type": { "type": "string", "enum": [ "upvote", "downvote" ], "title": "VoteRequest.vote_type" } }, "required": [ "vote_type" ], "additionalProperties": false }, "CommentReplyRequest": { "type": "object", "properties": { "content": { "type": "string", "description": "Comment content" } }, "required": [ "content" ] }, "CommentUpdateRequest": { "type": "object", "properties": { "content": { "type": "string", "description": "Updated comment content" } }, "required": [ "content" ] }, "Comment": { "type": "object", "properties": { "comment_id": { "type": "string" }, "author": { "type": "string" }, "content": { "type": "string" }, "reply_to": { "type": "string", "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "deleted": { "type": "boolean" }, "upvotes": { "type": "number" }, "downvotes": { "type": "number" } }, "required": [ "comment_id", "author", "content", "created_at", "updated_at", "deleted", "upvotes", "downvotes" ] }, "OfferSessionStatus": { "enum": [ "closed", "open" ], "title": "OfferSessionStatus", "type": "string" }, "OfferStatus": { "enum": [ "rejected", "accepted", "counteroffered", "cancelled" ], "title": "OfferStatus", "type": "string" }, "OfferBodyMarketListing": { "properties": { "quantity": { "title": "OfferBodyMarketListing.quantity", "type": "number" }, "listing_id": { "title": "OfferBodyMarketListing.listing_id", "type": "string" } }, "required": [ "quantity", "listing_id" ], "title": "OfferBodyMarketListing", "type": "object" }, "Offer": { "properties": { "id": { "title": "Offer.id", "type": "string" }, "session_id": { "title": "Offer.session_id", "type": "string" }, "actor": { "$ref": "#/components/schemas/MinimalUser", "title": "Offer.actor" }, "kind": { "title": "Offer.kind", "type": "string" }, "cost": { "title": "Offer.cost", "type": "integer", "minimum": 0 }, "title": { "title": "Offer.title", "type": "string", "minLength": 1, "maxLength": 100 }, "description": { "title": "Offer.description", "type": "string", "minLength": 0, "maxLength": 2000 }, "timestamp": { "title": "Offer.timestamp", "type": "string" }, "status": { "$ref": "#/components/schemas/OfferStatus", "title": "Offer.status" }, "collateral": { "title": "Offer.cost", "type": "integer", "minimum": 0, "nullable": true }, "service": { "title": "Offer.service", "$ref": "#/components/schemas/Service", "nullable": true }, "market_listings": { "items": { "$ref": "#/components/schemas/OfferBodyMarketListing", "title": "Offer.market_listings.[]" }, "title": "Offer.market_listings", "type": "array" }, "payment_type": { "title": "Offer.payment_type", "type": "string", "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ] } }, "additionalProperties": false, "title": "Offer", "type": "object" }, "CounterOfferBody": { "properties": { "session_id": { "title": "CounterOfferBody.session_id", "type": "string" }, "title": { "title": "CounterOfferBody.title", "type": "string", "minLength": 1, "maxLength": 100 }, "kind": { "title": "CounterOfferBody.kind", "type": "string" }, "cost": { "title": "CounterOfferBody.cost", "type": "integer", "minimum": 0 }, "description": { "title": "CounterOfferBody.description", "type": "string", "minLength": 0, "maxLength": 2000 }, "timestamp": { "title": "CounterOfferBody.timestamp", "type": "string" }, "service_id": { "type": "string", "title": "CounterOfferBody.status", "nullable": true }, "market_listings": { "items": { "$ref": "#/components/schemas/OfferBodyMarketListing", "title": "CounterOfferBody.market_listings.[]" }, "title": "CounterOfferBody.market_listings", "type": "array" }, "payment_type": { "title": "CounterOfferBody.payment_type", "type": "string", "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ] }, "status": { "type": "string", "enum": [ "counteroffered" ] } }, "additionalProperties": false, "title": "CounterOfferBody", "type": "object" }, "OfferSessionDetails": { "properties": { "id": { "title": "OfferSessionDetails.id", "type": "string" }, "status": { "$ref": "#/components/schemas/OfferSessionStatus", "title": "OfferSessionDetails.status" }, "contractor": { "$ref": "#/components/schemas/MinimalContractor", "title": "OfferSessionDetails.contractor", "nullable": true }, "assigned_to": { "$ref": "#/components/schemas/MinimalUser", "title": "OfferSessionDetails.assigned_to", "nullable": true }, "customer": { "$ref": "#/components/schemas/MinimalUser", "title": "OfferSessionDetails.contractor" }, "discord_thread_id": { "type": "string", "nullable": true }, "discord_server_id": { "type": "string", "nullable": true }, "discord_invite": { "type": "string", "nullable": true }, "contract_id": { "type": "string", "nullable": true }, "order_id": { "type": "string", "nullable": true, "description": "Order ID associated with this offer session when status is 'Accepted'", "example": "123e4567-e89b-12d3-a456-426614174000" }, "offers": { "items": { "$ref": "#/components/schemas/Offer", "title": "OfferSessionDetails.offers.[]" }, "title": "OfferSessionDetails.offers", "type": "array" }, "timestamp": { "title": "OfferSessionDetails.timestamp", "type": "string" } }, "additionalProperties": false, "title": "OfferSessionDetails", "type": "object" }, "OfferStub": { "properties": { "service_name": { "title": "OfferStub.service_name", "type": "string", "nullable": true }, "cost": { "title": "OfferStub.cost", "type": "integer", "minimum": 0 }, "title": { "title": "OfferStub.title", "type": "string", "maxLength": 100 }, "payment_type": { "title": "OfferStub.payment_type", "type": "string", "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ] }, "count": { "title": "OfferStub.count", "type": "integer", "minimum": 0 } }, "additionalProperties": false, "title": "OfferSessionStub", "type": "object" }, "OfferSessionStub": { "properties": { "id": { "title": "OfferSessionStub.id", "type": "string" }, "status": { "$ref": "#/components/schemas/OfferSessionStatus", "title": "OfferSessionStub.status" }, "contractor": { "$ref": "#/components/schemas/MinimalContractor", "title": "OfferSessionDetails.contractor", "nullable": true }, "assigned_to": { "$ref": "#/components/schemas/MinimalUser", "title": "OfferSessionDetails.assigned_to", "nullable": true }, "customer": { "$ref": "#/components/schemas/MinimalUser", "title": "OfferSessionDetails.contractor" }, "most_recent_offer": { "$ref": "#/components/schemas/OfferStub", "title": "OfferSessionDetails.most_recent_offer" }, "timestamp": { "title": "OfferSessionDetails.timestamp", "type": "string" } }, "additionalProperties": false, "title": "OfferSessionStub", "type": "object" }, "ServiceBody": { "properties": { "service_name": { "title": "ServiceBody.service_name", "type": "string", "maxLength": 100 }, "service_description": { "title": "ServiceBody.service_description", "type": "string", "maxLength": 2000 }, "title": { "title": "ServiceBody.title", "type": "string", "maxLength": 100 }, "rush": { "title": "ServiceBody.rush", "type": "boolean" }, "description": { "title": "ServiceBody.description", "type": "string", "maxLength": 2000 }, "kind": { "title": "ServiceBody.kind", "type": "string", "enum": [ "Escort", "Transport", "Construction", "Support", "Resource Acquisition", "Rental", "Custom", "Delivery", "Medical", "Intelligence Services" ] }, "collateral": { "title": "ServiceBody.collateral", "type": "number" }, "departure": { "title": "ServiceBody.departure", "nullable": true, "type": "string" }, "destination": { "title": "ServiceBody.destination", "nullable": true, "type": "string" }, "cost": { "title": "ServiceBody.cost", "type": "number", "minimum": 0 }, "payment_type": { "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ], "title": "ServiceBody.payment_type", "type": "string" }, "contractor": { "title": "ServiceBody.contractor", "nullable": true, "type": "string" }, "status": { "title": "ServiceBody.status", "type": "string", "enum": [ "active", "inactive" ] }, "photos": { "items": { "title": "ServiceBody.photos.[]", "type": "string" }, "title": "ServiceBody.photos", "type": "array", "minLength": 1 } }, "required": [ "service_name", "service_description", "title", "rush", "description", "collateral", "departure", "destination", "cost", "payment_type", "status", "photos" ], "additionalProperties": false, "title": "ServiceBody", "type": "object" }, "PublicContractBody": { "properties": { "title": { "title": "PublicContractBody.title", "type": "string", "maxLength": 100, "minLength": 1 }, "description": { "title": "PublicContractBody.description", "type": "string", "maxLength": 2000 }, "kind": { "enum": [ "Escort", "Transport", "Construction", "Support", "Resource Acquisition", "Rental", "Custom", "Delivery", "Medical", "Intelligence Services" ], "title": "PublicContractBody.kind", "type": "string" }, "collateral": { "title": "PublicContractBody.collateral", "type": "integer", "minimum": 0 }, "departure": { "title": "PublicContractBody.departure", "type": "string", "nullable": true, "maxLength": 30 }, "destination": { "title": "PublicContractBody.destination", "type": "string", "nullable": true, "maxLength": 30 }, "cost": { "title": "PublicContractBody.cost", "type": "integer", "minimum": 0 }, "payment_type": { "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ], "title": "PublicContractBody.payment_type", "type": "string" } }, "required": [ "title", "description", "kind", "collateral", "cost", "payment_type" ], "additionalProperties": false, "title": "PublicContractBody", "type": "object" }, "PublicContractOfferBody": { "properties": { "title": { "title": "PublicContractBody.title", "type": "string", "maxLength": 100, "minLength": 1 }, "description": { "title": "PublicContractBody.description", "type": "string", "maxLength": 2000 }, "kind": { "enum": [ "Escort", "Transport", "Construction", "Support", "Resource Acquisition", "Rental", "Custom", "Delivery", "Medical", "Intelligence Services" ], "title": "PublicContractBody.kind", "type": "string" }, "collateral": { "title": "PublicContractBody.collateral", "type": "integer", "minimum": 0 }, "departure": { "title": "PublicContractBody.departure", "type": "string", "nullable": true, "maxLength": 30 }, "destination": { "title": "PublicContractBody.destination", "type": "string", "nullable": true, "maxLength": 30 }, "cost": { "title": "PublicContractBody.cost", "type": "integer", "minimum": 0 }, "payment_type": { "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ], "title": "PublicContractBody.payment_type", "type": "string" }, "contractor": { "title": "contractor", "type": "string", "description": "The contractor to apply on behalf of" } }, "required": [], "additionalProperties": false, "title": "PublicContractOfferBody", "type": "object" }, "PublicContract": { "properties": { "title": { "title": "PublicContract.title", "type": "string", "maxLength": 100, "minLength": 1 }, "description": { "title": "PublicContract.description", "type": "string", "maxLength": 2000 }, "kind": { "enum": [ "Escort", "Transport", "Construction", "Support", "Resource Acquisition", "Rental", "Custom", "Delivery", "Medical", "Intelligence Services" ], "title": "PublicContract.kind", "type": "string" }, "collateral": { "title": "PublicContract.collateral", "type": "integer", "minimum": 0 }, "departure": { "title": "PublicContract.departure", "type": "string", "nullable": true, "maxLength": 30 }, "destination": { "title": "PublicContract.destination", "type": "string", "nullable": true, "maxLength": 30 }, "cost": { "title": "PublicContract.cost", "type": "integer", "minimum": 0 }, "payment_type": { "enum": [ "one-time", "hourly", "daily", "unit", "box", "scu", "cscu", "mscu" ], "title": "PublicContract.payment_type", "type": "string" }, "customer": { "title": "PublicContract.customer", "$ref": "#/components/schemas/MinimalUser" } }, "required": [ "title", "description", "kind", "collateral", "departure", "destination", "cost", "payment_type", "customer" ], "additionalProperties": false, "title": "PublicContractBody", "type": "object" }, "VariantType": { "description": "Define available variant attributes and validation rules", "properties": { "variant_type_id": { "type": "string" }, "name": { "type": "string" }, "display_name": { "type": "string" }, "description": { "type": "string" }, "affects_pricing": { "type": "boolean" }, "searchable": { "type": "boolean" }, "filterable": { "type": "boolean" }, "value_type": { "type": "string", "enum": [ "integer", "decimal", "string", "enum" ] }, "min_value": { "type": "number", "format": "double" }, "max_value": { "type": "number", "format": "double" }, "allowed_values": { "items": { "type": "string" }, "type": "array" }, "display_order": { "type": "number", "format": "double" }, "icon": { "type": "string" }, "created_at": { "type": "string", "format": "date-time" } }, "required": [ "variant_type_id", "name", "display_name", "affects_pricing", "searchable", "filterable", "value_type", "display_order", "created_at" ], "type": "object", "additionalProperties": false }, "VariantTypesResponse": { "description": "Variant types list response", "properties": { "variant_types": { "items": { "$ref": "#/components/schemas/VariantType" }, "type": "array" } }, "required": [ "variant_types" ], "type": "object", "additionalProperties": false }, "VariantTypeResponse": { "description": "Single variant type response", "properties": { "variant_type": { "$ref": "#/components/schemas/VariantType" } }, "required": [ "variant_type" ], "type": "object", "additionalProperties": false }, "SearchListingsResponse": { "description": "Search results with pagination", "properties": { "listings": { "items": { "properties": { "created_at": { "type": "string", "format": "date-time" }, "variant_count": { "type": "number", "format": "double" }, "quality_tier_max": { "type": "number", "format": "double" }, "quality_tier_min": { "type": "number", "format": "double" }, "quantity_available": { "type": "number", "format": "double" }, "price_max": { "type": "number", "format": "double" }, "price_min": { "type": "number", "format": "double" }, "seller_rating": { "type": "number", "format": "double" }, "seller_name": { "type": "string" }, "title": { "type": "string" }, "listing_id": { "type": "string" } }, "required": [ "created_at", "variant_count", "quality_tier_max", "quality_tier_min", "quantity_available", "price_max", "price_min", "seller_rating", "seller_name", "title", "listing_id" ], "type": "object" }, "type": "array" }, "total": { "type": "number", "format": "double" }, "page": { "type": "number", "format": "double" }, "page_size": { "type": "number", "format": "double" } }, "required": [ "listings", "total", "page", "page_size" ], "type": "object", "additionalProperties": false }, "Listing": { "description": "Unified listing table (replaces V1's 3-table structure)", "properties": { "listing_id": { "type": "string" }, "seller_id": { "type": "string" }, "seller_type": { "type": "string", "enum": [ "user", "contractor" ] }, "title": { "type": "string" }, "description": { "type": "string" }, "status": { "type": "string", "enum": [ "active", "sold", "expired", "cancelled" ] }, "visibility": { "type": "string", "enum": [ "public", "private", "unlisted" ] }, "sale_type": { "type": "string", "enum": [ "fixed", "auction", "negotiable" ] }, "listing_type": { "type": "string", "enum": [ "single", "bundle", "bulk" ] }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "expires_at": { "type": "string", "format": "date-time" } }, "required": [ "listing_id", "seller_id", "seller_type", "title", "description", "status", "visibility", "sale_type", "listing_type", "created_at", "updated_at" ], "type": "object", "additionalProperties": false }, "VariantAttributes": { "description": "Variant attributes structure", "properties": { "quality_tier": { "type": "number", "format": "double" }, "quality_value": { "type": "number", "format": "double" }, "crafted_source": { "type": "string", "enum": [ "crafted", "store", "looted", "unknown" ] }, "blueprint_tier": { "type": "number", "format": "double" } }, "type": "object", "additionalProperties": {} }, "CreateListingRequest": { "description": "Create new listing with variants", "properties": { "title": { "type": "string" }, "description": { "type": "string" }, "game_item_id": { "type": "string" }, "pricing_mode": { "type": "string", "enum": [ "unified", "per_variant" ] }, "base_price": { "type": "number", "format": "double" }, "lots": { "items": { "properties": { "price": { "type": "number", "format": "double" }, "location_id": { "type": "string" }, "variant_attributes": { "$ref": "#/components/schemas/VariantAttributes" }, "quantity": { "type": "number", "format": "double" } }, "required": [ "variant_attributes", "quantity" ], "type": "object" }, "type": "array" } }, "required": [ "title", "description", "game_item_id", "pricing_mode", "lots" ], "type": "object", "additionalProperties": false }, "Record_string.any_": { "properties": {}, "additionalProperties": {}, "type": "object", "description": "Construct a type with a set of properties K of type T" }, "ListingDetailResponse": { "description": "Listing detail with variant breakdown", "properties": { "listing": { "$ref": "#/components/schemas/Listing" }, "seller": { "properties": { "rating": { "type": "number", "format": "double" }, "type": { "type": "string", "enum": [ "user", "contractor" ] }, "name": { "type": "string" }, "id": { "type": "string" } }, "required": [ "rating", "type", "name", "id" ], "type": "object" }, "items": { "items": { "properties": { "variants": { "items": { "properties": { "locations": { "items": { "type": "string" }, "type": "array" }, "price": { "type": "number", "format": "double" }, "quantity": { "type": "number", "format": "double" }, "short_name": { "type": "string" }, "display_name": { "type": "string" }, "attributes": { "$ref": "#/components/schemas/Record_string.any_" }, "variant_id": { "type": "string" } }, "required": [ "price", "quantity", "short_name", "display_name", "attributes", "variant_id" ], "type": "object" }, "type": "array" }, "base_price": { "type": "number", "format": "double" }, "pricing_mode": { "type": "string", "enum": [ "unified", "per_variant" ] }, "game_item": { "properties": { "icon_url": { "type": "string" }, "type": { "type": "string" }, "name": { "type": "string" }, "game_item_id": { "type": "string" } }, "required": [ "type", "name", "game_item_id" ], "type": "object" }, "item_id": { "type": "string" } }, "required": [ "variants", "pricing_mode", "game_item", "item_id" ], "type": "object" }, "type": "array" } }, "required": [ "listing", "seller", "items" ], "type": "object", "additionalProperties": false }, "HealthResponse": { "properties": { "status": { "type": "string" }, "version": { "type": "string" }, "timestamp": { "type": "string" } }, "required": [ "status", "version", "timestamp" ], "type": "object", "additionalProperties": false } }, "examples": {}, "headers": {}, "parameters": {}, "requestBodies": {}, "responses": {}, "securitySchemes": {} }, "servers": [ { "url": "https://api.sc-market.space", "description": "Prod Env" }, { "url": "http://localhost", "description": "Dev Env" } ] }