---
title: API HTTP
description: A API /v1 do Lampson para seus apps — mensagens a um agente em JSON, streaming SSE ou callback, API keys com limites, a caixa de entrada que junta rajadas e o OpenAPI.
---
# API HTTP

Cada projeto (workspace) do Lampson expõe uma API para seus apps, seus bots e outros agentes:

```
https://seu-lampson/w/<workspace>/v1/…
```

Sem URL pública, a base é `http://127.0.0.1:8080/w/<workspace>/v1` — só a partir deste computador. Para usar de fora: [`lampson --domain`](/pt/docs/phone) ou um túnel.

## API keys

A API pede **sempre** uma key, também a partir do mesmo computador.

```sh
lampson key add --agent tienda --name "bot do whatsapp"
lampson key add --agent tienda,soporte --rate 60 --callback https://hooks.mi-app.com/
lampson key list
lampson key remove k6KJgJHpu
```

Ou pela web: **API** no painel esquerdo → `+ crear una API key` (“+ criar uma API key”).

- A key é mostrada **uma única vez**, com as URLs da API e do MCP prontas para copiar. O Lampson guarda só o hash dela.
- `--agent`: os agentes que ela pode usar (sem opção, todos).
- `--rate N`: pedidos por minuto (padrão 120; `0` = sem limite). Passado o limite, responde `429` com `Retry-After`.
- `--callback URL`: as únicas URLs para as quais o Lampson mandará callbacks com esta key: mesmo esquema, host e porta, e o caminho como pasta (`https://app.com/hooks` permite `/hooks/…`, não `app.com.evil.net` nem `/hooks-x`). Sem essa opção, a key não pode pedir callbacks. As keys criadas antes do Lampson 0.5.1 chegam a qualquer nome de host público, e `lampson key list` as marca para que você as substitua.
- Uma key da API só abre `/v1`: nunca a interface web, o terminal nem o chat.

Um workspace com keys não é desligado por inatividade: senão, a próxima mensagem do seu bot o encontraria desligado.

## Enviar uma mensagem

```sh
curl -X POST https://seu-lampson/w/tienda/v1/messages \
  -H "Authorization: Bearer lk_…" -H "Content-Type: application/json" \
  -d '{"to": "tienda", "thread": "whatsapp:+5491122334455", "text": "vocês têm pão integral?"}'
```

```json
{"agent": "tienda", "thread": "whatsapp:+5491122334455", "session": "20261016-132332-8546",
 "text": "Olá! Sim, temos pão integral de fermentação natural a $3.200.", "steps": 2,
 "usage": {"input": 1453, "output": 148, "cached": 1024}, "stopped": "done",
 "batch": ["m59429972irl8"], "lead": "m59429972irl8"}
```

O body é um **envelope**:

| campo | |
|---|---|
| `text` | a mensagem (obrigatório) |
| `to` | o agente (por padrão, o do workspace) |
| `thread` | quem/o que é esta conversa: mesmo thread = mesma conversa. Cada key tem as suas: outro app com o mesmo `thread` começa outra |
| `session` | ou uma sessão conhecida, desta mesma key (a de outra key dá 404) |
| `images` | `[{"media_type": "image/jpeg", "data": "<base64>"}]` — os modelos com visão as veem |
| `from`, `meta` | livres: viajam com a mensagem (ids do seu sistema, nome do cliente) |
| `sent_at` | quando o cliente escreveu (unix): ordena uma rajada que chegou fora de ordem |
| `callback` | veja abaixo |

Erros: `400` (envelope inválido), `401` (sem key ou key inválida), `403` (agente fora da key, ou callback não permitido), `404` (agente inexistente), `429` (limite).

## Três formas de receber a resposta

