# An endpoint your app posts to

**Give a system a URL of its own. What it sends lands in your inbox, filtered and stamped the way you configured, and it can do nothing else.**

Anything that can make an HTTP request can put work into your inbox: your own app, a form, a helpdesk, an automation nobody wants to give a Flow account to. You publish an endpoint for it — one URL, one token, and the only thing either can do is write a capture. It cannot read your inbox, cannot see a task and cannot reach a project. What you configure on it is four separate things: which deliveries count, what every capture from it is stamped with, where the source’s own id lives so a retry does not double, and which line of the payload a person should read when the inbox is looked at. A delivery that does not match is not an error — the source did nothing wrong — so it is dropped and counted, and the counters are where a rule written against the wrong field stops being silent. The payload is stored exactly as it arrived, because what makes an inbox worth having is that nothing was decided or discarded on the way in. When the token leaks you rotate it and the URL stays; when the integration ends you revoke the endpoint, and everything it ever captured stays where it is.

Driven by an agent. Every step below is a step in
`packages/server/tests/e2e`, run against a listening server on every pull
request; the calls under each one are what that run executed.

The same flow is playable at https://flow.ttoss.dev/docs/examples/an-endpoint-for-an-app.

## 1. Ana creates a project for the app she is on call for

- `POST /api/v1/projects` → `201`

## 2. She publishes an endpoint for it, and sees the token once

- `POST /api/v1/ingest-endpoints` → `201`

## 3. Her app posts an event, and it lands in her inbox

- `POST /api/ingest/ing_p5se7svb84` → `201`

## 4. It arrived stamped with what she configured, and otherwise untouched

- `GET /api/v1/captures` → `200`

## 5. The same event, sent twice, is still one capture

- `POST /api/ingest/ing_p5se7svb84` → `200`

## 6. A delivery from something else is dropped, not refused

- `POST /api/ingest/ing_p5se7svb84` → `200`

## 7. She can see that it was dropped, and why

- `GET /api/v1/ingest-endpoints/ing_p5se7svb84` → `200`

## 8. She triages the event into the project it named

- `POST /api/v1/captures/cap_74wdjv4n12/triage` → `201`
- `GET /api/v1/tasks/task_0nn08p750g` → `200`
- `GET /api/v1/captures?triaged=true` → `200`

## 9. The token leaks, so she rotates it — the URL does not change

- `POST /api/v1/ingest-endpoints/ing_p5se7svb84/rotate` → `200`
- `POST /api/ingest/ing_p5se7svb84` → `401`
- `POST /api/ingest/ing_p5se7svb84` → `201`

## 10. The integration ends, so she revokes the endpoint

- `DELETE /api/v1/ingest-endpoints/ing_p5se7svb84` → `204`
- `POST /api/ingest/ing_p5se7svb84` → `404`

## 11. Everything it captured is still hers

- `GET /api/v1/captures?triaged=true` → `200`
