# 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:

```jadpo
// domains/planning/routes/todos.jadpo
routes Todos {
    prefix: /todos

    POST / {
        input: CreateTodo
        output: TodoView
        status: SuccessStatus.created
        run: create_todo(input, current_principal.user)
    }
}
```

This route answers `POST /todos`. Jadpo reads a `CreateTodo` from the
JSON body and checks it, and `run:` gets it as `input`. `run:` calls the
action `create_todo` for the signed-in user (`current_principal.user`, see
[Who is calling](who-is-calling-current-principal.md)). The
action returns a `TodoView`, which must be the route's `output:`, and
`status: SuccessStatus.created` makes the route answer 201 Created rather
than 200.

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

Every route needs a signed-in caller unless an `authentication:` line in
the route says otherwise
([Routes: signed in by default](routes-signed-in-by-default.md)).

The topics of this page cover:

- how routes are grouped and matched: [Route groups](route-groups.md) and
  [Paths and placeholders](paths-and-placeholders.md);
- what a route reads and answers: [One input](one-input.md) and
  [Output and status](output-and-status.md);
- how long it may run: [Time limits](time-limits.md);
- what Jadpo writes for you: [Health](health.md) checks,
  [Generated routes](generated-routes.md), an [OpenAPI](openapi.md) document
  for each API, and [The public API record](the-public-api-record.md), a
  file in your project that lists each API's routes and fields, so every
  change to the API shows as a diff of that file.
