{ "openapi": "3.1.0", "info": { "title": "TrailBase", "description": "TrailBase APIs", "license": { "name": "OSL-3.0", "identifier": "OSL-3.0" }, "version": "0.2.0" }, "paths": { "/api/auth/v1/avatar/": { "post": { "tags": ["auth"], "operationId": "create_avatar_handler", "responses": { "200": { "description": "Deletion success" } } }, "delete": { "tags": ["auth"], "operationId": "delete_avatar_handler", "responses": { "200": { "description": "Deletion success" } } } }, "/api/auth/v1/avatar/:b64_user_id": { "get": { "tags": ["auth"], "operationId": "get_avatar_handler", "responses": { "200": { "description": "Optional Avatar file" } } } }, "/api/auth/v1/change_email/confirm/:email_verification_code": { "get": { "tags": ["auth"], "summary": "Confirm a change of email address.", "operationId": "change_email_confirm_handler", "responses": { "200": { "description": "Success." } } } }, "/api/auth/v1/change_email/request": { "post": { "tags": ["auth"], "summary": "Request an email change.", "operationId": "change_email_request_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChangeEmailRequest" } } }, "required": true }, "responses": { "200": { "description": "Success." } } } }, "/api/auth/v1/change_password": { "post": { "tags": ["auth"], "summary": "Request a change of password.", "operationId": "change_password_handler", "parameters": [ { "name": "redirect_uri", "in": "query", "required": false, "schema": { "type": ["string", "null"] } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChangePasswordRequest" } } }, "required": true }, "responses": { "200": { "description": "Success." } } } }, "/api/auth/v1/delete": { "delete": { "tags": ["auth"], "summary": "Get public profile of the given user.", "operationId": "delete_handler", "responses": { "200": { "description": "User deleted." } } } }, "/api/auth/v1/login": { "post": { "tags": ["auth"], "summary": "Log in users by email and password.", "operationId": "login_handler", "parameters": [ { "name": "redirect_uri", "in": "query", "required": false, "schema": { "type": ["string", "null"] } }, { "name": "response_type", "in": "query", "required": false, "schema": { "type": ["string", "null"] } }, { "name": "pkce_code_challenge", "in": "query", "required": false, "schema": { "type": ["string", "null"] } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } }, "required": true }, "responses": { "200": { "description": "Auth & refresh tokens.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginResponse" } } } } } } }, "/api/auth/v1/logout": { "get": { "tags": ["auth"], "summary": "Logs out the current user and delete **all** pending sessions for that user.", "description": "Relies on the client to drop any auth tokens. We delete the session to avoid refresh tokens\nbringing a logged out session back to live.", "operationId": "logout_handler", "parameters": [ { "name": "redirect_uri", "in": "query", "required": false, "schema": { "type": ["string", "null"] } } ], "responses": { "200": { "description": "Auth & refresh tokens." } } }, "post": { "tags": ["auth"], "summary": "Logs out the current user and deletes the specific session for the given refresh token.", "description": "Relies on the client to drop any auth tokens.", "operationId": "post_logout_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LogoutRequest" } } }, "required": true }, "responses": { "200": { "description": "Auth & refresh tokens." } } } }, "/api/auth/v1/oauth/providers": { "get": { "tags": ["oauth"], "summary": "List configured OAuth providers.", "operationId": "list_configured_providers_handler", "responses": { "200": { "description": "List of OAuth providers.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConfiguredOAuthProvidersResponse" } } } } } } }, "/api/auth/v1/oauth/{provider}/callback": { "get": { "tags": ["oauth"], "summary": "This handler receives the ?code=<>&state=<>, uses it to get an external oauth token, gets the\nuser's information, creates a new local user if needed, and finally mints our own tokens.", "operationId": "callback_from_external_auth_provider", "parameters": [ { "name": "code", "in": "query", "required": true, "schema": { "type": "string" } }, { "name": "state", "in": "query", "required": true, "schema": { "type": "string" } }, { "name": "provider", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Redirect." } } } }, "/api/auth/v1/oauth/{provider}/login": { "get": { "tags": ["oauth"], "summary": "Log in via external OAuth provider.", "operationId": "login_with_external_auth_provider", "parameters": [ { "name": "redirect_uri", "in": "query", "required": false, "schema": { "type": ["string", "null"] } }, { "name": "response_type", "in": "query", "required": false, "schema": { "type": ["string", "null"] } }, { "name": "pkce_code_challenge", "in": "query", "required": false, "schema": { "type": ["string", "null"] } }, { "name": "provider", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Redirect." } } } }, "/api/auth/v1/refresh": { "post": { "tags": ["auth"], "summary": "Refreshes auth tokens given a refresh token.", "description": "NOTE: This is a json-only API, since cookies will be auto-refreshed.", "operationId": "refresh_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefreshRequest" } } }, "required": true }, "responses": { "200": { "description": "Refreshed auth tokens.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefreshResponse" } } } } } } }, "/api/auth/v1/register": { "post": { "tags": ["auth"], "summary": "Registers a new user with email and password.", "operationId": "register_user_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterUserRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful registration." } } } }, "/api/auth/v1/reset_password/request": { "post": { "tags": ["auth"], "summary": "Request a password reset.", "operationId": "reset_password_request_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResetPasswordRequest" } } }, "required": true }, "responses": { "200": { "description": "Success." } } } }, "/api/auth/v1/reset_password/update/:password_reset_code": { "post": { "tags": ["auth"], "summary": "Endpoint for setting a new password after the user has requested a reset and provided a\nreplacement password.", "operationId": "reset_password_update_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResetPasswordUpdateRequest" } } }, "required": true }, "responses": { "200": { "description": "Success." } } } }, "/api/auth/v1/status": { "get": { "tags": ["auth"], "summary": "Check login status.", "operationId": "login_status_handler", "responses": { "200": { "description": "Auth & refresh tokens.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginStatusResponse" } } } } } } }, "/api/auth/v1/token": { "post": { "tags": ["auth"], "summary": "Exchange authorization code for auth tokens.", "description": "This API endpoint is meant for client-side applications (SPA, mobile, desktop, ...) using the\nweb-auth flow.", "operationId": "auth_code_to_token_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthCodeToTokenRequest" } } }, "required": true }, "responses": { "200": { "description": "Converts auth & pkce codes to tokens.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenResponse" } } } } } } }, "/api/auth/v1/verify_email/confirm/:email_verification_code": { "get": { "tags": ["auth"], "summary": "Request a new email to verify email address.", "operationId": "verify_email_handler", "responses": { "200": { "description": "Email verified." } } } }, "/api/auth/v1/verify_email/trigger": { "get": { "tags": ["auth"], "summary": "Request a new email to verify email address.", "operationId": "request_email_verification_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmailVerificationRequest" } } }, "required": true }, "responses": { "200": { "description": "Email verification sent." } } } }, "/api/records/v1/{name}": { "get": { "tags": ["records"], "summary": "Lists records matching the given filters", "operationId": "list_records_handler", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Matching records." } } }, "post": { "tags": ["records"], "summary": "Create new record.", "operationId": "create_record_handler", "parameters": [ { "name": "redirect_uri", "in": "query", "description": "Redirect user to this address upon successful record creation.\nThis only exists to support insertions via static HTML form actions.\n\nWe may want to have a different on-error redirect to better support the static HTML use-case.", "required": false, "schema": { "type": ["string", "null"] } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": {} } }, "required": true }, "responses": { "200": { "description": "Ids of successfully created records.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateRecordResponse" } } } } } } }, "/api/records/v1/{name}/schema": { "get": { "tags": ["records"], "summary": "Retrieve json schema associated with given record api.", "operationId": "json_schema_handler", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "JSON schema." } } } }, "/api/records/v1/{name}/subscribe/{record}": { "get": { "tags": ["records"], "summary": "Read record.", "operationId": "add_subscription_sse_handler", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "record", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "SSE stream of record changes." } } } }, "/api/records/v1/{name}/{record}": { "get": { "tags": ["records"], "summary": "Read record.", "operationId": "read_record_handler", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "record", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Record contents.", "content": { "application/json": { "schema": {} } } } } }, "delete": { "tags": ["records"], "summary": "Delete record.", "operationId": "delete_record_handler", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "record", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Successful deletion." } } }, "patch": { "tags": ["records"], "summary": "Update existing record.", "operationId": "update_record_handler", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "record", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": {} } }, "required": true }, "responses": { "200": { "description": "Successful update." } } } }, "/api/records/v1/{name}/{record}/file/{column_name}": { "get": { "tags": ["records"], "summary": "Read file associated with record.", "description": "You may prefer using the more general \"files\" (plural) handler below. Since using unique\nfilenames does help with the content lifecycle, such as caching.", "operationId": "get_uploaded_file_from_record_handler", "responses": { "200": { "description": "File contents." } } } }, "/api/records/v1/{name}/{record}/files/{column_name}/{file_name}": { "get": { "tags": ["records"], "summary": "Read single file from list associated with record.", "operationId": "get_uploaded_files_from_record_handler", "responses": { "200": { "description": "File contents." } } } } }, "components": { "schemas": { "AuthCodeToTokenRequest": { "type": "object", "properties": { "authorization_code": { "type": ["string", "null"] }, "pkce_code_verifier": { "type": ["string", "null"] } } }, "ChangeEmailRequest": { "type": "object", "required": ["csrf_token", "new_email"], "properties": { "csrf_token": { "type": "string" }, "new_email": { "type": "string" }, "old_email": { "type": ["string", "null"] } } }, "ChangePasswordRequest": { "type": "object", "required": ["old_password", "new_password", "new_password_repeat"], "properties": { "new_password": { "type": "string" }, "new_password_repeat": { "type": "string" }, "old_password": { "type": "string" } } }, "ConfiguredOAuthProvidersResponse": { "type": "object", "required": ["providers"], "properties": { "providers": { "type": "array", "items": { "type": "array", "items": false, "prefixItems": [ { "type": "string" }, { "type": "string" } ] }, "description": "List of tuples (, )." } } }, "CreateRecordResponse": { "type": "object", "required": ["ids"], "properties": { "ids": { "type": "array", "items": { "type": "string" }, "description": "Url-Safe base64 encoded ids of the newly created record." } } }, "EmailVerificationRequest": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string" } } }, "LoginRequest": { "type": "object", "required": ["email", "password"], "properties": { "email": { "type": "string" }, "password": { "type": "string" }, "pkce_code_challenge": { "type": ["string", "null"] }, "redirect_uri": { "type": ["string", "null"] }, "response_type": { "type": ["string", "null"] } } }, "LoginResponse": { "type": "object", "required": ["auth_token", "refresh_token", "csrf_token"], "properties": { "auth_token": { "type": "string" }, "csrf_token": { "type": "string" }, "refresh_token": { "type": "string" } } }, "LoginStatusResponse": { "type": "object", "properties": { "auth_token": { "type": ["string", "null"] }, "csrf_token": { "type": ["string", "null"] }, "refresh_token": { "type": ["string", "null"] } } }, "LogoutRequest": { "type": "object", "required": ["refresh_token"], "properties": { "refresh_token": { "type": "string" } } }, "RefreshRequest": { "type": "object", "required": ["refresh_token"], "properties": { "refresh_token": { "type": "string" } } }, "RefreshResponse": { "type": "object", "required": ["auth_token", "csrf_token"], "properties": { "auth_token": { "type": "string" }, "csrf_token": { "type": "string" } } }, "RegisterUserRequest": { "type": "object", "required": ["email", "password", "password_repeat"], "properties": { "email": { "type": "string" }, "password": { "type": "string" }, "password_repeat": { "type": "string" } } }, "ResetPasswordRequest": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string" } } }, "ResetPasswordUpdateRequest": { "type": "object", "required": ["password", "password_repeat", "password_reset_code"], "properties": { "password": { "type": "string" }, "password_repeat": { "type": "string" }, "password_reset_code": { "type": "string" }, "redirect_uri": { "type": ["string", "null"] } } }, "TokenResponse": { "type": "object", "required": ["auth_token", "refresh_token", "csrf_token"], "properties": { "auth_token": { "type": "string" }, "csrf_token": { "type": "string" }, "refresh_token": { "type": "string" } } } } }, "tags": [ { "name": "auth", "description": "Auth-related APIs" } ] }