openapi: 3.0.0 info: title: shebang.run API version: 1.0.0 description: | REST API for shebang.run - a platform for hosting and sharing shell scripts with versioning, encryption, and signing. ## Authentication Two authentication methods are supported: 1. **JWT Token** - For web UI and temporary access - Header: `Authorization: Bearer ` - Obtain via `/api/auth/login` or `/api/auth/register` 2. **API Token** - For CLI and programmatic access - Header: `Authorization: Basic ` - Generate via web UI Account page or `/api/account/tokens` contact: email: hello@shebang.run license: name: MIT url: https://github.com/skibare87/shebangrun/blob/main/LICENSE servers: - url: https://shebang.run description: Production server - url: http://localhost:8080 description: Local development tags: - name: Authentication description: User authentication and OAuth - name: Scripts description: Script management and retrieval - name: Keys description: RSA keypair management - name: Secrets description: Encrypted key-value secrets store - name: Files description: File upload and management - name: Folders description: Folder organization and hierarchy - name: Sharing description: File, folder, and script access control - name: AI description: AI script generation (Ultimate tier) - name: Account description: Account settings and API tokens - name: Admin description: Administrative functions - name: Community description: Public script discovery components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT BasicAuth: type: http scheme: basic description: Use Client ID as username and Client Secret as password schemas: Script: type: object properties: id: type: integer name: type: string description: type: string visibility: type: string enum: [private, unlisted, public] version: type: integer encrypted: type: boolean created_at: type: string format: date-time updated_at: type: string format: date-time KeyPair: type: object properties: id: type: integer name: type: string public_key: type: string created_at: type: string format: date-time User: type: object properties: id: type: integer username: type: string email: type: string is_admin: type: boolean rate_limit: type: integer created_at: type: string format: date-time APIToken: type: object properties: id: type: integer name: type: string client_id: type: string client_secret: type: string description: Only shown on creation created_at: type: string format: date-time last_used: type: string format: date-time paths: # Authentication /api/auth/register: post: tags: [Authentication] summary: Register new user requestBody: required: true content: application/json: schema: type: object required: [username, email, password] properties: username: type: string email: type: string password: type: string responses: '200': description: Registration successful content: application/json: schema: type: object properties: token: type: string user: $ref: '#/components/schemas/User' /api/auth/login: post: tags: [Authentication] summary: Login with username and password requestBody: required: true content: application/json: schema: type: object required: [username, password] properties: username: type: string password: type: string responses: '200': description: Login successful content: application/json: schema: type: object properties: token: type: string user: $ref: '#/components/schemas/User' /api/auth/oauth/{provider}: get: tags: [Authentication] summary: OAuth login parameters: - name: provider in: path required: true schema: type: string enum: [github, google] responses: '307': description: Redirect to OAuth provider # Scripts /api/scripts: get: tags: [Scripts] summary: List user's scripts security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: List of scripts content: application/json: schema: type: array items: $ref: '#/components/schemas/Script' post: tags: [Scripts] summary: Create new script security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name, content, visibility] properties: name: type: string content: type: string description: type: string visibility: type: string enum: [private, unlisted, public] keypair_id: type: integer description: Required for private scripts responses: '201': description: Script created content: application/json: schema: $ref: '#/components/schemas/Script' /api/scripts/{id}: get: tags: [Scripts] summary: Get script details security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Script details content: application/json: schema: $ref: '#/components/schemas/Script' put: tags: [Scripts] summary: Update script (creates new version) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: content: application/json: schema: type: object properties: content: type: string description: type: string visibility: type: string enum: [private, unlisted, public] keypair_id: type: integer tag: type: string enum: [dev, beta] responses: '200': description: Script updated delete: tags: [Scripts] summary: Delete script security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '204': description: Script deleted /{username}/{script}: get: tags: [Scripts] summary: Retrieve script content parameters: - name: username in: path required: true schema: type: string - name: script in: path required: true schema: type: string description: Script name with optional version tag (@v1, @latest, @dev) - name: token in: query schema: type: string description: Share token for private scripts responses: '200': description: Script content headers: X-Script-Version: schema: type: string X-Script-Checksum: schema: type: string X-Encrypted: schema: type: string description: "true" if encrypted X-Wrapped-Key: schema: type: string description: Hex-encoded wrapped encryption key content: text/plain: schema: type: string application/octet-stream: schema: type: string format: binary /{username}/{script}/meta: get: tags: [Scripts] summary: Get script metadata parameters: - name: username in: path required: true schema: type: string - name: script in: path required: true schema: type: string responses: '200': description: Script metadata content: application/json: schema: type: object properties: name: type: string description: type: string visibility: type: string version: type: integer checksum: type: string size: type: integer created_at: type: string updated_at: type: string # Keys /api/keys: get: tags: [Keys] summary: List keypairs security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: List of keypairs content: application/json: schema: type: array items: $ref: '#/components/schemas/KeyPair' /api/keys/generate: post: tags: [Keys] summary: Generate new RSA-4096 keypair security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: '200': description: Keypair generated content: application/json: schema: type: object properties: id: type: integer name: type: string public_key: type: string private_key: type: string description: Only shown once - save it! /api/keys/{id}: delete: tags: [Keys] summary: Delete keypair security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '204': description: Keypair deleted # Account /api/account/tokens: get: tags: [Account] summary: List API tokens security: - BearerAuth: [] responses: '200': description: List of API tokens content: application/json: schema: type: array items: $ref: '#/components/schemas/APIToken' post: tags: [Account] summary: Create API token security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: '200': description: Token created content: application/json: schema: $ref: '#/components/schemas/APIToken' /api/account/tokens/{id}: delete: tags: [Account] summary: Delete API token security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '204': description: Token deleted /api/account/password: put: tags: [Account] summary: Change password security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: application/json: schema: type: object required: [current_password, new_password] properties: current_password: type: string new_password: type: string responses: '200': description: Password changed /api/account/export: get: tags: [Account] summary: Export all user data (GDPR) security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: User data export content: application/json: schema: type: object /api/account: delete: tags: [Account] summary: Delete account permanently security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Account deleted # Community /api/community/scripts: get: tags: [Community] summary: List public scripts from all users security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: List of public scripts content: application/json: schema: type: array items: type: object properties: id: type: integer name: type: string username: type: string description: type: string version: type: integer updated_at: type: string # Admin /api/admin/users: get: tags: [Admin] summary: List all users (admin only) security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: List of users content: application/json: schema: type: array items: $ref: '#/components/schemas/User' /api/admin/users/{id}/limits: put: tags: [Admin] summary: Set user limits and role (admin only) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: content: application/json: schema: type: object properties: is_admin: type: boolean rate_limit: type: integer max_scripts: type: integer max_script_size: type: integer responses: '200': description: Limits updated /api/admin/users/{id}/password: put: tags: [Admin] summary: Reset user password (admin only) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: type: object required: [new_password] properties: new_password: type: string responses: '200': description: Password reset /api/admin/users/{id}: delete: tags: [Admin] summary: Delete user (admin only) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: User deleted # Secrets Management /api/secrets: get: tags: [Secrets] summary: List user's secrets security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: List of secrets post: tags: [Secrets] summary: Create or update a secret security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: application/json: schema: type: object required: [key_name, value] properties: key_name: type: string value: type: string expires_at: type: string format: date-time responses: '201': description: Secret created /api/secrets/{name}/value: get: tags: [Secrets] summary: Get secret value security: - BearerAuth: [] - BasicAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Secret value content: application/json: schema: type: object properties: value: type: string /api/secrets/{name}: delete: tags: [Secrets] summary: Delete a secret security: - BearerAuth: [] - BasicAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '204': description: Secret deleted /api/secrets/{name}/audit: get: tags: [Secrets] summary: Get secret audit log security: - BearerAuth: [] - BasicAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Audit log entries # Script Sharing /api/scripts/{id}/access: get: tags: [Sharing] summary: List script access control security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Access list post: tags: [Sharing] summary: Add users or enable link sharing security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: type: object required: [access_type] properties: access_type: type: string enum: [link, user] usernames: type: array items: type: string responses: '201': description: Access added /api/scripts/{id}/access/{access_id}: delete: tags: [Sharing] summary: Remove access security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer - name: access_id in: path required: true schema: type: integer responses: '204': description: Access removed /api/shared/scripts: get: tags: [Sharing] summary: List scripts shared with you security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Shared scripts /api/users/search: get: tags: [Sharing] summary: Search users for sharing security: - BearerAuth: [] - BasicAuth: [] parameters: - name: q in: query required: true schema: type: string responses: '200': description: Matching usernames # AI Generation /api/ai/generate: post: tags: [AI] summary: Generate script with AI (Ultimate tier) security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: application/json: schema: type: object required: [prompt] properties: prompt: type: string args: type: array items: type: string provider: type: string enum: [bedrock, claude, openai] responses: '200': description: Generated script content: application/json: schema: type: object properties: script: type: string provider: type: string model: type: string tokens: type: integer /api/ai/usage: get: tags: [AI] summary: Get AI generation usage stats security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Usage statistics content: application/json: schema: type: object properties: used: type: integer limit: type: integer unlimited: type: boolean /api/account/tier: get: tags: [Account] summary: Get current tier information security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Tier information /api/admin/tiers: get: tags: [Admin] summary: List all tiers (admin only) security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: List of tiers /api/auth/check-username: get: tags: [Authentication] summary: Check if username is available parameters: - name: username in: query required: true schema: type: string responses: '200': description: Availability status content: application/json: schema: type: object properties: available: type: boolean /api/auth/set-username: post: tags: [Authentication] summary: Set username for OAuth users security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [username] properties: username: type: string responses: '200': description: Username set, returns new token # File Management /api/files/upload: post: tags: [Files] summary: Upload a file security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary folder_id: type: integer visibility: type: string enum: [public, unlisted, private] responses: '201': description: File uploaded (or replaced/versioned if duplicate) /api/files: get: tags: [Files] summary: List user's files security: - BearerAuth: [] - BasicAuth: [] parameters: - name: folder_id in: query schema: type: integer responses: '200': description: List of files /api/files/storage: get: tags: [Files] summary: Get file storage usage security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Storage usage content: application/json: schema: type: object properties: used: type: integer limit: type: integer /api/files/{id}: get: tags: [Files] summary: Get file metadata security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: File metadata put: tags: [Files] summary: Update file metadata security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: type: object properties: original_filename: type: string folder_id: type: integer nullable: true visibility: type: string responses: '200': description: File updated delete: tags: [Files] summary: Delete file security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '204': description: File deleted /api/files/{id}/download: get: tags: [Files] summary: Download file security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: File content /api/files/{id}/versions: get: tags: [Files] summary: List file versions (Ultimate tier) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: List of versions /api/files/{id}/versions/{version}: get: tags: [Files] summary: Download specific version security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer - name: version in: path required: true schema: type: integer responses: '200': description: Version content delete: tags: [Files] summary: Delete specific version security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer - name: version in: path required: true schema: type: integer responses: '200': description: Version deleted /api/files/{id}/restore/{version}: post: tags: [Files] summary: Restore old version (creates new version) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer - name: version in: path required: true schema: type: integer responses: '200': description: Version restored /api/files/{id}/access: get: tags: [Files] summary: List file access control security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Access list post: tags: [Files] summary: Add file access security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: type: object required: [access_type] properties: access_type: type: string enum: [link, user] usernames: type: array items: type: string responses: '201': description: Access added /api/files/{id}/access/{accessId}: delete: tags: [Files] summary: Remove file access security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer - name: accessId in: path required: true schema: type: integer responses: '204': description: Access removed /api/folders: post: tags: [Folders] summary: Create folder security: - BearerAuth: [] - BasicAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string parent_id: type: integer responses: '201': description: Folder created get: tags: [Folders] summary: List folders security: - BearerAuth: [] - BasicAuth: [] parameters: - name: parent_id in: query schema: type: integer responses: '200': description: List of folders /api/folders/{id}: delete: tags: [Folders] summary: Delete folder security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '204': description: Folder deleted /api/folders/{id}/contents: get: tags: [Folders] summary: Get folder contents (handles shared access) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Folder contents content: application/json: schema: type: object properties: folders: type: array files: type: array /api/folders/{id}/access: get: tags: [Folders] summary: List folder access control security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Access list post: tags: [Folders] summary: Add folder access (shares folder and all contents) security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: type: object required: [access_type] properties: access_type: type: string enum: [link, user] usernames: type: array items: type: string responses: '201': description: Access added /api/folders/{id}/access/{accessId}: delete: tags: [Folders] summary: Remove folder access security: - BearerAuth: [] - BasicAuth: [] parameters: - name: id in: path required: true schema: type: integer - name: accessId in: path required: true schema: type: integer responses: '204': description: Access removed /api/shared/files: get: tags: [Sharing] summary: List files shared with you security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Shared files /api/shared/folders: get: tags: [Sharing] summary: List folders shared with you security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Shared folders /api/shared/with-me: get: tags: [Sharing] summary: Get all shared items grouped by owner security: - BearerAuth: [] - BasicAuth: [] responses: '200': description: Shared items with owner grouping