{"note":"OpenAPI conversion -- returning structured metadata","name":"valtown","description":"Val Town API","version":"1","base_url":"https://api.val.town","endpoints":52,"raw":"@lap v0.3\n# Machine-readable API spec. Each @endpoint block is one API call.\n@api Val Town API\n@base https://api.val.town\n@version 1\n@auth Bearer bearer\n@endpoints 52\n@hint download_for_search\n@toc alias(2), me(2), blob(8), users(1), sqlite(2), email(1), telemetry(2), vals(20), files(1), orgs(2), connections(2), val(1), environment-variable-groups(8)\n\n@group alias\n@endpoint GET /v1/alias/{username}\n@desc Get basic details about a user, given their username\n@required {username: str # Username of the user who you are looking for}\n@returns(200) {id: str(uuid), type: any, bio: any, username: any, profileImageUrl: any, url: str(uri), links: map{self: str(uri)}} # User object\n\n@endgroup\n\n@group me\n@endpoint GET /v1/me\n@desc Get profile information for the current user\n@returns(200) Your user information, with tier and email included\n\n@endgroup\n\n@group blob\n@endpoint GET /v1/blob\n@desc List blobs in your account\n@optional {prefix: str # If specified, only include blobs that start with this string}\n@returns(200) List of blobs that you’ve stored\n\n@endpoint GET /v1/blob/{key}\n@desc Get a blob’s contents.\n@required {key: str # Key that uniquely identifies this blob}\n@returns(200) Binary contents of the returned file\n\n@endpoint POST /v1/blob/{key}\n@desc Store data in blob storage\n@required {key: str # Key that uniquely identifies this blob}\n@returns(201) Default Response\n@errors {400: Default Response}\n\n@endpoint DELETE /v1/blob/{key}\n@desc Delete a blob\n@required {key: str # Key that uniquely identifies this blob}\n@returns(204) Blob successfully deleted\n\n@endgroup\n\n@group users\n@endpoint GET /v1/users/{user_id}\n@desc Get basic information about a user\n@required {user_id: str(uuid) # User Id}\n@returns(200) {id: str(uuid), type: any, bio: any, username: any, profileImageUrl: any, url: str(uri), links: map{self: str(uri)}} # User object\n\n@endgroup\n\n@group sqlite\n@endpoint POST /v1/sqlite/execute\n@desc Execute a single SQLite statement and return results\n@required {statement: any}\n@returns(200) {columns: [str], columnTypes: [str], rows: [[any]], rowsAffected: num, lastInsertRowid: any} # Result of executing an SQL statement.\n@example_request {\"statement\":\"SELECT 1;\"}\n\n@endpoint POST /v1/sqlite/batch\n@desc Execute a batch of SQLite statements and return results for all of them\n@required {statements: [any]}\n@optional {mode: any(write/read/deferred)}\n@returns(200) Array of results from the statements executed\n@example_request {\"statements\":[\"SELECT 1;\"],\"mode\":\"read\"}\n\n@endgroup\n\n@group email\n@endpoint POST /v1/email\n@desc Send emails\n@optional {subject: str # The subject line of the email, from: any, headers: map # A set of headers to include the email that you send, to: any # A single email or list of emails for one of the address fields, cc: any # A single email or list of emails for one of the address fields, bcc: any # A single email or list of emails for one of the address fields, text: str # Text content of the email, for email clients that may not support HTML, html: str # HTML content of the email. Can be specified alongside text, attachments: [map{content!: str, filename!: str, type: str, disposition: str, contentId: str}] # A list of attachments to add to the email, replyToList: any # A reply-to list of email addresses}\n@returns(202) {message: str} # Email accepted to be sent\n@errors {500: Default Response}\n@example_request {\"subject\":\"An important message\",\"text\":\"Hello world\",\"html\":\"Hello <strong>world</strong>\"}\n\n@endgroup\n\n@group telemetry\n@endpoint GET /v1/telemetry/traces\n@desc Get OpenTelemetry traces within a specified time window with flexible pagination options: Pass in only the end time to paginate backwards from there. Pass in a start time to paginate backwards from now until the start time. Pass in both to get resources within the time window. Choose to return in end_time order instead to view traces that completed in a window or since a time. Filter additionally by branch_ids or file_id.\n@required {direction: any(asc/desc)=desc # Sort direction for the traces. Defaults to descending order of timestamp., limit: int=20 # Maximum items to return in each paginated response}\n@optional {file_id: str(uuid) # Include only resources from a given file identified by its ID, branch_ids: [str(uuid)] # Branch IDs to filter by, start: str(date-time) # Start date of the time window (earliest time), end: str(date-time) # End date of the time window (latest time), order_by: any(start_time/end_time)=start_time # When set to end_time, traces are sorted by their end time, and pending traces are omitted. When set to start_time, all traces are included, with pending traces given \"0\" for their end time.}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint GET /v1/telemetry/logs\n@desc Get OpenTelemetry logs within a specified time window with flexible pagination options: Pass in only the end time to paginate backwards from there. Pass in a start time to paginate backwards from now until the start time. Pass in both to get resources within the time window. Filter additionally by branch_ids or file_id.\n@required {direction: any(asc/desc)=desc # Sort direction for the traces. Defaults to descending order of timestamp., limit: int=20 # Maximum items to return in each paginated response}\n@optional {trace_ids: [str], file_id: str(uuid) # Include only resources from a given file identified by its ID, branch_ids: [str(uuid)] # Branch IDs to filter by, start: str(date-time) # Start date of the time window (earliest time), end: str(date-time) # End date of the time window (latest time)}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endgroup\n\n@group vals\n@endpoint GET /v2/vals/{val_id}/environment_variables/\n@desc List environment variables defined in this project. This only includes names, not values.\n@required {offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response, val_id: str(uuid) # Id of a val}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint POST /v2/vals/{val_id}/environment_variables/\n@desc Create a new environment variable scoped to this project.\n@required {val_id: str(uuid) # Id of a val, value: str # Value of the environment variable., key: str # Name or key of the environment variable, accessible via Deno.env or process.env}\n@optional {description: any}\n@returns(201) {key: str, description: any, updatedAt: any, createdAt: str(date-time)} # An environment variable\n@errors {409: Key already exists}\n\n@endpoint PUT /v2/vals/{val_id}/environment_variables/{key}\n@desc Update a environment variable scoped to this project.\n@required {val_id: str(uuid) # Id of a val, key: str, value: str # Value of the environment variable.}\n@optional {description: any}\n@returns(201) {key: str, description: any, updatedAt: any, createdAt: str(date-time)} # An environment variable\n\n@endpoint DELETE /v2/vals/{val_id}/environment_variables/{key}\n@desc Delete a environment variable scoped to this project.\n@required {val_id: str(uuid) # Id of a val, key: str}\n@returns(204) Default Response\n@errors {404: Environment variable or project not found}\n\n@endpoint GET /v2/vals/{val_id}/environment_variable_groups/\n@desc List the environment variable groups attached to this val. This only includes the groups, not the variables in them.\n@required {offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response, val_id: str(uuid) # Id of a val}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint PUT /v2/vals/{val_id}/environment_variable_groups/{group_id}\n@desc Attach an environment variable group to this val. Every variable in the group is injected into the val's environment. Variables defined on the val itself take precedence over variables with the same key in a group. Attaching a group that is already attached succeeds without doing anything.\n@required {val_id: str(uuid) # Id of a val, group_id: str(uuid) # Id of an environment variable group}\n@returns(204) The group is attached to the val\n@errors {404: Val or environment variable group not found in your organization}\n\n@endpoint DELETE /v2/vals/{val_id}/environment_variable_groups/{group_id}\n@desc Detach an environment variable group from this val. The group itself, and the variables in it, are left alone.\n@required {val_id: str(uuid) # Id of a val, group_id: str(uuid) # Id of an environment variable group}\n@returns(204) The group is no longer attached to the val\n@errors {404: Val or environment variable group not found in your organization, or the group was not attached to this val}\n\n@endpoint GET /v2/vals/{val_id}\n@desc Get a val by id\n@required {val_id: str(uuid) # Id of a val}\n@returns(200) {name: str, id: str(uuid), createdAt: str(date-time), privacy: any, author: map{type: any, id: str(uuid), username: any}, imageUrl: any, description: any, links: map{self: str(uri), html: str(uri)}} # A Val\n\n@endpoint DELETE /v2/vals/{val_id}\n@desc Delete a project\n@required {val_id: str(uuid) # Id of a val}\n@returns(204) Default Response\n@errors {404: Project not found}\n\n@endpoint GET /v2/vals\n@desc Lists all vals including all public vals and your unlisted and private vals\n@required {limit: int=20 # Maximum items to return in each paginated response}\n@optional {privacy: any(public/unlisted/private) # This resource's privacy setting. Unlisted resources do not appear on profile pages or elsewhere, but you can link to them., user_id: str(uuid) # User ID to filter by, cursor: str(date-time) # Cursor to start the pagination from}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint POST /v2/vals\n@desc Create a new val\n@required {name: str, privacy: any(public/unlisted/private)}\n@optional {description: str, httpPrivacy: any(public/restricted) # Who can access the val's HTTP endpoints. Restricted app access is only available to eligible team organizations. If omitted, eligible team organizations default to restricted and other organizations default to public., orgId: str(uuid) # ID of the org to create the val in}\n@returns(201) {name: str, id: str(uuid), createdAt: str(date-time), privacy: any, author: map{type: any, id: str(uuid), username: any}, imageUrl: any, description: any, links: map{self: str(uri), html: str(uri)}} # A Val\n@errors {409: Conflict: Project name already exists}\n@example_request {\"name\":\"myVal\",\"description\":\"My val\",\"privacy\":\"public\"}\n\n@endpoint GET /v2/vals/{val_id}/branches/{branch_id}\n@desc Get a branch by id\n@required {val_id: str(uuid) # Id of a val, branch_id: str(uuid) # Id of a branch}\n@returns(200) {name: str, id: str(uuid), version: int, createdAt: str(date-time), updatedAt: str(date-time), forkedBranchId: any, links: map{self: str(uri), html: str(uri)}} # A Branch\n\n@endpoint DELETE /v2/vals/{val_id}/branches/{branch_id}\n@desc Delete a branch\n@required {val_id: str(uuid) # Id of a val, branch_id: str(uuid) # Id of a branch}\n@returns(204) Deleted\n@errors {404: Branch not found}\n\n@endpoint GET /v2/vals/{val_id}/branches\n@desc List all branches for a val\n@required {offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response, val_id: str(uuid) # Id of a val}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint POST /v2/vals/{val_id}/branches\n@desc Create a new branch\n@required {val_id: str(uuid) # Id of a val, name: str}\n@optional {branchId: str(uuid) # The branch ID to fork from. If this is not specified, the new branch will be forked from main.}\n@returns(201) {name: str, id: str(uuid), version: int, createdAt: str(date-time), updatedAt: str(date-time), forkedBranchId: any, links: map{self: str(uri), html: str(uri)}} # A Branch\n@errors {409: Conflict: Branch name already exists in this project}\n@example_request {\"name\":\"my-branch\",\"branchId\":\"00000000-0000-0000-0000-000000000000\"}\n\n@endpoint GET /v2/vals/{val_id}/files\n@desc Get metadata for files and directories in a val. If path is an empty string, returns files at the root directory.\n@required {path: str # Path to a file or directory (e.g. 'dir/subdir/file.ts'). Pass in an empty string to represent the root directory., recursive: bool=false # Whether to recursively act on all files in the project, offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response, val_id: str(uuid) # Id of a val}\n@optional {version: int # Specific branch version to query, branch_id: str(uuid) # Id to query}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint POST /v2/vals/{val_id}/files\n@desc Create a new file, project val or directory\n@required {path: str # Path to a file or directory (e.g. 'dir/subdir/file.ts'). Pass in an empty string to represent the root directory., val_id: str(uuid) # Id of a val}\n@optional {branch_id: str(uuid) # The specified branch of the resource. Defaults to main if not provided.}\n@returns(201) {name: str, id: str(uuid), path: str, version: int, updatedAt: str(date-time), type: any, links: map{self: str(uri), html: str(uri), module: str(uri), endpoint: str(uri), email: str(email)}} # A File or Directory's Metadata\n@errors {409: Default Response}\n\n@endpoint DELETE /v2/vals/{val_id}/files\n@desc Deletes a file or a directory. To delete a directory and all of its children, use the recursive flag. To delete all files, pass in an empty path and the recursive flag.\n@required {path: str # Path to a file or directory (e.g. 'dir/subdir/file.ts'). Pass in an empty string to represent the root directory., recursive: bool=false # Whether to recursively act on all files in the project, val_id: str(uuid) # Id of a val}\n@optional {branch_id: str(uuid) # The specified branch of the resource. Defaults to main if not provided.}\n@returns(204) Default Response\n@errors {404: File not found}\n\n@endpoint PUT /v2/vals/{val_id}/files\n@desc Update a file's content\n@required {path: str # Path to a file or directory (e.g. 'dir/subdir/file.ts'). Pass in an empty string to represent the root directory., val_id: str(uuid) # Id of a val}\n@optional {branch_id: str(uuid) # The specified branch of the resource. Defaults to main if not provided.}\n@returns(200) {name: str, id: str(uuid), path: str, version: int, updatedAt: str(date-time), type: any, links: map{self: str(uri), html: str(uri), module: str(uri), endpoint: str(uri), email: str(email)}} # A File or Directory's Metadata\n@returns(201) {name: str, id: str(uuid), path: str, version: int, updatedAt: str(date-time), type: any, links: map{self: str(uri), html: str(uri), module: str(uri), endpoint: str(uri), email: str(email)}} # A File or Directory's Metadata\n\n@endpoint GET /v2/vals/{val_id}/files/content\n@desc Download file content\n@required {path: str # Path to a file or directory (e.g. 'dir/subdir/file.ts'). Pass in an empty string to represent the root directory., val_id: str(uuid) # Id of a val}\n@optional {version: int # Specific branch version to query, branch_id: str(uuid) # Id to query, If-Match: str, If-Unmodified-Since: str, If-None-Match: str, If-Modified-Since: str, Cache-Control: str}\n@returns(200) Contents of the file\n@errors {304: Cached version of the file is the same as the one requested, 412: Precondition failed}\n\n@endgroup\n\n@group files\n@endpoint GET /v2/files/{file_id}\n@desc Get file metadata by file ID\n@required {file_id: str(uuid) # ID of a file in a val}\n@returns(200) {name: str, id: str(uuid), path: str, version: int, updatedAt: str(date-time), type: any, links: map{self: str(uri), html: str(uri), module: str(uri), endpoint: str(uri), email: str(email)}} # A File or Directory's Metadata\n\n@endgroup\n\n@group alias\n@endpoint GET /v2/alias/vals/{username}/{val_name}\n@desc Get a val\n@required {username: str # Username of the user whose val you are looking for, val_name: str # Name of the val you're looking for}\n@returns(200) {name: str, id: str(uuid), createdAt: str(date-time), privacy: any, author: map{type: any, id: str(uuid), username: any}, imageUrl: any, description: any, links: map{self: str(uri), html: str(uri)}} # A Val\n\n@endgroup\n\n@group me\n@endpoint GET /v2/me/vals\n@desc [BETA] List all of a user's vals for authenticated users\n@required {offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endgroup\n\n@group orgs\n@endpoint GET /v2/orgs\n@desc Get all orgs you are a member of\n@required {offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint GET /v2/orgs/{org_id}/memberships\n@desc List all memberships of an org\n@required {org_id: str(uuid) # Id of an org}\n@returns(200) Default Response\n\n@endgroup\n\n@group blob\n@endpoint GET /v2/blob\n@desc List blobs in your account\n@optional {prefix: str # If specified, only include blobs that start with this string}\n@returns(200) List of blobs that you’ve stored\n\n@endpoint GET /v2/blob/{key}\n@desc Get a blob’s contents.\n@required {key: str # Key that uniquely identifies this blob}\n@returns(200) Binary contents of the returned file\n\n@endpoint POST /v2/blob/{key}\n@desc Store data in blob storage\n@required {key: str # Key that uniquely identifies this blob}\n@returns(201) Default Response\n@errors {400: Default Response}\n\n@endpoint DELETE /v2/blob/{key}\n@desc Delete a blob\n@required {key: str # Key that uniquely identifies this blob}\n@returns(204) Blob successfully deleted\n\n@endgroup\n\n@group connections\n@endpoint POST /v3/connections/slack/token\n@desc Get a valid Slack access token for a connected workspace. Automatically refreshes the token if expired.\n@required {team_id: str # The Slack team/workspace ID (e.g., 'T9TK3CUKW')}\n@returns(200) {access_token: str} # Default Response\n@errors {404: Default Response, 500: Default Response}\n\n@endpoint POST /v3/connections/google-docs/token\n@desc Get a valid Google access token for a connected Google account. Automatically refreshes the token if expired.\n@required {email: str # The Google account email}\n@returns(200) {access_token: str, granted_scopes: [str]} # Default Response\n@errors {404: Default Response, 500: Default Response}\n\n@endgroup\n\n@group val\n@endpoint GET /v3/val/viewer\n@desc Look up the identity of the viewer of an app-authenticated (intranet) val, given the X-Val-Town-User header value that Fastify forwarded to the val. Authenticated with the val's own API token (bearer auth). The projectId inside the signed header must match the caller's own project.\n@required {x-val-town-user: str # The signed X-Val-Town-User header value Fastify forwarded to the val.}\n@returns(200) {id: str(uuid), type: any, username: any, bio: any, profileImageUrl: any, url: str(uri), links: map{self: str(uri)}} # Public identity of the viewer derived from a verified X-Val-Town-User header. Only safe, public profile fields are returned — no email or tier.\n@errors {400: Default Response, 401: Default Response, 403: Default Response, 404: Default Response}\n\n@endgroup\n\n@group environment-variable-groups\n@endpoint GET /v3/environment-variable-groups/\n@desc List environment variable groups\n@required {offset: int=0 # Number of items to skip in order to deliver paginated results, limit: int=20 # Maximum items to return in each paginated response}\n@optional {orgId: str(uuid) # Organization to act in. Defaults to the organization that owns the API token. List the organizations you belong to with GET /v2/orgs.}\n@returns(200) {data: [map], links: map{self: str(uri), prev: str(uri), next: str(uri)}} # A paginated result set\n\n@endpoint POST /v3/environment-variable-groups/\n@desc Create a new environment variable group\n@required {name: str}\n@optional {orgId: str(uuid) # Organization to act in. Defaults to the organization that owns the API token. List the organizations you belong to with GET /v2/orgs.}\n@returns(201) {name: str, id: str(uuid), orgId: str(uuid), count: int, updatedAt: any, createdAt: str(date-time)} # An environment variable group\n@errors {409: Name conflict with another environment variable group in that organization}\n\n@endpoint DELETE /v3/environment-variable-groups/{id}\n@desc Delete an environment variable group\n@required {id: str(uuid) # Environment variable group ID}\n@returns(204) Default Response\n\n@endpoint PUT /v3/environment-variable-groups/{id}\n@desc Rename an environment variable group\n@required {id: str(uuid) # Environment variable group ID, name: str # New name for group}\n@returns(204) Rename accepted\n@errors {409: Name conflict with another environment variable group in your organization}\n\n@endpoint GET /v3/environment-variable-groups/{id}/environment-variables\n@desc List variables in an environment variable group\n@required {id: str(uuid) # Environment variable group ID}\n@returns(200) Default Response\n\n@endpoint POST /v3/environment-variable-groups/{id}/environment-variables\n@desc Create an environment variable in a group\n@required {id: str(uuid) # Environment variable group ID, value: str # Value of the environment variable., key: str # Name or key of the environment variable, accessible via Deno.env or process.env}\n@optional {description: any}\n@returns(201) {key: str, description: any, updatedAt: any, createdAt: str(date-time)} # An environment variable\n@errors {409: Name conflict with another environment variable in this group}\n\n@endpoint POST /v3/environment-variable-groups/{id}/environment-variables/{key}\n@desc Create or update an environment variable in a group\n@required {id: str(uuid) # Environment variable group ID, key: str # Environment variable key, value: str # Value of the environment variable.}\n@optional {description: any}\n@returns(201) {key: str, description: any, updatedAt: any, createdAt: str(date-time)} # An environment variable\n\n@endpoint DELETE /v3/environment-variable-groups/{id}/environment-variables/{key}\n@desc Delete an environment variable in a group\n@required {id: str(uuid) # Environment variable group ID, key: str # Environment variable key}\n@returns(204) Default Response\n\n@endgroup\n\n@end\n"}