- **JSON** — `POST /v1/messages`: o request espera o agente e devolve o resultado.
- **Streaming** — `POST /v1/messages/stream`: Server-Sent Events com cada passo (`session`, `assistant`, `tool_call`…, `done`), como [`lampson run --json`](/pt/docs/headless#json-os-eventos).
- **Callback** — `POST /v1/messages` com `"callback": "https://…"`: responde `202 {"job": "m…", "status": "queued"}` na hora e, quando o agente termina, o Lampson faz um POST para a sua URL. É o que os webhooks do WhatsApp e companhia precisam, porque exigem uma resposta rápida.

O callback leva `{job, jobs, batch, status, agent, thread, session, text, steps, usage, stopped, meta}`. Ele vai **assinado** com o segredo da key que o pediu, que o `lampson key add` mostra uma única vez junto com a key: `X-Lampson-Signature: sha256=<HMAC-SHA256 do body>`, e `X-Lampson-Key` diz qual key é. Assim, outro app que use o mesmo Lampson não consegue assinar um callback falso para o seu. As keys criadas antes do Lampson 0.5.1 assinam com `LAMPSON_WEBHOOK_SECRET`, como antes. Verifique com o [SDK](/pt/docs/sdk#verificar-um-callback) ou:

```python
import hmac, hashlib
ok = hmac.compare_digest("sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest(), signature)
```

`GET /v1/jobs/<id>` devolve o estado de uma mensagem enviada com callback.

## A caixa de entrada

Cada conversa (agente + thread) tem a sua caixa de entrada. Isso já vem resolvido, não precisa configurar:

- **Nunca dois turnos ao mesmo tempo** na mesma conversa. Clientes diferentes rodam, sim, em paralelo.
- **As rajadas se juntam.** O turno começa após 3 segundos sem mensagens novas (ou 15 desde a primeira): «oi» / «quanto custa o pão sem glúten?» / «tem em estoque?» vão em **um** turno e recebem **uma** resposta — a mesma nos três requests, com `batch` (as mensagens do lote) e `lead` (a primeira). Com callback sai **um** POST por lote.
- **O que chega no meio do turno** entra no turno em andamento, antes de o agente responder. Se chega quando o modelo já está escrevendo a resposta, o Lampson a descarta e responde de novo com tudo: nunca sai uma resposta que ignora a última mensagem do cliente.

A espera se ajusta por agente com `"buffer": {"quiet_s": 3, "max_s": 15}`, ou `"buffer": false` para responder sem esperar (a fila continua). → [Agentes](/pt/docs/agents)

## Objetivos

Um [objetivo](/pt/docs/objectives) é algo que um agente (ou uma [equipe](/pt/docs/teams)) trabalha sozinho até terminar.

```sh
curl -X POST https://seu-lampson/w/loja/v1/objectives -H "Authorization: Bearer lk_…" \
  -d '{"agent": "cto", "text": "Adicione filtrar por status, com testes; me peça aprovação antes do merge.", "budget_tokens": 400000}'
```

| | |
|---|---|
| `POST /v1/objectives` | criar: `{text, agent? \| team?, budget_tokens?, round_seconds?}` → `201` com o objetivo |
| `GET /v1/objectives` | os que esta key pode ver (os dos seus agentes) |
| `GET /v1/objectives/<id>` | um: `status` (`active`, `waiting`, `done`, `failed`, `cancelled`, `paused`), `progress` (último informe), `question` e `question_kind` (`question` ou `approval`), `result`, `tasks` (o quadro), `ledger` (o registro), `spent` |
| `POST /v1/objectives/<id>/reply` | responder: `{text}` a uma pergunta, `{approved: true\|false, text?}` a uma aprovação |
| `POST /v1/objectives/<id>/cancel` | interromper |

Um objetivo `waiting` não avança nem gasta até você responder.

## Outros endpoints

| | |
|---|---|
| `GET /v1/agents` | os agentes que esta key pode usar |
| `GET /v1/jobs/<id>` | estado de uma mensagem com callback |
| `POST /v1/mcp` · `/v1/mcp/stream` | MCP por HTTP → [Lampson como servidor MCP](/pt/docs/mcp-server) |
| `GET /v1/openapi.json` | o OpenAPI 3.1 desta API |

## OpenAPI

`/v1/openapi.json` descreve **só** a API pública — a interface web, o terminal e os webhooks dos canais não aparecem. Use para gerar um cliente na sua linguagem (`openapi-generator` para Go, Java, C#, PHP…) ou para testar a API na sua ferramenta favorita. Para JavaScript e Python já existe [SDK](/pt/docs/sdk).
