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

CallAnswers
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}/topicsWhich 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:

  1. new: first seen active on a defining topic within the window.
  2. rising: this week's activity is at least 1.5x the prior week's.
  3. steady: roughly flat week over week.
  4. 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_makers counts people at C-level, VP or Director seniority. managers counts managers. other counts everyone else, including staff and people with no known seniority. The three sum to with_intent.
  • departments lists up to 3 departments as {department, people}, most people first. department_count counts every department among the people with intent, including those not listed. People with no known department are not counted.
  • buying_group is true when 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: check view before reading signals. When view is intents, signals is present. When view is profile, signals is null. Use the topics call 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_at says 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. reason says 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.csv

The 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) or email. A valid hem wins if both are sent. Optional: id (echoed back), topic_ids (keep only these topics), min_score (high or medium, default medium), dry_run.
  • Topics. Only high and medium topics that carry a trend are returned. intent_trend is new, rising, steady, or cooling, 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/batch takes items (1 to 1,000, each with id, hem, or email) plus the same topic_ids, min_score, and dry_run. It returns {"response": {"results": [...], "matched_count": N}, "as_of": "..."} with results in request order.
  • Errors. 400 for min_score: low (low topics carry no trend), linkedin_url, resolve_person, an item with no hem or email, or a batch outside 1 to 1,000. 402 when the spend gate refuses the call. 403 for anything but an API key. 429 when the Platform Cap would be exceeded. 503 when 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: test and is never billed. A hem of 64 zeros returns matched: 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 topics bill the same answer only once per audience per day, no matter how many times it is fetched.
  • One unit per history call that returns at least one day. Repeating the call bills again, and a call with days: [] is free.
  • One unit per member returned by the paged members call 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/lookup or people/batch, counted after topic_ids and min_score are 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.


Did this page help you?