---
title: API HTTP
description: La API /v1 de Lampson para tus apps — mensajes a un agente en JSON, streaming SSE o con callback, API keys con límites, el buzón que junta ráfagas y el OpenAPI.
---
# API HTTP

Cada proyecto (workspace) de Lampson expone una API para tus apps, tus bots y otros agentes:

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

Sin URL pública, la base es `http://127.0.0.1:8080/w/<workspace>/v1` — solo desde esta PC. Para usarla desde afuera: [`lampson --domain`](/es/docs/phone) o un túnel.

## API keys

La API pide **siempre** una key, también desde la misma PC.

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

O desde la web: **API** en el panel izquierdo → `+ crear una API key`.

- La key se muestra **una sola vez**, con las URLs de la API y del MCP listas para copiar. Lampson guarda solo su hash.
- `--agent`: los agentes que puede usar (sin opción, todos).
- `--rate N`: pedidos por minuto (por defecto 120; `0` = sin límite). Pasado el límite responde `429` con `Retry-After`.
- `--callback URL`: las únicas URLs a las que Lampson le mandará callbacks con esta key: mismo esquema, host y puerto, y la ruta como carpeta (`https://app.com/hooks` deja `/hooks/…`, no `app.com.evil.net` ni `/hooks-x`). Sin esta opción, la key no puede pedir callbacks. Las keys creadas antes de Lampson 0.5.1 llegan a cualquier nombre de host público, y `lampson key list` las marca para que las reemplaces.
- Una key de la API solo abre `/v1`: nunca la interfaz web, la terminal ni el chat.

Un workspace con keys no se apaga por inactividad: si no, el próximo mensaje de tu bot lo encontraría apagado.

## Mandar un mensaje

```sh
curl -X POST https://tu-lampson/w/tienda/v1/messages \
  -H "Authorization: Bearer lk_…" -H "Content-Type: application/json" \
  -d '{"to": "tienda", "thread": "whatsapp:+5491122334455", "text": "¿tienen pan integral?"}'
```

```json
{"agent": "tienda", "thread": "whatsapp:+5491122334455", "session": "20261016-132332-8546",
 "text": "¡Hola! Sí, tenemos pan integral de masa madre a $3.200.", "steps": 2,
 "usage": {"input": 1453, "output": 148, "cached": 1024}, "stopped": "done",
 "batch": ["m59429972irl8"], "lead": "m59429972irl8"}
```

El body es un **sobre**:

| campo | |
|---|---|
| `text` | el mensaje (obligatorio) |
| `to` | el agente (por defecto, el del workspace) |
| `thread` | quién/qué es esta conversación: mismo thread = misma conversación. Cada key tiene las suyas: otra app con el mismo `thread` empieza otra |
| `session` | o una sesión conocida, de esta misma key (la de otra key da 404) |
| `images` | `[{"media_type": "image/jpeg", "data": "<base64>"}]` — los modelos con visión las ven |
| `from`, `meta` | libres: viajan con el mensaje (ids de tu sistema, nombre del cliente) |
| `sent_at` | cuándo escribió el cliente (unix): ordena una ráfaga que llegó desordenada |
| `callback` | ver abajo |

Errores: `400` (sobre inválido), `401` (sin key o key inválida), `403` (agente fuera de la key, o callback no permitido), `404` (agente inexistente), `429` (límite).

## Tres formas de recibir la respuesta

