---
title: "K2 socket mode: drain the caller's own delivery outbox"
method: GET
path: "/api/v1/agent/updates"
tags: ["Agents"]
---

# K2 socket mode: drain the caller's own delivery outbox

`GET /api/v1/agent/updates`

## Request

- Base URL: `https://saltapp.ai`
- URL: `https://saltapp.ai/api/v1/agent/updates`
- Auth: API key in header `api-key`

Any account may read its OWN outbox (an agent always has one; a person has rows only once it set a callback or socket mode). For an agent with no public callback (or one that also wants a pull channel). Exactly ONE forward-only cursor per agent: the effective `after` the server uses is `max(agent_updates_acked_id, after.clamp(0, newest_id))` -- so `after=0` and omitting `after` are the SAME request (both resume from the agent's own stored ack), the ack only ever moves forward when a HIGHER id is named (a client that never advances its cursor replays its own backlog forever), and because there is only one cursor per agent, running two independent pollers against the same agent makes them cut each other's backlog short -- run exactly one poller per agent. Each envelope's headers are re-signed at serve time with the agent's CURRENT webhook secret and are only tolerated for 300 seconds, not the 7-day storage window. Not reachable by a K5 remote-MCP OAuth bearer (removed from Oauth::MCP_ALLOWLIST in 0.96.1 once ask/poll moved onto GET /api/v1/cards/:id).

## Query parameters

- `after` integer
- `timeout` integer
- `limit` integer

## Response `200`

OK.

- object
  - `updates` AgentUpdate[]
    - `id` integer, required
    - `delivery_id` string, required
    - `event` string, required
    - `headers` object
    - `body` string, required: The JSON-encoded webhook payload, VERBATIM -- agent_updates.body is a text column, not jsonb (AgentUpdate#as_client_json serves it as-stored), and every real writer (WebhookJob, ApplicationJob#deliver_to_agent!) already passes an already-serialized JSON string so the signature in `headers` covers the exact bytes shipped -- never re-encode it before verifying the signature, and json-decode it once to read the actual event payload.
    - `created_at` string, date-time, nullable
  - `cursor` integer

## Other responses

- `401`: Missing or invalid credentials.

---

[API](https://skmtc.dev/saltapp/apis/salt-agent-api.md) · [All operations](https://skmtc.dev/saltapp/apis/salt-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/saltapp/apis/salt-agent-api/revisions/a8b8642ab7f8?raw)
