# What a Twitter Monitoring API Should Tell You When It Is Failing > Seven of the ten pages ranking for twitter monitoring api sell the happy path. None documents the fields that let you tell nothing matched from nothing was fetched. - **URL:** https://www.twitterapis.com/blogs/twitter-monitoring-api-coverage-honesty-2026 - **Published:** 2026-08-31 - **Author:** Emma - **Tags:** twitter monitoring api, x api monitoring, observability, webhooks --- > **TL;DR:** A monitor that has stopped and a week where nothing happened produce the identical output: nothing. Every vendor page ranking for this query sells latency and coverage as adjectives; none documents the fields that let you tell those two apart. This is that list. Four distinctions decide whether you can trust a monitoring product, and you can run them as a checklist against any vendor, including us. Search for a Twitter monitoring API and you get ten results from ten domains. Seven are pages selling monitoring. One is the platform's own docs, one is a GitHub repo, and one is a build-it-yourself tutorial. Every one of the seven leads on the same three words: real-time, reliable, complete. Not one of them tells you what the product does when it is none of those things. That is not laziness either. A vendor page cannot enumerate its own degradation states without immediately raising the question of how often they fire. So the information a buyer most needs is the information the format cannot contain. ## The problem underneath all of this A monitor produces events. When you receive none, exactly one of these is true: ::directive{id="img-1"} 1. Nothing matched your filter. The system is healthy and the world was quiet. 2. Nothing was fetched. The collector is dead, paused, rate-limited or stuck. 3. Something was fetched and dropped. It matched, and you did not get it. **These three look identical from the outside.** They are the same empty inbox. A monitoring product is trustworthy exactly to the degree that it lets you tell them apart, and almost every product on this SERP reports only case 1, silently, for all three. Canon in operations has a name for this: silence from a producer is not a clean result. A dead job and a quiet day are indistinguishable until something measures the difference. Everything below is that measurement. ## Distinction 1: point-in-time health against cumulative loss The single most misleading field in monitoring is a boolean called something like `degraded` or `healthy`. ::directive{id="img-2"} Ask what window it covers. A well-built `degraded` flag answers **"is the system serving this monitor right now"**. It is computed from the current polling cycle: did this tick fail entirely. That is genuinely useful, and it is deliberately NOT a memory of everything that has ever gone wrong. Which means a monitor can legitimately report: ``` degraded: false events_possibly_missed: 3835 status: paused last_poll_at: 15 days ago ``` Every one of those is correct. The flag is answering about the current tick, and a paused monitor has no current tick, so nothing is failing. The 3,835 accumulated earlier and lives in a different field. **The failure is not the boolean. The failure is having only the boolean.** A product that exposes `degraded` and nothing else is telling you the truth about a question you did not ask. What to require: a point-in-time health flag AND a cumulative loss counter, clearly labelled as different things. If a vendor offers one, ask for the other. If they cannot say which one theirs is, that is your answer. ## Distinction 2: zero as a measurement against zero as an absence `events_missed_last_24h: 0` reads like good news. ::directive{id="img-3"} It is good news only if something was running to miss them. For a paused or dead monitor, that zero is arithmetically correct and completely misleading: nothing is polling, so nothing can be recorded as missed. The same zero means two opposite things: ``` running monitor, 0 missed -> genuinely clean paused monitor, 0 missed -> nothing was even attempted ``` What to require: any zero-valued counter should sit next to a liveness field, so the reading is `0 missed, last polled 40 seconds ago` rather than a bare `0`. Absent that, treat every zero from a monitoring API as unverified until you have separately confirmed the collector is alive. This is the single most common way monitoring dashboards mislead, and it costs nothing to fix. It is also the one you can check in ten seconds on any vendor's response payload. ## Distinction 3: suppression that is a ceiling against suppression that is staleness A good monitoring API will tell you it withheld something. A great one tells you why, because the two reasons demand opposite responses. ::directive{id="img-4"} **Ceiling suppression.** You hit a daily delivery cap. The item matched, it was fresh, and the product refused to send it because you are over your limit. Response: raise the limit or tighten the filter. The item is recoverable. **Staleness suppression.** The item was already older than the freshness window when the monitor first saw it, so it was withheld rather than delivered as if it were new. Response: nothing. This is the freshness gate working as designed. Retrying cannot recover it, and it is not a fault. Collapsed into one `suppressed: 47` counter, those are indistinguishable, and the natural reading is the wrong one: people see suppression and assume they are over a limit. What to require: a breakdown, plus an explicit flag for the ceiling condition specifically. And check whether the breakdown is allowed to say it could not resolve itself. A product that reports `resolved: false` with a reason when its own numbers do not reconcile is more trustworthy than one whose counts always add up neatly. That last point deserves emphasis, because it inverts the usual instinct. **A field that sometimes admits it does not know is a better field than one that always produces a number.** ## Distinction 4: coverage, which is the one nobody sells Everything so far concerns items the monitor FETCHED. Distinction 4 is about items it never reached, and it is the one that decides whether "complete" on a vendor page means anything. ::directive{id="img-5"} Platform listings are finite. When a feed moves faster than your poll interval, the listing can be exhausted before the poller reaches the point where the previous poll finished. The posts in that gap were never fetched, so they were never matched, so they appear in NO counter. Not as missed, not as suppressed, not as delivered. They are simply absent, and every count on the page still reads clean. This is why a monitoring product needs a coverage field that is separate from its delivery counters, with at least four states: ``` complete every poll reached the previous poll's stopping point degraded at least one poll was truncated and items were lost unrecoverably partial nothing found, but not every loss mode was checked unknown the check could not run at all ``` The distinction between `degraded` and `unknown` is the whole point. One says loss happened. The other says we could not tell. Products that lack the fourth state report `unknown` as `complete`, which is the fail-open direction. What to require: ask directly whether the vendor can tell you about posts it never fetched. Most cannot, and the honest ones will say so. A vendor that answers "our coverage is 100 percent" without explaining how they measure the gap is answering a question about their intentions, not their instrumentation. ## Distinction 5: the cadence you set against the cadence you get You configure a monitor at 30 seconds. You assume it polls every 30 seconds. ::directive{id="img-6"} That holds only while the poller has capacity. A shared poller with a per-cycle stream limit works through a queue, and when the registry outgrows one pass, some streams wait for the next. Your effective interval becomes a multiple of the one you chose, and nothing about the monitor's own configuration reveals it, because the configuration is still 30. This is a fleet-level property, invisible from a single monitor's settings, and it is why a `poll_capacity` reading matters: ``` streams_registered 75 streams_per_cycle_max 40 cadence_inflation 1.88x ``` Read that as: the interval you set is up to 1.88 times longer in practice. Note what an honest version of this field does NOT do. It does not claim that inflation caused a late poll unless it measured one. "Your cadence may be inflated and we have not observed a missed poll" is a smaller, truer statement than "everything is fine", and it is a much better field than a confident number derived from a biased sample. What to require: ask whether the poller is shared and whether capacity is exposed. If the answer to the first is yes and the second is no, your configured interval is a request, not a guarantee. ## The checklist, which is the point of the post Run this against any monitoring vendor, including the ones ranking above this page, and including us. Every item is answerable from a response payload or a support email in under an hour. ::directive{id="img-7"} | Ask | What a good answer looks like | What its absence hides | |---|---|---| | Is your health flag point-in-time or cumulative? | Named as one, with the other exposed separately | A boolean that reads healthy on a monitor dead for weeks | | Does a zero counter sit beside a liveness field? | `0 missed, last polled 40s ago` | A dead collector reporting a clean zero | | Do you split suppression by reason? | ceiling against staleness, with a resolved flag | "Over your limit" read into what was a freshness withhold | | Can you tell me about items you never fetched? | A coverage state with an explicit unknown | Truncated listings counted nowhere, every counter clean | | Is the poller shared, and is capacity exposed? | `streams_registered` against `per_cycle_max` | A configured interval that is a request, not a guarantee | | What happens to a failed delivery? | Retry policy, dead-letter, whether a failed call bills | Silent drops indistinguishable from no matches | Six questions. A vendor that can answer all six is not necessarily better at monitoring than one that cannot, but it is measurably more honest about what it does not know, and over a year of operating a monitor that difference is worth more than a latency figure. ## Webhooks do not remove the problem, they move it The usual answer to all of this is push instead of poll: register a webhook and stop worrying about intervals. ::directive{id="img-8"} Webhooks change which failures you have. They do not remove failure. **Delivery is now a network call to you.** Your endpoint returns 500 during a deploy, or times out, and the event is gone unless the vendor retries. Ask what the retry policy is and whether there is a dead-letter queue you can read. **Silence is still ambiguous.** An empty webhook stream means the same three things as an empty poll result, and now you cannot even inspect the poller. **Ordering and duplicates.** At-least-once delivery is the norm, so your handler must be idempotent. Key on the event id, not on arrival order. So the checklist does not change for webhooks. One row changes shape: "what happens to a failed delivery" stops being theoretical and becomes the most important question you will ask. ## Building the check yourself, in about twenty lines Whatever your vendor exposes, the one thing you can always do is verify liveness independently. If a monitor claims to be watching a busy account, then over any window long enough for that account to post, a monitor that returns nothing is suspect. ::directive{id="img-9"} ```python import os, requests, datetime KEY = os.environ["TWITTERAPIS_KEY"] BASE = "https://api.twitterapis.com/twitter" def last_post_age_seconds(handle): r = requests.get(f"{BASE}/user/tweets", headers={"x-api-key": KEY}, params={"userName": handle}, timeout=30) r.raise_for_status() tweets = r.json().get("tweets") or [] if not tweets: return None ts = tweets[0].get("created_at") dt = datetime.datetime.strptime(ts, "%a %b %d %H:%M:%S %z %Y") return (datetime.datetime.now(datetime.timezone.utc) - dt).total_seconds() # A canary account that posts reliably. If it has posted and your monitor # delivered nothing in the same window, the silence is not the world being quiet. age = last_post_age_seconds("XBusiness") print(f"canary last posted {age/3600:.1f}h ago" if age else "canary: no posts returned") ``` One call, $0.0008. Run it beside your monitor and compare. This is a positive control, and it is the only construction that distinguishes "quiet" from "broken" without trusting the thing under test. The principle generalises well beyond monitoring: a check that cannot fail when the system is broken is not a check. If your alerting has never fired, that is not evidence it works, it is an untested assumption wearing the clothes of a passing test. Break it deliberately once, in a window you choose, and find out. ## Four failure modes, and what each looks like from the outside Abstract distinctions are easier to hold once you have seen the shape each one makes in your data. These are the four that account for most monitoring incidents, written as symptoms rather than causes, because symptoms are what you actually get. ::directive{id="img-10"} ### The collector that stopped in March **Symptom:** a clean series that simply ends, and nobody notices until somebody asks for a chart. This is the most common and most expensive failure in monitoring, and it has nothing to do with the API. A scheduled job dies, the series stops accumulating, and every dashboard built on it keeps rendering the last known values without complaint. Six weeks later a decision gets made on data that stopped three months earlier. **What catches it:** an alert on the ABSENCE of writes, not on errors. Most alerting fires when something goes wrong; this needs alerting that fires when nothing goes right. If your collector has not written a row in twice its expected interval, that is the alert, and it must go somewhere a person reads. **Why it survives so long:** the failure produces no error anywhere. There is no exception, no 500, no red line. There is simply less data than there should be, and less data looks exactly like a quiet period. ### The filter that quietly stopped matching **Symptom:** volume drops to near zero and stays there, and the drop looks like a market change. A competitor renames their handle. A product gets rebranded. A hashtag falls out of use. Your filter is still valid, still runs, still returns successfully, and now matches almost nothing. Every health field is green because nothing is failing. **What catches it:** track match RATE as a series, not just matches. A filter that returned 40 items a day for six months and now returns 2 has either witnessed a genuine collapse in the conversation or stopped matching, and the way to tell is a second broader filter running beside it as a control. If the broad one held and the narrow one collapsed, it is your filter. ### The delivery endpoint that started failing during a deploy **Symptom:** a gap of exactly the length of your deploy window, then normal service. Push delivery is a network call to infrastructure you control, and your infrastructure has downtime. If the vendor does not retry, or retries three times over thirty seconds while your deploy takes four minutes, those events are gone and nothing on either side reports a loss: the vendor sent them, you 500ed, both sides consider the transaction complete. **What catches it:** a dead-letter queue you can read, and knowing the retry policy BEFORE you need it. Ask the question when you sign, not when you have a gap. ### The rate limit that degrades instead of erroring **Symptom:** everything works, slightly less often, forever. The failure people expect from rate limiting is a 429. The failure they get is a queue: requests are accepted, served late, and the effective interval stretches. Nothing errors. Your monitor is simply less real-time than you configured, permanently, and the only visible sign is a cadence figure most products do not expose. **What catches it:** comparing configured interval against observed interval, which requires the product to tell you when it actually polled. If `last_poll_at` is not in the response, you cannot compute this at all, which is why it is on the checklist. ## Instrumenting your own side, which is the half you control You cannot fix a vendor's fields. You can make your own side legible, and three properties do most of the work. **Store the observation time, not just the value.** Every row gets a `captured_at`. Follower counts, engagement counts and match counts are all moving targets, and a value without its timestamp cannot be compared to anything later. This is the single highest-value habit in the list and it costs one column. **Make writes idempotent.** Key on `(monitor_id, event_id)` so a retry repairs a gap rather than double-counting. Without it, one replayed webhook silently inflates every aggregate downstream, and the corruption is invisible because the numbers stay plausible. **Log what you asked for, not only what you got.** Record the filter, the interval and the window with each batch. When volume changes six weeks later, the first question is whether the query changed, and an un-logged filter cannot answer it. A comment that disagrees with the code beside it is a defect report; an unrecorded query is worse, because there is nothing to disagree with. ## What we would want a competitor to point out **This checklist favours products with rich instrumentation, and rich instrumentation is not the same as good coverage.** A product could expose every field named here and still miss more posts than a simpler competitor that exposes none. The fields tell you what a product KNOWS about its own gaps, not how large those gaps are. Both matter, and only one of them is on this page. **Nothing here is measured against named competitors.** We read the SERP and observed that seven of ten vendor pages document no degradation states. We did not test their products, and absence of documentation is not evidence of absence of capability. Several of them may handle all six questions well and simply not publish it, which is exactly why the recommendation is to ASK rather than to assume. **The canary technique has a blind spot.** It proves the collector is alive and reaching a busy account. It does not prove your specific filter is correct, and a monitor can be perfectly live while watching the wrong thing. That is what the match-rate series in the second failure mode is for. The narrow claim this post will defend: the three-way ambiguity of an empty result is real, it is unaddressed by every page currently ranking for this query, and six questions resolve it in an afternoon. ## What the platform itself is doing, and why it matters here The monitoring question does not sit still, because the platform keeps changing what it sells directly. https://x.com/XBusiness/status/2092614843220074912 That is X's own business account announcing Lead Gen Ads, and it is worth reading as a signal about direction rather than as a product pitch: the platform's first-party answer to "how do I find people" is increasingly an advertising product. Monitoring the public conversation through an API is a different route to a different question, and the two are not substitutes. Practitioners argue about this constantly, and the argument is more useful than most vendor pages: https://www.reddit.com/r/socialmedia/comments/1ah8xqz/best_dm_automation_tools/ For the mechanics of getting credentialed on the official path, this covers the console steps that change most often: https://www.youtube.com/watch?v=ODXlxzmX5-A ## Common objections, answered honestly **"This is a lot of ceremony for a mentions feed."** If you are watching your own brand casually, it is. The checklist matters when a monitor feeds something that acts: an alert that pages someone, a support queue, a trading signal, a compliance log. The cost of a silent gap scales with what depends on it, and for a casual feed the cost is near zero. **"Surely any paid product handles this."** Measured against this SERP, most do not publish enough to tell. That is not the same as failing, and this post is deliberately not claiming any named vendor is bad. It is claiming that seven of ten pages selling monitoring do not document a single degradation state, so a buyer cannot distinguish a product that handles it from one that does not without asking. **"Why would a vendor publish its own failure modes?"** Because the alternative is being indistinguishable from products that have no failure modes documented because they have not thought about them. Naming your degraded states is a costly signal, and costly signals are the ones worth reading. **"Our vendor says coverage is 99.9 percent."** Ask how that is measured. Coverage against what denominator? A figure computed over items the system fetched is arithmetically fine and answers a different question, because items never fetched are absent from both numerator and denominator. The number can be true and still tell you nothing about the gap you care about. This is not an accusation, it is a question with a good answer available, and a vendor who has thought about it will have one ready. **"We use webhooks, so this does not apply."** It applies with one row changed. See the webhook section above: push moves the failure to delivery, it does not remove it. ## FAQ **How do I tell whether a Twitter monitor is broken or the world is just quiet?** You cannot, from the monitor alone. Run an independent positive control: pick an account that posts reliably, check separately whether it has posted in the window, and compare. If the canary posted and your monitor delivered nothing, the silence is not the world being quiet. **What does a `degraded: false` flag actually mean?** On a well-built API it means the current polling cycle is working, not that nothing has ever gone wrong. A paused monitor with thousands of historically missed events can correctly report `degraded: false`, because nothing is currently failing. Ask for the cumulative counter separately. **Why would a monitoring API withhold an item it matched?** Two reasons that demand opposite responses: you hit a delivery ceiling (recoverable, raise the limit or tighten the filter), or the item was already stale when first seen (not recoverable, and not a fault). A product that reports one number for both is telling you less than it knows. **What is coverage and why is it separate from delivery counts?** Delivery counters only describe items that were fetched. If a platform listing was exhausted before the poller reached its previous stopping point, those items were never fetched, never matched, and appear in no counter at all. Coverage is the separate field that speaks to what was never reached. **Does configuring a 30-second interval guarantee a 30-second interval?** Not on a shared poller. If the registry has outgrown one pass, some streams wait for a later cycle and the effective interval is a multiple of the configured one. Ask whether poll capacity is exposed. ## The verdict Seven of the ten pages ranking for this query sell monitoring on three adjectives. None of them documents the fields that let you tell nothing matched from nothing was fetched, or a delivery ceiling from a freshness withhold, or a genuine zero from a dead collector. Those distinctions are not exotic. They are the difference between a monitor you can act on and a monitor you merely have. Take the six-question checklist to whichever vendor you are evaluating, including this one. Send it as an email, not a call, so the answers are written down and comparable across vendors. The answers, and more tellingly which questions produce a pause, will tell you more in an afternoon than any comparison page will, this one included. ## Frequently Asked Questions ### How do I tell whether a Twitter monitor is broken or the world is just quiet? You cannot, from the monitor alone. Run an independent positive control: pick an account that posts reliably, check separately whether it has posted in the window, and compare. If the canary posted and your monitor delivered nothing, the silence is not the world being quiet. ### What does a `degraded: false` flag actually mean? On a well-built API it means the current polling cycle is working, not that nothing has ever gone wrong. A paused monitor with thousands of historically missed events can correctly report `degraded: false`, because nothing is currently failing. Ask for the cumulative counter separately. ### Why would a monitoring API withhold an item it matched? Two reasons that demand opposite responses: you hit a delivery ceiling (recoverable, raise the limit or tighten the filter), or the item was already stale when first seen (not recoverable, and not a fault). A product that reports one number for both is telling you less than it knows. ### What is coverage and why is it separate from delivery counts? Delivery counters only describe items that were fetched. If a platform listing was exhausted before the poller reached its previous stopping point, those items were never fetched, never matched, and appear in no counter at all. Coverage is the separate field that speaks to what was never reached. ### Does configuring a 30-second interval guarantee a 30-second interval? Not on a shared poller. If the registry has outgrown one pass, some streams wait for a later cycle and the effective interval is a multiple of the configured one. Ask whether poll capacity is exposed.