Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 5 Nov 2026. What's built · Install 0.3.0
jadpo
ReferenceHTTP

APIs

HTTP

A Jadpo app answers HTTP requests with routes. A route says which method and URL it answers, what comes in, what goes out, and which action or query runs. This route adds a todo:

domains/todos/routes/todos.jadpo:

example
use todos/types { NewTodo, TodoView }use todos/actions { add_todo }/// The todo list.routes Todos {    prefix: /todos    /// Adds a todo.    POST / {        authentication: RouteAuthentication.none        input: NewTodo        output: TodoView        run: add_todo(input)    }}

It answers POST /todos. Jadpo reads a NewTodo from the JSON body and checks it, and run: gets it as input. run: calls the action add_todo, which returns a TodoView, the route's output:. The route answers 200 with that value as JSON.

NewTodo, TodoView and add_todo are your app's own. Each use line brings a name in from another file of your app, and these are the files:

domains/todos/types/new_todo.jadpo:

example
/// What a caller sends to add a todo.type NewTodo = Input {    title: Text}

domains/todos/types/todo_view.jadpo:

example
/// A todo, as the app sends it back.type TodoView = Output {    title: Text    done: Bool}

domains/todos/actions/add_todo.jadpo:

example
use todos/types { NewTodo, TodoView }/// Builds the todo and sends it back. It stores nothing.action add_todo(input: NewTodo) -> TodoView {    return TodoView {        title: input.title        done: false    }}

policy.jadpo:

example
use todospolicy {    actions: {        todos.add_todo: [Access.public]    }}

Most actions take their permission from the stored records they reach (Policy). add_todo reaches none, so policy.jadpo says who may run it, and Access.public means anyone. RouteAuthentication, Access, Text and Bool are built into Jadpo, so they need no use line.

Every route needs a signed-in caller unless an authentication: line in the route says otherwise, as this one does because the app has no sign-in yet (Routes: signed in by default).

Run jadpo api update once, which writes the public API record, then jadpo dev, and send it a todo:

shell
curl -X POST http://localhost:3000/todos \  -H 'content-type: application/json' \  -d '{"title": "Buy milk"}'
text
{"title":"Buy milk","done":false}

A route holds no logic of its own. The work lives in actions and queries. When an action fails, the HTTP status comes from the failure's kind, a category such as not_found (404), never from the route (Failure kinds).

The topics of this page cover:

Route groups

Every route belongs to a route group: a routes declaration with a name and a prefix:.

Paths and placeholders

A placeholder in a path is typed where it appears, and reaches what the route runs by its name.

One input

A route reads at most one input, named by input:.

Output and status

output: names what the route answers with: an Output type, an object made to be sent to clients.

What a route runs

run: calls one named action.

Time limits

Every route has a deadline: 10 seconds, unless deadline: sets another, and never more than 60.

Waiting for follow-on work

An action does its own database work and leaves the rest, such as a second call to a provider, to subscribers: code that runs when an event the action emits is delivered (Subscribers).

Streaming a model's answer

When what a route runs returns an AiStream, the route sends a model's answer as it is written, piece by piece.

How failures reach the client

Every failure reaches the client in one envelope: code, message, request_id, and the failure's client fields under details (Failures).

Idempotent writes

A client that retries a write after a timeout can't tell whether the first try worked.

Generated routes

Some features generate their routes for you.

Health

The runtime always serves two health checks, and there is nothing to write.

APIs and versions

Most apps have one API.

OpenAPI

The compiler writes one OpenAPI 3.1 document per API into build/openapi/.

The public API record

Each API has a committed, readable record of its routes, fields and failure codes: api/main.jadpo_record for main.

Write revisions not built

After a write, a client can make sure its next read sees that write rather than an older cached copy.

Webhooks

You don't write routes for a provider's webhooks: Jadpo generates them from the provider's package (Webhooks as events).

What is built says which of this works today.

Markdown for agents: /docs/http.md.Built from Jadpo main at aee2e8f.