Predictive Signals: who in your audience is in market
Predictive Signals: who in your audience is in market
Base URL: https://api.delivr.ai
Version: v1
Authentication: Organization API key. Send X-Api-Key: <dlvr_...> and X-Api-Secret: <secret> on every request (both required). Create the key + secret in the dashboard at https://app.delivr.ai/{org_id}/settings/api-keys.
Once you have an intents audience, Predictive Signals answers the next questions. Which of its members are showing buying intent right now? Which companies do they roll up to? Is that intent accelerating or fading?
See the Predictive Signals reference for the full request and response schemas.
The audience calls
| Call | Answers |
|---|---|
GET /api/v1/signals/audiences/{id} | How many members are in market right now, broken out by momentum, plus the top companies. |
GET /api/v1/signals/audiences/{id}/history?range= | The same counts over the last 30, 90 (default), 180, or 365 days. |
GET /api/v1/signals/audiences/{id}/topics | Which topics this audience concentrates in or avoids, against an archived day. |
GET /api/v1/signals/audiences/{id}/members?state= | The people in one state, one page at a time. |
GET /api/v1/signals/audiences/{id}/members/download?state= | The same people as one CSV file. |
All five take the audience's numeric id in the path. Per-person lookups are covered under "Trends for one person" below.
In market and momentum
A member counts as in market when they were active on 3 or more of the last 14 days. The activity must be on the audience's defining topics, at high, medium or low score (the document's definition.scores). The in-market status is computed daily after 13:40 UTC over the trailing 14-day window ending on the document's day.
Every member with intent, in market or not, is also bucketed into a single best momentum tier, checked in this order:
new: first seen active on a defining topic within the window.rising: this week's activity is at least 1.5x the prior week's.steady: roughly flat week over week.cooling: this week's activity is at most half the prior week's.
A member is counted once, under the highest tier that applies. Members with no trend, such as those whose only intent is low score, count as unknown.
Each by_topic and top_companies row counts its people three ways. with_intent is everyone with any intent on that topic or at that company. in_market is the part of them that is in market. rising_or_new is the part of them that is new or rising, in market or not, so it is not a subset of in_market.
Buying groups
Each top_companies row also shows who is researching at that company. Present from version 6.
decision_makerscounts people at C-level, VP or Director seniority.managerscounts managers.othercounts everyone else, including staff and people with no known seniority. The three sum towith_intent.departmentslists up to 3 departments as{department, people}, most people first.department_countcounts every department among the people with intent, including those not listed. People with no known department are not counted.buying_groupistruewhen at least 3 people at the company are researching your topics, across 2 or more departments, including a decision maker (Director, VP or C-level).
The document's definition.buying_group carries the rule as numbers: min_people 3, min_departments 2, min_decision_makers 1, and decision_maker_seniority ["cxo", "vp", "director"].
On documents before version 6, these keys are absent, not 0. They are also absent on a row whose roles are unknown. Treat a missing key as unknown, not as zero people.
Reading the overview
GET /api/v1/signals/audiences/{id}?project_id=YOUR_PROJECT_ID
{
"audience_id": "10482",
"view": "intents",
"status": "ready",
"signals": {
"day": "20260921",
"members": 48213,
"with_intent": 9104,
"in_market": 2211,
"momentum": { "new": 2340, "rising": 588, "steady": 1102, "cooling": 1181, "unknown": 3893 },
"top_companies": [
{
"company_domain": "acme.com", "with_intent": 14, "in_market": 3, "rising_or_new": 6,
"decision_makers": 4, "managers": 6, "other": 4,
"departments": [{ "department": "Sales", "people": 6 }, { "department": "Marketing", "people": 5 }],
"department_count": 2,
"buying_group": true
}
]
}
}status is one of:
ready: checkviewbefore readingsignals. Whenviewisintents,signalsis present. Whenviewisprofile,signalsisnull. Use thetopicscall instead.preparing: signals are not computed yet. While the audience is being built or indexed, ask again after the next indexing run (hourly, except 03:00-09:00 UTC). Once it is indexed, it waits for the daily signals run after 13:40 UTC.next_run_atsays when that run starts. Asking again before then usually gets the same answer (a run already under way can still publish sooner).unavailable: the audience cannot have signals right now: a company audience, a paused or failed intents audience, or signals not enabled in this environment.reasonsays which and what to do (for example, resume or refresh the audience).
Trend, not just a snapshot
GET /api/v1/signals/audiences/{id}/history?project_id=YOUR_PROJECT_ID&range=90d
Returns the same daily counts across the requested window, ending on the audience's latest signals day. range accepts 30d, 90d (default), 180d, or 365d. Anything else is a 400.
Unlike the overview, this call never starts preparing the audience: an audience with no history yet answers 200 with days: []. To start preparation, call the overview endpoint above.
Download the people behind the counts
The overview gives counts. To get the people, download one state as a CSV file. Only intents and persona audiences have member lists. Any other audience returns 400.
state is one of in_market, new, rising, steady, cooling, entered_market, or almost_in_market. day is optional and defaults to the latest signals day.
First, quote the download. A dry_run bills nothing and returns the row count and the day it used:
curl "https://api.delivr.ai/api/v1/signals/audiences/10482/members/download?project_id=YOUR_PROJECT_ID&state=in_market&dry_run=true" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Api-Secret: YOUR_API_SECRET"{
"dry_run": true,
"meter": "predictive_signal",
"records_to_charge": 2211,
"records_fidelity": "exact",
"audience_id": "10482",
"state": "in_market",
"day": "20260921"
}Then run the real download with the same day:
curl "https://api.delivr.ai/api/v1/signals/audiences/10482/members/download?project_id=YOUR_PROJECT_ID&state=in_market&day=20260921" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Api-Secret: YOUR_API_SECRET" \
-o in-market.csvThe file has these columns: hem, intent_trend, active_days_14d, topic_ids (separated by ;), and company_domain. CCPA opt-outs are removed. The response header X-Record-Count holds the number of rows billed. If the file has fewer rows, the stream ended early. Download again. The repeat is free.
The route accepts only project_id, state, day, and dry_run. Any other query parameter returns 400.
Trends for one person
The audience calls above answer questions about a group. To ask about a single person, look them up by hem or email. No audience is needed.
POST /api/v1/signals/people/lookup?project_id=YOUR_PROJECT_ID
{ "id": "lead-1042", "email": "[email protected]", "min_score": "medium" }{
"response": {
"id": "lead-1042",
"matched": true,
"matched_on": "email",
"topics": [
{
"topic_id": "crm_software",
"topic_name": "CRM Software",
"score": "high",
"perc_score": 91,
"intent_trend": "rising",
"active_days_14d": 6,
"first_seen": "2026-09-23",
"last_seen": "2026-10-05"
}
]
},
"as_of": "2026-10-05"
}- Fields.
hem(lowercase SHA-256 of the email) oremail. A validhemwins if both are sent. Optional:id(echoed back),topic_ids(keep only these topics),min_score(highormedium, defaultmedium),dry_run. - Topics. Only high and medium topics that carry a trend are returned.
intent_trendisnew,rising,steady, orcooling, as for momentum above, but per person and per topic. matched. True when at least one trend topic came back after filtering. A person who has opted out looks exactly like a person we do not hold:matched: false,topics: [].- Batch.
POST /api/v1/signals/people/batchtakesitems(1 to 1,000, each withid,hem, oremail) plus the sametopic_ids,min_score, anddry_run. It returns{"response": {"results": [...], "matched_count": N}, "as_of": "..."}with results in request order. - Errors.
400formin_score: low(low topics carry no trend),linkedin_url,resolve_person, an item with nohemoremail, or a batch outside 1 to 1,000.402when the spend gate refuses the call.403for anything but an API key.429when the Platform Cap would be exceeded.503when the lookups are not enabled or the data is unavailable. That response is retryable, and nothing is billed. - Test keys. A test API key returns a fixed sample person with the header
X-Delivr-Mode: testand is never billed. Ahemof 64 zeros returnsmatched: false.
These two calls are for API keys only, and the project comes from X-Project-Id or ?project_id=.
Billing
Calls from the dashboard are never metered. An API-key caller is metered as Predictive Signals:
- One unit per company row returned in the overview's
top_companies. - One unit per result row returned by
topics. - The overview and
topicsbill the same answer only once per audience per day, no matter how many times it is fetched. - One unit per
historycall that returns at least one day. Repeating the call bills again, and a call withdays: []is free. - One unit per member returned by the paged
memberscall for an API key. The dashboard view is free. - One unit per member in a members download, for every caller. A state and day bills once per audience, so a repeat download is free.
- One unit per distinct person with at least one trend topic returned by
people/lookuporpeople/batch, counted aftertopic_idsandmin_scoreare applied. A person with no trend topic, or one filtered out, costs nothing, and a hem repeated in a batch bills once.
Add "dry_run": true to a people call to get records_to_charge back with no topics and no charge.
Updated about 24 hours ago
