basePath: / definitions: authn.AdminCreateUserRequest: properties: email: example: jane@example.com type: string name: example: Jane Doe type: string password: example: Secret123! type: string role: description: 'Role allowed values: "user" or "admin"' enum: - user - admin example: user type: string type: object authn.AdminUpdateUserRequest: properties: email: example: jane@example.com type: string name: example: Jane Doe type: string password: example: NewSecret123! type: string role: enum: - user - admin example: admin type: string type: object authn.AuthClaimsDTO: properties: aud: items: type: string type: array exp: type: integer iat: type: integer iss: type: string nbf: type: integer orgs: items: type: string type: array roles: items: type: string type: array sub: type: string type: object authn.ListUsersOut: properties: page: type: integer page_size: type: integer total: type: integer users: items: $ref: '#/definitions/authn.UserListItem' type: array type: object authn.LoginInput: properties: email: example: me@here.com type: string password: example: "123456" type: string type: object authn.MeResponse: properties: claims: $ref: '#/definitions/authn.AuthClaimsDTO' org_role: type: string organization_id: type: string user_id: $ref: '#/definitions/authn.UserDTO' type: object authn.RegisterInput: properties: email: example: me@here.com type: string name: example: My Name type: string password: example: "123456" type: string type: object authn.UserDTO: properties: created_at: type: string email: type: string email_verified: type: boolean id: type: string name: type: string role: $ref: '#/definitions/models.Role' updated_at: type: string type: object authn.UserListItem: properties: created_at: {} email: type: string email_verified: type: boolean id: {} name: type: string role: type: string updated_at: {} type: object authn.userOut: properties: created_at: {} email: type: string email_verified: type: boolean id: {} name: type: string role: type: string updated_at: {} type: object models.Member: properties: created_at: type: string id: type: string organization: $ref: '#/definitions/models.Organization' organization_id: type: string role: allOf: - $ref: '#/definitions/models.MemberRole' description: e.g. admin, member updated_at: type: string user: $ref: '#/definitions/models.User' user_id: type: string type: object models.MemberRole: enum: - admin - member - user type: string x-enum-varnames: - MemberRoleAdmin - MemberRoleMember - MemberRoleUser models.Organization: properties: created_at: type: string id: type: string logo: type: string metadata: type: string name: type: string slug: type: string updated_at: type: string type: object models.Role: enum: - admin - user type: string x-enum-varnames: - RoleAdmin - RoleUser models.User: properties: created_at: type: string email: type: string email_verified: type: boolean email_verified_at: type: string id: type: string name: type: string password: type: string role: $ref: '#/definitions/models.Role' updated_at: type: string type: object orgs.InviteInput: properties: email: type: string role: type: string type: object orgs.OrgInput: properties: name: type: string slug: type: string type: object servers.createServerRequest: properties: hostname: type: string ip_address: type: string role: example: master|worker|bastion type: string ssh_key_id: type: string ssh_user: type: string status: example: pending|provisioning|ready|failed type: string type: object servers.serverResponse: properties: created_at: type: string hostname: type: string id: type: string ip_address: type: string organization_id: type: string role: type: string ssh_key_id: type: string ssh_user: type: string status: type: string updated_at: type: string type: object servers.updateServerRequest: properties: hostname: type: string ip_address: type: string role: example: master|worker|bastion type: string ssh_key_id: type: string ssh_user: type: string status: description: 'enum: pending,provisioning,ready,failed' example: pending|provisioning|ready|failed type: string type: object ssh.createSSHRequest: properties: bits: example: 4096 type: integer comment: example: deploy@autoglue type: string download: example: both type: string name: type: string type: object ssh.sshResponse: properties: created_at: type: string fingerprint: type: string id: type: string name: type: string organization_id: type: string public_keys: type: string updated_at: type: string type: object ssh.sshRevealResponse: properties: created_at: type: string fingerprint: type: string id: type: string name: type: string organization_id: type: string private_key: type: string public_keys: type: string updated_at: type: string type: object info: contact: {} description: API for managing K3s clusters across cloud providers title: AutoGlue API version: "1.0" paths: /api/healthz: get: consumes: - application/json description: Returns a 200 if the service is up produces: - text/plain responses: "200": description: ok schema: type: string summary: Basic health check tags: - health /api/v1/admin/users: get: description: Returns paginated list of users (admin only) parameters: - description: Page number (1-based) in: query name: page type: integer - description: Page size (max 200) in: query name: page_size type: integer produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/authn.ListUsersOut' "401": description: unauthorized schema: type: string "403": description: forbidden schema: type: string security: - BearerAuth: [] summary: 'Admin: list all users' tags: - admin post: consumes: - application/json parameters: - description: payload in: body name: body required: true schema: $ref: '#/definitions/authn.AdminCreateUserRequest' produces: - application/json responses: "201": description: Created schema: $ref: '#/definitions/authn.userOut' "400": description: bad request schema: type: string "401": description: unauthorized schema: type: string "403": description: forbidden schema: type: string "409": description: conflict schema: type: string security: - BearerAuth: [] summary: 'Admin: create user' tags: - admin /api/v1/admin/users/{userId}: delete: parameters: - description: User ID in: path name: userId required: true type: string responses: "204": description: no content schema: type: string "400": description: bad request schema: type: string "401": description: unauthorized schema: type: string "403": description: forbidden schema: type: string "404": description: not found schema: type: string "409": description: conflict schema: type: string security: - BearerAuth: [] summary: 'Admin: delete user' tags: - admin patch: consumes: - application/json parameters: - description: User ID in: path name: userId required: true type: string - description: payload in: body name: body required: true schema: $ref: '#/definitions/authn.AdminUpdateUserRequest' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/authn.userOut' "400": description: bad request schema: type: string "401": description: unauthorized schema: type: string "403": description: forbidden schema: type: string "404": description: not found schema: type: string "409": description: conflict schema: type: string security: - BearerAuth: [] summary: 'Admin: update user' tags: - admin /api/v1/auth/introspect: post: consumes: - application/json description: Returns whether the token is active and basic metadata parameters: - description: token in: body name: body required: true schema: additionalProperties: type: string type: object produces: - application/json responses: "200": description: OK schema: additionalProperties: true type: object summary: Introspect a token tags: - auth /api/v1/auth/login: post: consumes: - application/json description: Authenticates a user and returns a JWT bearer token parameters: - description: User login input in: body name: body required: true schema: $ref: '#/definitions/authn.LoginInput' produces: - application/json responses: "200": description: token schema: additionalProperties: type: string type: object "401": description: unauthorized schema: type: string summary: Authenticate and return a token tags: - auth /api/v1/auth/logout: post: consumes: - application/json description: Revoke a refresh token parameters: - description: refresh_token in: body name: body required: true schema: additionalProperties: type: string type: object produces: - application/json responses: "204": description: no content schema: type: string security: - BearerAuth: [] summary: Logout user tags: - auth /api/v1/auth/logout_all: post: description: Revokes all active refresh tokens for the authenticated user produces: - text/plain responses: "204": description: no content schema: type: string security: - BearerAuth: [] summary: Logout from all sessions tags: - auth /api/v1/auth/me: get: description: Returns the authenticated user's profile and auth context produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/authn.MeResponse' "401": description: unauthorized schema: type: string security: - BearerAuth: [] summary: Get authenticated user info tags: - auth /api/v1/auth/password/change: post: consumes: - application/json description: Changes the password for the authenticated user parameters: - description: current_password, new_password in: body name: body required: true schema: additionalProperties: type: string type: object produces: - text/plain responses: "204": description: no content schema: type: string "400": description: bad request schema: type: string security: - BearerAuth: [] summary: Change password tags: - auth /api/v1/auth/password/forgot: post: consumes: - application/json description: Sends a reset token to the user's email address parameters: - description: email in: body name: body required: true schema: additionalProperties: type: string type: object produces: - text/plain responses: "204": description: no content schema: type: string summary: Request password reset tags: - auth /api/v1/auth/password/reset: post: consumes: - application/json description: Resets the password using a valid reset token parameters: - description: token, new_password in: body name: body required: true schema: additionalProperties: type: string type: object produces: - text/plain responses: "204": description: no content schema: type: string "400": description: bad request schema: type: string summary: Confirm password reset tags: - auth /api/v1/auth/refresh: post: consumes: - application/json description: Use a refresh token to obtain a new access token parameters: - description: refresh_token in: body name: body required: true schema: additionalProperties: type: string type: object produces: - application/json responses: "200": description: new access token schema: additionalProperties: type: string type: object "401": description: unauthorized schema: type: string security: - BearerAuth: [] summary: Refresh access token tags: - auth /api/v1/auth/refresh/rotate: post: consumes: - application/json description: Exchanges a valid refresh token for a new access and refresh token, revoking the old one parameters: - description: refresh_token in: body name: body required: true schema: additionalProperties: type: string type: object produces: - application/json responses: "200": description: access_token, refresh_token schema: additionalProperties: type: string type: object "401": description: unauthorized schema: type: string security: - BearerAuth: [] summary: Rotate refresh token tags: - auth /api/v1/auth/register: post: consumes: - application/json description: Registers a new user and stores credentials parameters: - description: User registration input in: body name: body required: true schema: $ref: '#/definitions/authn.RegisterInput' produces: - application/json responses: "201": description: created schema: type: string "400": description: bad request schema: type: string summary: Register a new user tags: - auth /api/v1/auth/verify: get: description: Verifies the user's email using a token (often from an emailed link) parameters: - description: verification token in: query name: token required: true type: string produces: - text/plain responses: "204": description: no content schema: type: string "400": description: bad request schema: type: string summary: Verify email address tags: - auth /api/v1/auth/verify/resend: post: consumes: - application/json description: Sends a new email verification token if needed parameters: - description: email in: body name: body required: true schema: additionalProperties: type: string type: object produces: - text/plain responses: "204": description: no content schema: type: string summary: Resend email verification tags: - auth /api/v1/orgs: get: produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/models.Organization' type: array "401": description: unauthorized schema: type: string security: - BearerAuth: [] summary: List organizations for user tags: - organizations post: consumes: - application/json description: Creates a new organization and assigns the authenticated user as an admin member parameters: - description: Optional organization context (ignored for creation) in: header name: X-Org-ID type: string - description: Organization Input in: body name: body required: true schema: $ref: '#/definitions/orgs.OrgInput' produces: - application/json responses: "200": description: organization_id schema: additionalProperties: type: string type: object "400": description: invalid input schema: type: string "401": description: unauthorized schema: type: string "500": description: internal error schema: type: string security: - BearerAuth: [] summary: Create a new organization tags: - organizations /api/v1/orgs/{orgId}: delete: parameters: - description: Organization ID in: path name: orgId required: true type: string responses: "204": description: deleted schema: type: string "403": description: forbidden schema: type: string security: - BearerAuth: [] summary: Delete organization tags: - organizations patch: consumes: - application/json parameters: - description: Org ID in: path name: orgId required: true type: string - description: Organization data in: body name: body required: true schema: $ref: '#/definitions/orgs.OrgInput' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/models.Organization' "403": description: forbidden schema: type: string security: - BearerAuth: [] summary: Update organization metadata tags: - organizations /api/v1/orgs/invite: post: consumes: - application/json parameters: - description: Invite input in: body name: body required: true schema: $ref: '#/definitions/orgs.InviteInput' - description: Organization context in: header name: X-Org-ID required: true type: string produces: - text/plain responses: "201": description: invited schema: type: string "400": description: bad request schema: type: string "403": description: forbidden schema: type: string security: - BearerAuth: [] summary: Invite user to organization tags: - organizations /api/v1/orgs/members: get: description: Returns a list of all members in the current organization parameters: - description: Organization context in: header name: X-Org-ID required: true type: string produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/models.Member' type: array "401": description: unauthorized schema: type: string security: - BearerAuth: [] summary: List organization members tags: - organizations /api/v1/orgs/members/{userId}: delete: parameters: - description: User ID in: path name: userId required: true type: string responses: "204": description: deleted schema: type: string "403": description: forbidden schema: type: string security: - BearerAuth: [] summary: Remove member from organization tags: - organizations /api/v1/servers: get: consumes: - application/json description: 'Returns servers for the organization in X-Org-ID. Optional filters: status, role.' parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: Filter by status (pending|provisioning|ready|failed) in: query name: status type: string - description: Filter by role in: query name: role type: string produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/servers.serverResponse' type: array "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "500": description: failed to list servers schema: type: string security: - BearerAuth: [] summary: List servers (org scoped) tags: - servers post: consumes: - application/json description: Creates a server bound to the org in X-Org-ID. Validates that ssh_key_id belongs to the org. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: Server payload in: body name: body required: true schema: $ref: '#/definitions/servers.createServerRequest' produces: - application/json responses: "201": description: Created schema: $ref: '#/definitions/servers.serverResponse' "400": description: invalid json / missing fields / invalid status / invalid ssh_key_id schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "500": description: create failed schema: type: string security: - BearerAuth: [] summary: Create server (org scoped) tags: - servers /api/v1/servers/{id}: delete: consumes: - application/json description: Permanently deletes the server. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: Server ID (UUID) in: path name: id required: true type: string produces: - application/json responses: "204": description: No Content schema: type: string "400": description: invalid id schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "500": description: delete failed schema: type: string security: - BearerAuth: [] summary: Delete server (org scoped) tags: - servers get: consumes: - application/json description: Returns one server in the given organization. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: Server ID (UUID) in: path name: id required: true type: string produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/servers.serverResponse' "400": description: invalid id schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "404": description: not found schema: type: string "500": description: fetch failed schema: type: string security: - BearerAuth: [] summary: Get server by ID (org scoped) tags: - servers patch: consumes: - application/json description: Partially update fields; changing ssh_key_id validates ownership. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: Server ID (UUID) in: path name: id required: true type: string - description: Fields to update in: body name: body required: true schema: $ref: '#/definitions/servers.updateServerRequest' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/servers.serverResponse' "400": description: invalid id / invalid json / invalid status / invalid ssh_key_id schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "404": description: not found schema: type: string "500": description: update failed schema: type: string security: - BearerAuth: [] summary: Update server (org scoped) tags: - servers /api/v1/ssh: get: consumes: - application/json description: Returns ssh keys for the organization in X-Org-ID. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string produces: - application/json responses: "200": description: OK schema: items: $ref: '#/definitions/ssh.sshResponse' type: array "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "500": description: failed to list keys schema: type: string security: - BearerAuth: [] summary: List ssh keys (org scoped) tags: - ssh post: consumes: - application/json description: Generates an RSA keypair, saves it, and returns metadata. Optionally set `download` to "public", "private", or "both" to download files immediately. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: Key generation options in: body name: body required: true schema: $ref: '#/definitions/ssh.createSSHRequest' produces: - application/json responses: "201": description: Created headers: Content-Disposition: description: When download is requested type: string schema: $ref: '#/definitions/ssh.sshResponse' "400": description: invalid json / invalid bits schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "500": description: generation/create failed schema: type: string security: - BearerAuth: [] summary: Create ssh keypair (org scoped) tags: - ssh /api/v1/ssh/{id}: delete: consumes: - application/json description: Permanently deletes a keypair. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: SSH Key ID (UUID) in: path name: id required: true type: string produces: - application/json responses: "204": description: No Content schema: type: string "400": description: invalid id schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "500": description: delete failed schema: type: string security: - BearerAuth: [] summary: Delete ssh keypair (org scoped) tags: - ssh get: consumes: - application/json description: Returns public key fields. Append `?reveal=true` to include the private key PEM. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: SSH Key ID (UUID) in: path name: id required: true type: string - description: Reveal private key PEM in: query name: reveal type: boolean produces: - application/json responses: "200": description: When reveal=true schema: $ref: '#/definitions/ssh.sshRevealResponse' "400": description: invalid id schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "404": description: not found schema: type: string "500": description: fetch failed schema: type: string security: - BearerAuth: [] summary: Get ssh key by ID (org scoped) tags: - ssh /api/v1/ssh/{id}/download: get: description: Download `part=public|private|both` of the keypair. `both` returns a zip file. parameters: - description: Organization UUID in: header name: X-Org-ID required: true type: string - description: SSH Key ID (UUID) in: path name: id required: true type: string - description: Which part to download enum: - public - private - both in: query name: part required: true type: string produces: - text/plain responses: "200": description: file content schema: type: string "400": description: invalid id / invalid part schema: type: string "401": description: Unauthorized schema: type: string "403": description: organization required schema: type: string "404": description: not found schema: type: string "500": description: download failed schema: type: string security: - BearerAuth: [] summary: Download ssh key files by ID (org scoped) tags: - ssh schemes: - http securityDefinitions: BearerAuth: in: header name: Authorization type: apiKey swagger: "2.0"