openapi: 3.1.0 info: title: Arcfire API version: "0.0.0" description: | Public and administrative endpoints exposed by the Arcfire media server. All routes are served from the same origin as the web client. Runtime security is handled via bearer tokens (`Authorization: Bearer `) or the `auth_token` HTTP-only cookie set by the OpenID Connect login flow. license: name: MIT url: https://opensource.org/licenses/MIT servers: - url: http://localhost:3000 description: Local development server security: - bearerAuth: [] - cookieAuth: [] tags: - name: System description: Service level endpoints that do not require authentication. - name: Auth - name: Discover - name: Requests - name: Stream - name: Admin paths: /health: get: tags: [System] summary: Check service health description: Lightweight readiness probe used by load balancers and monitoring. operationId: getHealth security: [] responses: '200': description: Service is healthy content: application/json: schema: type: object properties: status: type: string example: ok uptime: type: number format: float version: type: string node: type: string time: type: string format: date-time '500': description: Service is unhealthy content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/auth/login: get: tags: [Auth] summary: Begin OIDC login description: Initiates the OpenID Connect authorization code flow and redirects to the upstream identity provider. operationId: beginLogin parameters: - in: query name: remember schema: type: string description: Optional duration string that controls the session lifetime (e.g. `7d`). - in: query name: redirect schema: type: string description: Optional URL to redirect the user to once the login completes. security: [] responses: '302': description: Redirect to the OIDC authorization endpoint '500': description: OIDC login cannot be started content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/auth/callback: get: tags: [Auth] summary: Complete OIDC callback description: Handles the authorization code returned by the identity provider, issues a session cookie, and redirects back to the client. operationId: completeLogin parameters: - in: query name: code schema: type: string required: true description: Authorization code issued by the identity provider. - in: query name: state schema: type: string required: true description: CSRF protection token that must match the stored cookie. security: [] responses: '302': description: Redirect to the original destination or site root '400': description: Invalid state or authorization code content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Login could not be completed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/auth/me: get: tags: [Auth] summary: Get the current user profile operationId: getCurrentUser responses: '200': description: Authenticated user details content: application/json: schema: $ref: '#/components/schemas/User' '401': description: No valid session content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/auth/logout: get: tags: [Auth] summary: Terminate the active session operationId: logout responses: '302': description: Session cleared and browser redirected to the site root '500': description: Logout failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/auth/token: get: tags: [Auth] summary: Inspect the active API token operationId: getToken responses: '200': description: Token retrieved successfully content: application/json: schema: $ref: '#/components/schemas/AuthTokenResponse' '401': description: Token is invalid or expired content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: No session token cookie was found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/discover: get: tags: [Discover] summary: List visible media operationId: listMedia responses: '200': description: Media collection available to the user content: application/json: schema: type: array items: $ref: '#/components/schemas/MediaItem' /api/discover/{mediaId}: get: tags: [Discover] summary: Get media details operationId: getMedia parameters: - name: mediaId in: path required: true schema: type: string responses: '200': description: Media record including seasons and movies content: application/json: schema: $ref: '#/components/schemas/MediaWithLibrary' '404': description: Media item not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/discover/{mediaId}/{libraryId}: get: tags: [Discover] summary: Get a library item operationId: getLibraryItem parameters: - name: mediaId in: path required: true schema: type: string - name: libraryId in: path required: true schema: type: string responses: '200': description: Library item with optional episode metadata content: application/json: schema: $ref: '#/components/schemas/LibraryItemWithEpisodes' '404': description: Library item not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/requests: get: tags: [Requests] summary: Get cached trending content operationId: getTrending responses: '200': description: Cached trending payload sourced from TMDB and Rotten Tomatoes. content: application/json: schema: $ref: '#/components/schemas/TrendingResponse' post: tags: [Requests] summary: Submit a new media request operationId: createRequest requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RequestCreate' responses: '200': description: Request accepted content: application/json: schema: type: object properties: message: type: string example: Request received id: type: string '400': description: Invalid request payload content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: User is not authenticated content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Server error when creating request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/requests/my: get: tags: [Requests] summary: List the caller's requests operationId: listMyRequests parameters: - in: query name: offset schema: type: integer minimum: 0 description: Page offset (50 items per page). responses: '200': description: Requests created by the current user content: application/json: schema: type: array items: $ref: '#/components/schemas/Request' '401': description: Caller is not authenticated content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/requests/search: get: tags: [Requests] summary: Search TMDB for movies, shows, or people operationId: searchTmdb parameters: - in: query name: q required: true schema: type: string description: Free text search term forwarded to TMDB. responses: '200': description: TMDB search results filtered to exclude people content: application/json: schema: type: object properties: results: type: object description: Raw TMDB search response. additionalProperties: true '400': description: Missing query parameter content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/requests/tv/{id}: get: tags: [Requests] summary: Fetch extended TV information operationId: getTvDetails parameters: - name: id in: path required: true schema: type: string responses: '200': description: Combined TMDB data and local metadata content: application/json: schema: $ref: '#/components/schemas/TvDetailsResponse' '400': description: Missing TV id content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Failed to fetch details content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/requests/movie/{id}: get: tags: [Requests] summary: Fetch extended movie information operationId: getMovieDetails parameters: - name: id in: path required: true schema: type: string responses: '200': description: Combined TMDB data and local metadata content: application/json: schema: $ref: '#/components/schemas/MovieDetailsResponse' '400': description: Missing movie id content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Failed to fetch details content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/requests/{id}: delete: tags: [Requests] summary: Cancel a pending request operationId: deleteRequest parameters: - name: id in: path required: true schema: type: string responses: '200': description: Request cancelled content: application/json: schema: type: object properties: message: type: string example: Request canceled '400': description: Request cannot be cancelled content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Caller is not authenticated content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Attempt to cancel another user's request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Request not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Cancellation failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/stream/{libraryId}: get: tags: [Stream] summary: Retrieve library metadata for playback operationId: getStreamLibraryItem parameters: - name: libraryId in: path required: true schema: type: string responses: '200': description: Library item metadata content: application/json: schema: $ref: '#/components/schemas/LibraryItem' '404': description: Library item not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' post: tags: [Stream] summary: Start a new on-demand stream operationId: startStream parameters: - name: libraryId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/StreamStartRequest' responses: '200': description: Stream initialized and encoder kicked off content: application/json: schema: type: object properties: message: $ref: '#/components/schemas/StreamSessionSummary' streamId: type: string playlist: type: string description: Relative URL to the generated HLS playlist '400': description: Request body missing required properties content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Caller is not authenticated content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Library item could not be located content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Stream initialization failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/stream/byStream/{streamId}/hls.m3u8: get: tags: [Stream] summary: Retrieve the generated HLS playlist operationId: getHlsPlaylist parameters: - name: streamId in: path required: true schema: type: string responses: '200': description: M3U8 playlist content: application/vnd.apple.mpegurl: schema: type: string '401': description: Caller is not authenticated content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Playlist not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '503': description: Stream is not ready yet content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/stream/byStream/{streamId}/{segment}: get: tags: [Stream] summary: Retrieve an encoded HLS segment operationId: getHlsSegment parameters: - name: streamId in: path required: true schema: type: string - name: segment in: path required: true schema: type: string responses: '200': description: Transport stream segment content: video/mp2t: schema: type: string format: binary '400': description: Invalid segment name content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Caller is not authenticated content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Segment not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/requests: get: tags: [Admin] summary: List all requests (50 per page) operationId: adminListRequests parameters: - in: query name: page schema: type: integer minimum: 0 description: Page index for pagination. responses: '200': description: Requests ordered by creation time content: application/json: schema: type: array items: $ref: '#/components/schemas/Request' /api/admin/requests/deny/{id}: post: tags: [Admin] summary: Deny a request operationId: adminDenyRequest parameters: - name: id in: path required: true schema: type: string responses: '200': description: Request marked as denied content: application/json: schema: $ref: '#/components/schemas/Request' '404': description: Request not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Update failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/requests/approve/{id}: post: tags: [Admin] summary: Approve a request operationId: adminApproveRequest parameters: - name: id in: path required: true schema: type: string responses: '200': description: Request marked as approved content: application/json: schema: $ref: '#/components/schemas/Request' '404': description: Request not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Update failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/users: get: tags: [Admin] summary: List all users operationId: adminListUsers responses: '200': description: User directory content: application/json: schema: type: array items: $ref: '#/components/schemas/User' /api/admin/tasks: get: tags: [Admin] summary: Inspect recurring task statuses operationId: adminListTasks responses: '200': description: Current scheduler state content: application/json: schema: type: array items: $ref: '#/components/schemas/TaskStatus' /api/admin/tasks/{taskName}: post: tags: [Admin] summary: Control a scheduled task operationId: adminControlTask parameters: - name: taskName in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TaskActionRequest' responses: '200': description: Command accepted content: application/json: schema: type: object properties: message: type: string '400': description: Invalid action or task state content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/import/sonarr: post: tags: [Admin] summary: Trigger Sonarr import workflows operationId: adminSonarrImport requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SonarrImportRequest' responses: '200': description: Import started content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '400': description: Invalid input parameters content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Import command failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/media: get: tags: [Admin] summary: List all media including hidden items operationId: adminListMedia responses: '200': description: Full media catalog content: application/json: schema: type: array items: $ref: '#/components/schemas/MediaItem' /api/admin/media/{mediaId}/images: get: tags: [Admin] summary: Fetch TMDB imagery for a media item operationId: adminGetMediaImages parameters: - name: mediaId in: path required: true schema: type: string responses: '200': description: TMDB imagery payload content: application/json: schema: type: object additionalProperties: true '404': description: Media not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' post: tags: [Admin] summary: Save media artwork operationId: adminSaveMediaImage parameters: - name: mediaId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MediaImageSelection' responses: '200': description: Image persisted to disk content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '400': description: Missing type or url content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Media not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Image download failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/media/{mediaId}/season/{seasonNumber}/images: get: tags: [Admin] summary: Fetch TMDB season imagery operationId: adminGetSeasonImages parameters: - name: mediaId in: path required: true schema: type: string - name: seasonNumber in: path required: true schema: type: integer responses: '200': description: TMDB season imagery payload content: application/json: schema: type: object additionalProperties: true '400': description: Media is not a series content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Media not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' post: tags: [Admin] summary: Save season artwork operationId: adminSaveSeasonImage parameters: - name: mediaId in: path required: true schema: type: string - name: seasonNumber in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ImageUrlRequest' responses: '200': description: Season poster downloaded content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '400': description: Missing URL or invalid parameters content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Media or season not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Image download failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/media/{mediaId}/season/{seasonNumber}/episode/{episodeNumber}/images: get: tags: [Admin] summary: Fetch TMDB episode imagery operationId: adminGetEpisodeImages parameters: - name: mediaId in: path required: true schema: type: string - name: seasonNumber in: path required: true schema: type: integer - name: episodeNumber in: path required: true schema: type: integer responses: '200': description: TMDB episode imagery payload content: application/json: schema: type: object additionalProperties: true '400': description: Media is not a series content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Media not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' post: tags: [Admin] summary: Save episode artwork operationId: adminSaveEpisodeImage parameters: - name: mediaId in: path required: true schema: type: string - name: seasonNumber in: path required: true schema: type: integer - name: episodeNumber in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ImageUrlRequest' responses: '200': description: Episode still downloaded content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '400': description: Missing URL or invalid parameters content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Media or season not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Image download failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/database/stats: get: tags: [Admin] summary: Database statistics operationId: adminDatabaseStats responses: '200': description: Aggregate metrics about the database content: application/json: schema: $ref: '#/components/schemas/DatabaseStats' /api/admin/database/table: get: tags: [Admin] summary: List available tables operationId: adminDatabaseTables responses: '200': description: Table names content: application/json: schema: type: array items: type: string /api/admin/database/table/{tableName}: get: tags: [Admin] summary: Describe a table operationId: adminDescribeTable parameters: - name: tableName in: path required: true schema: type: string responses: '200': description: Column metadata content: application/json: schema: type: object additionalProperties: $ref: '#/components/schemas/TableColumn' '500': description: Unable to describe table content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' post: tags: [Admin] summary: Insert a new row operationId: adminInsertRow parameters: - name: tableName in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object additionalProperties: true responses: '200': description: Row inserted content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '500': description: Insert failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/database/table/{tableName}/data: get: tags: [Admin] summary: Read table data operationId: adminGetTableData parameters: - name: tableName in: path required: true schema: type: string responses: '200': description: Rows stored in the table content: application/json: schema: type: array items: type: object additionalProperties: true '500': description: Unable to fetch data content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/admin/database/table/{tableName}/{id}: put: tags: [Admin] summary: Update a row operationId: adminUpdateRow parameters: - name: tableName in: path required: true schema: type: string - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object additionalProperties: true responses: '200': description: Row updated content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '500': description: Update failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' delete: tags: [Admin] summary: Delete a row operationId: adminDeleteRow parameters: - name: tableName in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: Row deleted content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '500': description: Delete failed content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: UUID cookieAuth: type: apiKey in: cookie name: auth_token schemas: ErrorResponse: type: object properties: error: type: string message: type: string required: - error User: type: object properties: id: type: string username: type: string display_name: type: [string, 'null'] email: type: [string, 'null'] role: type: string description: Either `user` or `admin`. required: - id - username - role AuthTokenResponse: type: object properties: token: type: string expires_at: type: [string, 'null'] format: date-time MediaItem: type: object properties: id: type: string name: type: string type: type: string enum: [movie, series] sub_type: type: [string, 'null'] overview: type: [string, 'null'] genres: type: array items: type: string parental_rating: type: [string, 'null'] ratings: type: object additionalProperties: true metadata: type: object additionalProperties: true tmdb_id: type: integer tvdb_id: type: [integer, 'null'] imdb_id: type: [string, 'null'] arr_id: type: [integer, 'null'] hidden: type: boolean required: - id - name - type - tmdb_id SeasonItem: type: object properties: id: type: string media_id: type: string type: type: string enum: [season] name: type: string season_number: type: integer overview: type: [string, 'null'] metadata: type: object additionalProperties: true hidden: type: boolean required: - id - media_id - type - name - season_number EpisodeItem: type: object properties: id: type: string media_id: type: string season_id: type: string type: type: string enum: [episode] name: type: string season_number: type: integer episode_number: type: integer overview: type: [string, 'null'] metadata: type: object additionalProperties: true hidden: type: boolean required: - id - media_id - season_id - type - name - season_number - episode_number LibraryItem: type: object properties: id: type: string media_id: type: string season_id: type: [string, 'null'] type: type: string enum: [episode, movie, season] name: type: string season_number: type: [integer, 'null'] episode_number: type: [integer, 'null'] overview: type: [string, 'null'] metadata: type: object additionalProperties: true hidden: type: boolean required: - id - media_id - type - name LibraryItemWithEpisodes: allOf: - $ref: '#/components/schemas/LibraryItem' - type: object properties: episodes: type: [array, 'null'] items: $ref: '#/components/schemas/EpisodeItem' MediaWithLibrary: allOf: - $ref: '#/components/schemas/MediaItem' - type: object properties: seasons: type: array items: $ref: '#/components/schemas/SeasonItem' movies: type: array items: $ref: '#/components/schemas/LibraryItem' Request: type: object properties: id: type: string tmdb_id: type: integer type: type: string enum: [movie, series] sub_type: type: [string, 'null'] seasons: type: array items: type: integer default: [] status: type: string requester_id: type: string media_data: type: object properties: title: type: string year: type: [integer, 'null'] poster_path: type: [string, 'null'] backdrop_path: type: [string, 'null'] overview: type: [string, 'null'] required: - id - tmdb_id - type - status - requester_id - media_data RequestCreate: type: object additionalProperties: false properties: tmdb_id: type: integer type: type: string enum: [movie, series] sub_type: type: [string, 'null'] seasons: type: array items: type: integer description: Required when requesting a series. image_paths: type: object properties: poster_path: type: [string, 'null'] backdrop_path: type: [string, 'null'] title: type: string overview: type: [string, 'null'] required: - tmdb_id - type TrendingItem: type: object properties: id: type: integer title: type: [string, 'null'] name: type: [string, 'null'] media_type: type: string overview: type: [string, 'null'] poster_path: type: [string, 'null'] backdrop_path: type: [string, 'null'] vote_average: type: [number, 'null'] format: float vote_count: type: [integer, 'null'] popularity: type: [number, 'null'] format: float release_date: type: [string, 'null'] first_air_date: type: [string, 'null'] genre_ids: type: array items: type: integer additionalProperties: true TrendingResponse: type: object properties: trendingShows: type: array items: $ref: '#/components/schemas/TrendingItem' trendingMovies: type: array items: $ref: '#/components/schemas/TrendingItem' trendingAnime: type: array items: $ref: '#/components/schemas/TrendingItem' TvDetailsResponse: type: object properties: details: type: object additionalProperties: true credits: type: [object, 'null'] additionalProperties: true recommendations: type: array items: type: object additionalProperties: true similar: type: array items: type: object additionalProperties: true score: type: [object, 'null'] additionalProperties: true localdata: type: [object, 'null'] additionalProperties: true keywords: type: array items: type: object additionalProperties: true MovieDetailsResponse: type: object properties: details: type: object additionalProperties: true credits: type: [object, 'null'] additionalProperties: true recommendations: type: array items: type: object additionalProperties: true similar: type: array items: type: object additionalProperties: true score: type: [object, 'null'] additionalProperties: true localdata: type: [object, 'null'] additionalProperties: true keywords: type: array items: type: object additionalProperties: true StreamStartRequest: type: object properties: options: type: object description: Playback capabilities and preferred qualities reported by the client player. additionalProperties: true supportedCodecs: type: array description: Video/audio codec identifiers supported by the client. items: type: string required: - options - supportedCodecs StreamSessionSummary: type: object properties: id: type: string video_streams: type: array items: type: object additionalProperties: true TaskStatus: type: object properties: name: type: string interval: type: string enabled: type: boolean lastRun: type: [string, 'null'] format: date-time nextRun: type: [string, 'null'] format: date-time running: type: boolean TaskActionRequest: type: object properties: action: type: string enum: [run, enable, disable] required: - action SonarrImportRequest: type: object properties: seriesId: type: integer seasonNumber: type: [integer, 'null'] episodeNumber: type: [integer, 'null'] type: type: string enum: [season, episode, series, all] required: - seriesId - type MediaImageSelection: type: object properties: type: type: string enum: [poster, backdrop, logo] url: type: string format: uri required: - type - url ImageUrlRequest: type: object properties: url: type: string format: uri required: - url GenericSuccess: type: object properties: ok: type: boolean example: true message: type: [string, 'null'] result: type: [object, 'null'] additionalProperties: true path: type: [string, 'null'] DatabaseStats: type: object properties: userCount: type: [integer, 'null'] mediaCount: type: [integer, 'null'] requestCount: type: [integer, 'null'] activeRequests: type: [integer, 'null'] completedRequests: type: [integer, 'null'] userTokens: type: [integer, 'null'] TableColumn: type: object properties: type: type: string allowNull: type: boolean defaultValue: type: [string, number, boolean, object, 'null'] primaryKey: type: boolean autoIncrement: type: [boolean, 'null'] additionalProperties: true