- **JSON** — `POST /v1/messages`: el request espera al agente y devuelve el resultado.
- **Streaming** — `POST /v1/messages/stream`: Server-Sent Events con cada paso (`session`, `assistant`, `tool_call`…, `done`), como [`lampson run --json`](/es/docs/headless#json-los-eventos).
- **Callback** — `POST /v1/messages` con `"callback": "https://…"`: responde `202 {"job": "m…", "status": "queued"}` enseguida y, cuando el agente termina, Lampson hace un POST a tu URL. Es lo que necesitan los webhooks de WhatsApp y compañía, que exigen una respuesta rápida.

El callback lleva `{job, jobs, batch, status, agent, thread, session, text, steps, usage, stopped, meta}`. Va **firmado** con el secreto de la key que lo pidió, que `lampson key add` muestra una sola vez junto a la key: `X-Lampson-Signature: sha256=<HMAC-SHA256 del body>`, y `X-Lampson-Key` dice qué key es. Así, otra app que use el mismo Lampson no puede firmar un callback falso para la tuya. Las keys creadas antes de Lampson 0.5.1 firman con `LAMPSON_WEBHOOK_SECRET`, como antes. Verifícalo con el [SDK](/es/docs/sdk#verificar-un-callback) o:

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

`GET /v1/jobs/<id>` devuelve el estado de un mensaje enviado con callback.

## El buzón

Cada conversación (agente + thread) tiene su buzón. Esto viene resuelto, no hay que configurarlo:

- **Nunca dos turnos a la vez** sobre la misma conversación. Clientes distintos sí van en paralelo.
- **Las ráfagas se juntan.** El turno arranca tras 3 segundos sin mensajes nuevos (o a los 15 desde el primero): «hola» / «¿precio del pan sin gluten?» / «¿hay stock?» van en **un** turno y reciben **una** respuesta — la misma en los tres requests, con `batch` (los mensajes del lote) y `lead` (el primero). Con callback sale **un** POST por lote.
- **Lo que llega a mitad de turno** entra al turno en curso, antes de que el agente responda. Si llega mientras el modelo ya estaba escribiendo la respuesta, Lampson la descarta y responde de nuevo con todo: nunca sale una respuesta que ignora lo último que escribió el cliente.

La espera se ajusta por agente con `"buffer": {"quiet_s": 3, "max_s": 15}`, o `"buffer": false` para responder sin esperar (la fila sigue). → [Agentes](/es/docs/agents)

## Objetivos

Un [objetivo](/es/docs/objectives) es algo que un agente (o un [equipo](/es/docs/teams)) trabaja solo hasta terminarlo.

```sh
curl -X POST https://tu-lampson/w/tienda/v1/objectives -H "Authorization: Bearer lk_…" \
  -d '{"agent": "cto", "text": "Agregá filtrar por estado, con tests; pedime aprobación antes de mergear.", "budget_tokens": 400000}'
```

| | |
|---|---|
| `POST /v1/objectives` | crear: `{text, agent? \| team?, budget_tokens?, round_seconds?}` → `201` con el objetivo |
| `GET /v1/objectives` | los que esta key puede ver (los de sus agentes) |
| `GET /v1/objectives/<id>` | uno: `status` (`active`, `waiting`, `done`, `failed`, `cancelled`, `paused`), `progress` (último informe), `question` y `question_kind` (`question` o `approval`), `result`, `tasks` (su tablero), `ledger` (su registro), `spent` |
| `POST /v1/objectives/<id>/reply` | responder: `{text}` a una pregunta, `{approved: true\|false, text?}` a una aprobación |
| `POST /v1/objectives/<id>/cancel` | cortarlo |

Un objetivo `waiting` no avanza ni gasta hasta que respondas.

## Otros endpoints

| | |
|---|---|
| `GET /v1/agents` | los agentes que esta key puede usar |
| `GET /v1/jobs/<id>` | estado de un mensaje con callback |
| `POST /v1/mcp` · `/v1/mcp/stream` | MCP por HTTP → [Lampson como servidor MCP](/es/docs/mcp-server) |
| `GET /v1/openapi.json` | el OpenAPI 3.1 de esta API |

## OpenAPI

`/v1/openapi.json` describe **solo** la API pública — la interfaz web, la terminal y los webhooks de los canales no aparecen. Úsalo para generar un cliente en tu lenguaje (`openapi-generator` para Go, Java, C#, PHP…) o para probar la API desde tu herramienta favorita. Para JavaScript y Python ya hay [SDK](/es/docs/sdk).
