A market being talked about and a market being bought into look identical on a chart.
DemandGraph separates them. Send the signals you already collect — search, developer, product, hiring, social, commerce — and get back four measures that disagree with each other on purpose: how fast it is moving, whether that rate is still climbing, how much of it is buying rather than reading, and whether it holds up across sources.
Runs the same engine the paid endpoint uses. Nothing is stored and no key is needed.
Press “Score this topic” to call the live API.
You can see that a number went up. You can’t tell whether it means anything.
Every demand tool you already have reports volume. Volume is the one thing that does not tell you whether to act — a huge flat market and a small market tripling produce the same impressive-looking chart.
Size is mistaken for opportunity
The biggest number wins the meeting. But a category with a million searches and no growth is a category with entrenched incumbents and no opening, and a category with four thousand searches doubling every month is the one that will be contested in a year.
Attention is mistaken for demand
A launch trends, a thread goes viral, a keyword spikes. None of that is a buying signal. Read-intent and buy-intent move on completely different curves, and one flat average across your sources hides which of them you are actually looking at.
Every source is scored the same
A spike in social mentions and a spike in job postings for the same skill are not equally informative, but almost every dashboard adds them together unweighted. A company hiring for something has already committed budget to it. A person posting about it has not.
Nobody bills you for backing the wrong market. You pay for it in quarters.
Demand decisions are expensive because they are slow to disprove. By the time the number tells you the answer, you have already spent the year.
-
Roadmap
Two quarters spent building into a category that had already peaked
The signal looked strong when the decision was made because the level was high. Nobody checked whether the rate had already turned. Momentum and acceleration disagree at exactly the moment that matters, and only one of them was on the chart.
-
Go-to-market
A launch aimed at an audience that reads but does not buy
The topic was genuinely growing — in social and search, not in hiring or commerce. High momentum, near-zero commercial intent. The content performed, the pipeline did not, and the post-mortem blamed the messaging.
-
Investment
A thesis built on a spike that never had a second week
One source, one window, one enormous number. A durability score would have said so immediately: a single viral day and a sustained six-month climb are trivially distinguishable, but only if something is looking at direction agreement rather than totals.
Four measures that can contradict each other.
A single demand score is worthless, because the interesting cases are exactly the ones where the components disagree. DemandGraph reports them separately and tells you how much to trust the result.
| Measure | What it answers | Range |
|---|---|---|
| momentum | How fast is it moving? A rate of change, not a level — so a large flat market scores 0 and a small tripling one scores high. | −100…100 |
| acceleration | Is the rate itself still climbing? This is what separates “big” from “taking off”, and it turns negative before momentum does. | −100…100 |
| commercialIntent | How much of the signal is buying rather than reading? Weighted toward commerce, hiring and product sources. | 0…100 |
| durability | Do the sources agree on direction over time? A single spike inside noise scores low however large it is. | 0…100 |
| confidence | How much do the inputs support any of the above? Thin evidence is reported as thin rather than dressed up. | 0…100 |
Observations in Aligned per source Weighted Four measures Confidence Ranked
-
01
You send observations
A topic and a list of dated values, each tagged with the source it came from. From your own analytics, a licensed feed, an ATS export or an internal warehouse — whatever you already have.
-
02
Each source is measured on its own curve
Sources are never pooled into one series. Search volume in the thousands and job postings in the dozens are measured as rates within their own source, so the large number cannot drown the informative one.
-
03
Weighted, and the weights are published
Commerce 1.0, employment 0.9, developer 0.7, product 0.6, search 0.5, social 0.3 — because committed budget predicts spend better than a mention does. Override any of them per request.
-
04
Four measures, reported separately
Momentum, acceleration, commercial intent and durability come back as distinct numbers, with a per-source breakdown showing exactly which source contributed what.
-
05
Confidence attached
Derived from breadth of sources, depth of observations and length of window. A score built on one source over two days says so, so you can discard it instead of acting on it.
-
06
Ranked across topics
Send up to 200 topics in one request and get them ordered by momentum, with confidence breaking ties — so a thin spike can never outrank a well-evidenced climb.
This is what a scored topic looks like when it reaches your code.
One element of the scores array returned by POST /v1/scores — three months of search volume plus a hiring signal for the same topic.
{
"topic": "mcp servers",
"momentum": 100,
"acceleration": 53.6,
"commercialIntent": 64.3,
"durability": 100,
"trend": "accelerating",
"sourceCount": 2,
"confidence": 64,
"breakdown": [
{ "source": "search", "points": 3, "changePct": 300, "weight": 0.5 },
{ "source": "employment", "points": 2, "changePct": 291.7, "weight": 0.9 }
],
"windowStart": "2026-06-01T00:00:00.000Z",
"windowEnd": "2026-08-01T00:00:00.000Z"
}
Confidence is 64, not 100
Two sources over a two-month window is a real signal but not a strong one. The score says so rather than presenting a thin read with the same authority as a broad one. Add a third source or a longer window and it climbs.
The breakdown is the audit trail
Every source that contributed is listed with its point count, its own rate of change and the weight applied. You can recompute the headline number by hand, which means you can defend it in a meeting.
You supply the observations
DemandGraph scores what you send it. It does not acquire, resell or redistribute signal data — which is what keeps it free of the licensing and redistribution constraints that make most demand data awkward to build on.
This service is newly launched. We publish no uptime percentage, customer count, logo wall or certification claim until we have the operating history to support one.
Two calls from zero to a ranked list
Create a key
POST your email to
/v1/keys. You get 50 scored topics a month, no card. The key works only on DemandGraph.Send observations
POST one or more topics, each with at least two dated, source-tagged values. Two points is the minimum — a single point has no rate of change, and the API tells you so rather than guessing.
Read ranked scores
Topics come back ordered by momentum with confidence breaking ties, each with its four measures and a per-source breakdown. Billing is one unit per topic scored.
Why hiring counts for three times a mention
These are explicit and auditable rather than learned. A company posting a role has already committed budget; a person posting an opinion has not. Override any of them per request via weights.
- commerce1.0
- employment0.9
- developer0.7
- product0.6
- search0.5
- social0.3
Small surface, versioned, OpenAPI-first
Authenticate with Authorization: Bearer <key>. Every error returns a stable code and a requestId you can quote.
/v1/keysPublic. Issues a free key against your email — 50 scored topics a month, no card./v1/scoresScore and rank up to 200 topics. Billed one unit per topic scored./v1/demo/scorePublic. Real engine, capped at 3 topics and 60 observations. No key required — it is what the demo above calls./v1/weightsPublic. The default source weights and the reasoning behind them./v1/checkoutPublic. Returns a Square-hosted payment URL for a paid tier.curl -X POST https://web-production-37b02.up.railway.app/v1/scores \ -H "Authorization: Bearer $DEMANDGRAPH_KEY" \ -H "content-type: application/json" \ -d '{"topics":[{"topic":"mcp servers","points":[ {"source":"search","at":"2026-06-01T00:00:00Z","value":1200}, {"source":"search","at":"2026-08-01T00:00:00Z","value":4800}]}]}'
Python and TypeScript SDKs Service health: https://web-production-37b02.up.railway.app/health
Priced per scored topic, capped so a runaway job can’t surprise you
One unit is one topic scored, so a 50-topic request bills 50. Every plan includes an allowance, then a per-unit overage that is hard-capped per billing period — your worst-case bill is the base price plus the cap, never more.
- 5,000 scored topics included
- $0.08 per additional scored topic
- Overage capped at $500 per period
- Full API access, Python and TypeScript SDKs
- 30,000 scored topics included
- $0.05 per additional scored topic
- Overage capped at $2,000 per period
- Full API access, Python and TypeScript SDKs
- 100,000 scored topics included
- $0.03 per additional scored topic
- Overage capped at $5,000 per period
- Full API access, Python and TypeScript SDKs
- 300,000 scored topics included
- $0.02 per additional scored topic
- Overage capped at $10,000 per period
- Full API access, Python and TypeScript SDKs
Free tier: 50 scored topics per month, no card. Prices in USD, billed monthly. Payment is processed by Square through our shared billing platform; card details never touch this site.
What counts as a scored topic?
What happens when I hit my allowance?
Where does the data come from?
Why not one demand score?
Can I change the source weights?
weights object. The defaults are published at GET /v1/weights along with the reasoning, and the applied weights are echoed back in every response so a score is always reproducible.Can I evaluate it before paying?
Find out which one is actually growing.
The free tier is 50 scored topics a month, no card. Create a key, post two observations of a topic, and the response comes back with all four measures and a confidence score.
curl -X POST https://web-production-37b02.up.railway.app/v1/keys \ -H "content-type: application/json" \ -d '{"email":"you@company.com","name":"Evaluation key"}'