{"files":{"SKILL.md":"---\nname: val-town-api\ndescription: \"Val Town API skill. Use when working with Val Town for alias, me, blob. Covers 52 endpoints.\"\nversion: 1.0.0\ngenerator: lapsh\n---\n\n# Val Town API\nAPI version: 1\n\n## Auth\nBearer bearer\n\n## Base URL\nhttps://api.val.town\n\n## Setup\n1. Set Authorization header with your Bearer token\n2. GET /v1/me -- verify access\n3. POST /v1/blob/{key} -- create first blob\n\n## Endpoints\n\n52 endpoints across 13 groups. See references/api-spec.lap for full details.\n\n### alias\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v1/alias/{username} | Get basic details about a user, given their username |\n| GET | /v2/alias/vals/{username}/{val_name} | Get a val |\n\n### me\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v1/me | Get profile information for the current user |\n| GET | /v2/me/vals | [BETA] List all of a user's vals for authenticated users |\n\n### blob\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v1/blob | List blobs in your account |\n| GET | /v1/blob/{key} | Get a blob’s contents. |\n| POST | /v1/blob/{key} | Store data in blob storage |\n| DELETE | /v1/blob/{key} | Delete a blob |\n| GET | /v2/blob | List blobs in your account |\n| GET | /v2/blob/{key} | Get a blob’s contents. |\n| POST | /v2/blob/{key} | Store data in blob storage |\n| DELETE | /v2/blob/{key} | Delete a blob |\n\n### users\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v1/users/{user_id} | Get basic information about a user |\n\n### sqlite\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /v1/sqlite/execute | Execute a single SQLite statement and return results |\n| POST | /v1/sqlite/batch | Execute a batch of SQLite statements and return results for all of them |\n\n### email\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /v1/email | Send emails |\n\n### telemetry\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v1/telemetry/traces | 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| GET | /v1/telemetry/logs | 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\n### vals\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v2/vals/{val_id}/environment_variables/ | List environment variables defined in this project. This only includes names, not values. |\n| POST | /v2/vals/{val_id}/environment_variables/ | Create a new environment variable scoped to this project. |\n| PUT | /v2/vals/{val_id}/environment_variables/{key} | Update a environment variable scoped to this project. |\n| DELETE | /v2/vals/{val_id}/environment_variables/{key} | Delete a environment variable scoped to this project. |\n| GET | /v2/vals/{val_id}/environment_variable_groups/ | List the environment variable groups attached to this val. This only includes the groups, not the variables in them. |\n| PUT | /v2/vals/{val_id}/environment_variable_groups/{group_id} | 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| DELETE | /v2/vals/{val_id}/environment_variable_groups/{group_id} | Detach an environment variable group from this val. The group itself, and the variables in it, are left alone. |\n| GET | /v2/vals/{val_id} | Get a val by id |\n| DELETE | /v2/vals/{val_id} | Delete a project |\n| GET | /v2/vals | Lists all vals including all public vals and your unlisted and private vals |\n| POST | /v2/vals | Create a new val |\n| GET | /v2/vals/{val_id}/branches/{branch_id} | Get a branch by id |\n| DELETE | /v2/vals/{val_id}/branches/{branch_id} | Delete a branch |\n| GET | /v2/vals/{val_id}/branches | List all branches for a val |\n| POST | /v2/vals/{val_id}/branches | Create a new branch |\n| GET | /v2/vals/{val_id}/files | Get metadata for files and directories in a val. If path is an empty string, returns files at the root directory. |\n| POST | /v2/vals/{val_id}/files | Create a new file, project val or directory |\n| DELETE | /v2/vals/{val_id}/files | 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| PUT | /v2/vals/{val_id}/files | Update a file's content |\n| GET | /v2/vals/{val_id}/files/content | Download file content |\n\n### files\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v2/files/{file_id} | Get file metadata by file ID |\n\n### orgs\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v2/orgs | Get all orgs you are a member of |\n| GET | /v2/orgs/{org_id}/memberships | List all memberships of an org |\n\n### connections\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /v3/connections/slack/token | Get a valid Slack access token for a connected workspace. Automatically refreshes the token if expired. |\n| POST | /v3/connections/google-docs/token | Get a valid Google access token for a connected Google account. Automatically refreshes the token if expired. |\n\n### val\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v3/val/viewer | 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\n### environment-variable-groups\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /v3/environment-variable-groups/ | List environment variable groups |\n| POST | /v3/environment-variable-groups/ | Create a new environment variable group |\n| DELETE | /v3/environment-variable-groups/{id} | Delete an environment variable group |\n| PUT | /v3/environment-variable-groups/{id} | Rename an environment variable group |\n| GET | /v3/environment-variable-groups/{id}/environment-variables | List variables in an environment variable group |\n| POST | /v3/environment-variable-groups/{id}/environment-variables | Create an environment variable in a group |\n| POST | /v3/environment-variable-groups/{id}/environment-variables/{key} | Create or update an environment variable in a group |\n| DELETE | /v3/environment-variable-groups/{id}/environment-variables/{key} | Delete an environment variable in a group |\n\n## Common Questions\n\nMatch user requests to endpoints in references/api-spec.lap. Key patterns:\n- \"Get alia details?\" -> GET /v1/alias/{username}\n- \"List all me?\" -> GET /v1/me\n- \"List all blob?\" -> GET /v1/blob\n- \"Get blob details?\" -> GET /v1/blob/{key}\n- \"Delete a blob?\" -> DELETE /v1/blob/{key}\n- \"Get user details?\" -> GET /v1/users/{user_id}\n- \"Create a execute?\" -> POST /v1/sqlite/execute\n- \"Create a batch?\" -> POST /v1/sqlite/batch\n- \"Create a email?\" -> POST /v1/email\n- \"List all traces?\" -> GET /v1/telemetry/traces\n- \"List all logs?\" -> GET /v1/telemetry/logs\n- \"List all environment_variables?\" -> GET /v2/vals/{val_id}/environment_variables/\n- \"Create a environment_variable?\" -> POST /v2/vals/{val_id}/environment_variables/\n- \"Update a environment_variable?\" -> PUT /v2/vals/{val_id}/environment_variables/{key}\n- \"Delete a environment_variable?\" -> DELETE /v2/vals/{val_id}/environment_variables/{key}\n- \"List all environment_variable_groups?\" -> GET /v2/vals/{val_id}/environment_variable_groups/\n- \"Update a environment_variable_group?\" -> PUT /v2/vals/{val_id}/environment_variable_groups/{group_id}\n- \"Delete a environment_variable_group?\" -> DELETE /v2/vals/{val_id}/environment_variable_groups/{group_id}\n- \"Get val details?\" -> GET /v2/vals/{val_id}\n- \"Delete a val?\" -> DELETE /v2/vals/{val_id}\n- \"List all vals?\" -> GET /v2/vals\n- \"Create a val?\" -> POST /v2/vals\n- \"Get branche details?\" -> GET /v2/vals/{val_id}/branches/{branch_id}\n- \"Delete a branche?\" -> DELETE /v2/vals/{val_id}/branches/{branch_id}\n- \"List all branches?\" -> GET /v2/vals/{val_id}/branches\n- \"Create a branche?\" -> POST /v2/vals/{val_id}/branches\n- \"List all files?\" -> GET /v2/vals/{val_id}/files\n- \"Create a file?\" -> POST /v2/vals/{val_id}/files\n- \"List all content?\" -> GET /v2/vals/{val_id}/files/content\n- \"Get file details?\" -> GET /v2/files/{file_id}\n- \"Get val details?\" -> GET /v2/alias/vals/{username}/{val_name}\n- \"List all vals?\" -> GET /v2/me/vals\n- \"List all orgs?\" -> GET /v2/orgs\n- \"List all memberships?\" -> GET /v2/orgs/{org_id}/memberships\n- \"List all blob?\" -> GET /v2/blob\n- \"Get blob details?\" -> GET /v2/blob/{key}\n- \"Delete a blob?\" -> DELETE /v2/blob/{key}\n- \"Create a token?\" -> POST /v3/connections/slack/token\n- \"Create a token?\" -> POST /v3/connections/google-docs/token\n- \"List all viewer?\" -> GET /v3/val/viewer\n- \"List all environment-variable-groups?\" -> GET /v3/environment-variable-groups/\n- \"Create a environment-variable-group?\" -> POST /v3/environment-variable-groups/\n- \"Delete a environment-variable-group?\" -> DELETE /v3/environment-variable-groups/{id}\n- \"Update a environment-variable-group?\" -> PUT /v3/environment-variable-groups/{id}\n- \"List all environment-variables?\" -> GET /v3/environment-variable-groups/{id}/environment-variables\n- \"Create a environment-variable?\" -> POST /v3/environment-variable-groups/{id}/environment-variables\n- \"Delete a environment-variable?\" -> DELETE /v3/environment-variable-groups/{id}/environment-variables/{key}\n- \"How to authenticate?\" -> See Auth section\n\n## Response Tips\n- Check response schemas in references/api-spec.lap for field details\n- List endpoints may support pagination; check for limit, offset, or cursor params\n- Create/update endpoints typically return the created/updated object\n- Error responses use types: Conflict\n\n## CLI\n\n```bash\n# Update this spec to the latest version\nnpx @lap-platform/lapsh get val-town-api -o references/api-spec.lap\n\n# Search for related APIs\nnpx @lap-platform/lapsh search val-town-api\n```\n\n## References\n- Full spec: See references/api-spec.lap for complete endpoint details, parameter tables, and response schemas\n\n> Generated from the official API spec by [LAP](https://lap.sh)\n","references/api-spec.lap":"@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, 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"}}