Monitor Deliveries API
Returns your most recent monitor delivery events, most recent first, each carrying the actual measured lag: detected_lag_ms is X's own post timestamp subtracted from the moment our scheduler enqueued the delivery (i.e. real detection latency, bound by the current poll interval), and delivery_lag_ms is the separate queue-to-webhook-POST time. Either can be null for an older event whose payload predates this field. Cost: Free per call.
GET monitor/deliveries returns your most recent monitor delivery events across all monitors, newest first. Each event includes detected_lag_ms (time from tweet creation to detection) and delivery_lag_ms (time from queue to webhook POST), plus id, monitor_id, tweet_id, status, tweet_created_at, detected_at, delivered_at, total_lag_ms, and, for a failed delivery, attempts, last_status_code and last_error. Results are capped by the limit parameter, default 50, max 200.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Query Parameters
Max events to return, 1-200. Defaults to 50.
Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.
Set to 1 (or true) to apply the built-in compact preset: ids, url, text, created_at, lang, the engagement counts, the is_retweet/is_reply/is_quote flags, conversation ids, the author's id/username/name/followers_count/verification, and the quoted or retweeted tweet's id/url/author username. The preset trims what it recognises and leaves alone what it would empty, so it never turns a body into {}. Combine with fields to add paths on top of the preset. Typically cuts a tweet page by 70 to 90 percent for LLM tool callers.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/monitor/deliveries?limit=50&fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1"{ "deliveries": [ { "id": "79a94efd-8b6c-46f7-afa5-1fecdf1250a1", "monitor_id": "bd964ae0-7763-4dd6-9295-233d9badf6f9", "tweet_id": "2087910515246784773", "status": "delivered", "tweet_created_at": "Thu Aug 13 14:33:52 +0000 2026", "detected_at": "2026-08-13T14:34:25.984Z", "delivered_at": "2026-08-13T14:34:29.580Z", "detected_lag_ms": 33984, "delivery_lag_ms": 3596, "total_lag_ms": 37580, "attempts": 1, "last_status_code": 204, "last_error": null }, { "id": "9a0f6041-2c7e-4f4a-9c2d-0b1e6d3a4672", "monitor_id": "bd964ae0-7763-4dd6-9295-233d9badf6f9", "tweet_id": "2087910515246784774", "status": "dead", "tweet_created_at": "Thu Aug 13 14:33:52 +0000 2026", "detected_at": "2026-08-13T14:34:25.984Z", "delivered_at": null, "detected_lag_ms": 33984, "delivery_lag_ms": null, "total_lag_ms": null, "attempts": 8, "last_status_code": 400, "last_error": "non-2xx status 400" } ], "count": 2}{ "error": "bad_request", "message": "Missing or malformed parameter. Fix the request before retrying."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "not_found", "message": "The resource does not exist, for example a deleted tweet or a private account."}{ "error": "rate_limited", "message": "Too many requests. Back off and retry with exponential backoff."}{ "error": "server_error", "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}Pricing
| Unit | Price |
|---|---|
| Per call | Free |
When to use
Use this endpoint to audit what a monitor actually sent, including exact detection and delivery latency for each event, rather than to configure or list monitors themselves. Reach for it when a webhook consumer reports missing or delayed events and you need the per-event timing breakdown across all monitors, not just one.
Notes
- Scoped to your own key's deliveries only.
- detected_lag_ms measures the real gap from a post existing to us noticing it, the honest number for "how fast is monitoring" -- currently bound by the shared 60s poll interval, not a guaranteed SLA.
- A null lag field means tweet_created_at or delivered_at was unavailable for that specific event, not an error.
- status is pending, delivered or dead. A dead delivery exhausted all 8 attempts, or the destination returned 410 Gone, in which case the webhook is disabled too.
- attempts, last_status_code and last_error are the diagnosis for a failed delivery: how many times we tried, the HTTP status your destination returned on the last attempt, and our own client-side error when there was no response at all (a timeout, a DNS failure, a refused connection). last_status_code is null when the request never got a response, and last_error is null on a delivered event.
Related endpoints
- Create Monitor: Watch an X account for new posts and push them to your webhook(s).
- List Monitors: List every monitor on your account.
FAQ
How many delivery events can I fetch in one call, and what's the default?
Use the limit parameter, an integer from 1 to 200. If you omit it, the endpoint returns 50 events. Request 200 and paginate by timestamp on your side if you need a longer history than one call provides.
How do I tell whether a delay was in detection or in delivery?
Each event in the deliveries array carries detected_lag_ms (time from the tweet's actual creation to when the system detected it) and delivery_lag_ms (time from that detection queue to the webhook POST) separately, plus total_lag_ms as their sum. Compare the two fields to see whether a slow event was a detection problem or a delivery problem.
Account Monitor Health GET
Returns a single-call summary of your entire monitoring setup: overall status, how many of your monitors are active vs paused, and how many delivery attempts in the last 24 hours were pending, delivered, or failed. Distinct from Monitor Health above, which reports one monitor's cursor state, not your whole account's. Cost: Free per call.
Compat: Add User to Tweet Monitoring POST
An x_user_stream-shaped request/response envelope, translated onto the exact same underlying monitor system as POST /twitter/monitor -- not a second capability, one system with two request shapes in front of it. Migrating an integration already built against that shape? Point it at this path instead of rewriting it against /twitter/monitor. Free: account administration, not a metered read, billed identically to /twitter/monitor. Cost: Free per call.