canonical: https://jentic.com/apis/anvil.works/anvil-works

# Anvil Works API

Jentic publishes the only available OpenAPI specification for Anvil Works API, keeping it validated and agent-ready. Anvil is a platform for building full-stack web applications in Python, and its HTTP API exposes server functions, data tables, and HTTP endpoints to outside callers. Agents can invoke a deployed Anvil server function by name, read or write rows in an Anvil data table, and call user-defined HTTP endpoints exposed by an Anvil app. The API is lightweight (five endpoints) and authenticated with a per-app bearer token issued from the Anvil editor.

## For AI agents

Call Python server functions, query data table rows, and hit HTTP endpoints in any deployed Anvil app using a per-app bearer token.

## Scope

Does not handle UI rendering, app deployment, or user authentication flows - use for invoking server functions, data table rows, and custom HTTP endpoints in already-deployed Anvil apps only.

## Capabilities

- Invoke a named Python server function in a deployed Anvil app and receive its return value
- Read, filter, and write rows in an Anvil data table without writing custom server code
- Call user-defined HTTP endpoints registered inside an Anvil app from external systems
- Look up the Anvil runtime version to confirm an app is reachable before issuing a call
- Authenticate per-app with a bearer token scoped to a single Anvil application

## Use cases

### Internal tool back end

Use Anvil as the back end for an internal Python tool and let an external agent invoke its server functions over HTTPS. The agent calls `/api/{app_id}/call/{function_name}` with arguments, and Anvil runs the corresponding Python function in the cloud and returns the result. This avoids standing up a separate API service for small Python utilities.

Example prompt: POST to `/api/{app_id}/call/send_report` with {"args": ["q3"], "kwargs": {}} and return the function's response payload

### Lightweight data table operations

Use Anvil data tables as a hosted Postgres-backed store and read or write rows directly through the HTTP API. Agents can list rows in `/api/{app_id}/tables/{table_name}/rows`, fetch a specific row by id, or post a new row, without writing any server-side Python. Useful for prototypes and small apps that do not need a dedicated database service.

Example prompt: GET `/api/{app_id}/tables/customers/rows` with a filter on email, then POST a new row if no match is found

### Custom HTTP endpoints in an Anvil app

Anvil apps can expose user-defined HTTP endpoints under `/http/{app_id}/{path}.` Agents call these to trigger arbitrary logic inside the app, for example webhooks from third-party services or internal automation hooks. Anvil handles auth, routing, and Python execution server-side.

Example prompt: POST a Stripe webhook payload to `/http/{app_id}/stripe-webhook` and confirm a 200 response

### AI agent integration via Jentic

An agent that needs to interact with a deployed Anvil application can search Jentic for the right Anvil operation, load the input schema, and execute the call without ever handling the raw bearer token. Jentic stores the per-app token and injects it server-side, so the agent only sees the function name and arguments.

Example prompt: Search Jentic for 'call an Anvil server function', load the schema for `/api/{app_id}/call/{function_name}`, and invoke it with the user's arguments

## Key endpoints

| Method | Path | Description |
| --- | --- | --- |
| POST | `/api/{app_id}/call/{function_name}` | Invoke a deployed Python server function by name |
| GET | `/api/{app_id}/tables/{table_name}/rows` | List rows in an Anvil data table |
| GET | `/api/{app_id}/tables/{table_name}/rows/{row_id}` | Fetch a single data table row by id |
| POST | `/http/{app_id}/{path}` | Call a user-defined HTTP endpoint inside an Anvil app |
| GET | `/api/version` | Return the Anvil runtime version for diagnostics |

## Key resources

- **Server Functions** — Invoke a named Python function in a deployed Anvil app and receive its return value
- **Data Tables** — Read, filter, insert, and fetch rows in Anvil-hosted data tables
- **HTTP Endpoints** — Call user-defined HTTP routes registered inside an Anvil application
- **System** — Probe runtime version and connectivity for a given Anvil app

## Why Jentic

- **Setup:** Wiring the Anvil Works API by hand means carrying a per-app bearer token and threading the app id and function or table name through each path yourself. Through Jentic you install once, import Anvil Works from the API Directory, store the token once, and your agent calls it.
- **Permission scoping:** Anvil Works puts the app id and table name in the URL path (`/api/{app_id}/tables/{table_name}/rows/{row_id}`), so a rule can pin your agent to one app or table: it can read rows from that table and nothing else. You choose the operations it may call, so server-function calls or custom HTTP endpoints are not included unless you add them.
- **Credential handling:** Your Anvil per-app bearer token is stored once, encrypted, by your own Jentic One instance and injected for the right app id at execution time. It never enters the agent's prompt, logs, or context.
- **Discovery method:** Agents search Jentic by intent such as 'call an Anvil server function' or 'read rows from an Anvil table', and Jentic returns the matching operation with its input schema so the agent calls the right endpoint without browsing the reference docs.

## Related APIs

- **Airtable API** — Hosted relational store with REST CRUD on tables, similar feel to Anvil data tables.
- **GitHub API** — Source control for the Python repo behind the Anvil app.
- **Stripe API** — Accept payments inside an Anvil-built web app via webhooks routed through `/http/{app_id}/{path}.`

## FAQ

### Why is there no official OpenAPI spec for Anvil Works API?

Anvil Works does not publish an OpenAPI specification. Jentic generates and maintains this spec so that AI agents and developers can call Anvil Works API via structured tooling. It is validated against the live API and kept up to date. Get started with Jentic One, the self-hosted execution layer.

### What authentication does the Anvil Works API use?

Anvil uses HTTP bearer authentication with a per-app token issued from the Anvil editor. Through Jentic the token is stored in the encrypted Jentic One instance and injected at call time, so the agent context never sees the raw bearer value.

### Can I read and write data table rows with the Anvil Works API?

Yes. GET `/api/{app_id}/tables/{table_name}/rows` lists rows, GET `/api/{app_id}/tables/{table_name}/rows/{row_id}` fetches one row, and POSTs to the same collection insert new rows. Filters are passed as query parameters.

### How do I call an Anvil server function through Jentic?

Search Jentic for 'call an Anvil server function', load the schema for `/api/{app_id}/call/{function_name}`, and execute it with the function name and arguments. Jentic returns the function's serialised return value to the agent.

### What are the rate limits for the Anvil Works API?

Limits depend on the plan attached to the Anvil app and are not declared in the OpenAPI spec. Hobby plans have lower per-minute caps than paid plans. Check the dashboard of the specific app for its current quota.

### Can the API trigger arbitrary Python code in an Anvil app?

Only Python functions registered in the app as @anvil.server.callable can be invoked, and only HTTP endpoints decorated with @anvil.server.http_endpoint are reachable under `/http/{app_id}/{path}.` The API does not execute arbitrary code outside those decorators.

### Can I limit what my agent is allowed to do with the Anvil Works API?

Yes. Because you run Jentic One yourself, your own rules decide which Anvil operations and which per-app credential the agent may use. Since Anvil puts the app id and table name in the URL path, such as `/api/{app_id}/tables/{table_name}/rows/{row_id}`, you can pin the agent to a single app or a single table so it only reads rows there. Server-function calls to `/api/{app_id}/call/{function_name}` and custom endpoints under `/http/{app_id}/{path}` stay out of reach unless you explicitly allow them.
