Pythia Search Bundle — Multi-Source OSINT Fan-Out
Pricing
Pay per usage
Pythia Search Bundle — Multi-Source OSINT Fan-Out
One subject in, structured intelligence from many public sources out. Tick the sources you want — jobs boards, SEC filings, news, code repos — and pay only per result returned.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Creator Fusion
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 hours ago
Last modified
Categories
Share
Pythia Search Bundle — 14-Source OSINT Fan-Out API for AI Agents
One subject in — a company name, domain, GitHub org, or package name — structured intelligence from 14 public sources out, in a single Apify call. This is the account's flagship consolidated intelligence Actor: it replaces 19 single-source Pythia Actors (now deprecated and redirected here) with one typed, agent-friendly fan-out endpoint. Every run returns typed JSON rows — one per source, each holding a list of individually-dated signals — schema below.
Why agents use this actor
- One call, many sources. Instead of orchestrating 14 separate API integrations, an agent sends one
subjectand asourceslist and gets back a normalized row per source. - Deterministic typed output. Every row and every signal matches the published dataset schema, regardless of which source produced it.
evidencevaries by source but the envelope never does. - Per-source failure isolation. One source failing (rate limit, no data, transient error) never breaks the run — it comes back as
available: falsewith anerrorstring, and every other source still returns its data. - No auth, no cookies. All 14 sources are public APIs or public pages; this Actor holds any keys it needs internally.
- Cost-predictable.
max_results_per_sourcehard-caps signals per source, so the maximum possible bill for a run is known before you start it.
Sources
Built as a Rust Cargo workspace: search_bundle (this Actor) fans out via the Apify API to 14 private sibling Actors and aggregates their datasets into one response. subject is sent to each source using the wrapping its input_kind needs (a bare domain vs. a search query vs. a package name).
| Source key | Input kind | Signal it returns |
|---|---|---|
sec_edgar | query | sec_filing — SEC EDGAR full-text search hits |
statuspage | domain | incident / incident_summary — Atlassian Statuspage vendor incidents |
gdelt | query | news_mention — GDELT global news index |
google_news | query | news_mention — Google News RSS |
hackernews | query | story — HackerNews Algolia search |
github | domain | org_summary + repo — GitHub org repo list, languages, activity |
greenhouse | domain | job_posting — Greenhouse ATS open roles |
lever | domain | job_posting — Lever ATS open roles |
npm | package | package_meta — npm registry package metadata |
pypi | package | package_meta — PyPI package metadata |
reddit | query | post — Reddit search |
stackoverflow | query | question — Stack Exchange API |
federal_register | query | federal_register_doc — Federal Register full-text search |
wayback | url | snapshot_summary — Internet Archive Wayback Machine snapshot history |
subject is treated literally per source — for github it's matched as an exact org login, for domain-kind sources it's used as-is (no www-stripping). A near-miss (e.g. a decommissioned or unrelated org that happens to share a name) will still return real, live data for the wrong entity, so verify evidence.full_name / the source's own identity fields on the first row before trusting a run at scale.
Known gap — 4 sibling source Actors exist in the codebase but are not yet wired into this Actor's fan-out registry: opencorporates, opensanctions, producthunt, uspto_trademark. Requesting any of these in sources is accepted by the input schema but returns no row for that source — it is recorded as "unknown source: <name>" in the summary row's evidence.failed_sources and nothing is charged for it. Stick to the 14 keys in the table above until these are connected.
Input schema
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
subject | string | yes | — | Company slug, domain, GitHub org, package name, or search query. Used for every selected source. |
sources | string[] | yes | — | Which of the 14 source keys above to fan out to. Unrecognized keys are skipped, not charged. |
since_days | integer | no | 30 | Lookback window for sources that accept one (news, HackerNews, Reddit, SEC EDGAR, Federal Register, etc). Ignored by sources with no time dimension (npm, PyPI, GitHub org summary). |
concurrency | integer | no | 5 | How many child Actors to call at once. Higher is faster but heavier on account concurrency. |
max_results_per_source | integer | no | 25 | Hard cap on signals returned per source. Caps the maximum possible bill for the run: roughly actor-start + sources × this × per-signal price. |
Output schema
One row per requested-and-recognized source, plus one leading search_bundle summary row. All fields nullable.
| Field | Type | Description |
|---|---|---|
source | string | null | search_bundle for the summary row, otherwise the source key, e.g. hackernews, github. |
subject | string | null | Subject as sent to this source. |
signals | array | null | The signals this source returned. Empty when unavailable or nothing found. |
signals[].signal_id | string | null | Stable ID, typically {source}:{subject}:{event_type}:{id-or-date}. |
signals[].source | string | null | Source key for this individual signal. |
signals[].event_type | string | null | e.g. story, org_summary, repo, job_posting, sec_filing, news_mention, post, question, incident, package_meta, snapshot_summary, federal_register_doc, bundle_summary. |
signals[].subject | string | null | Subject this signal is about. |
signals[].summary | string | null | One-line, public-record-style description. No advice, no editorial framing. |
signals[].severity | string | null | critical, high, notable, or info. Every source Actor currently emits only notable/info; critical/high are reserved for a future synthesis layer. |
signals[].source_confidence | string | null | high, medium, or low. |
signals[].delta | string | null | new, changed, resolved, or info. Currently always info — no cross-run diffing yet. |
signals[].observed_at | string | null | ISO 8601 timestamp of the underlying event (not the run time). |
signals[].evidence | object | null | Free-form, source-specific structured data. Never contains raw PII or credentials — a redaction guard runs before every push and fails the run if it finds any. |
available | boolean | null | True if the source ran and returned data (even zero signals). False if it errored. |
error | string | null | Set when available is false, e.g. "reddit status 403 Forbidden". |
fetched_at | string | null | ISO 8601 timestamp this row was produced. |
actor_version | string | null | Semver of the Actor (bundle or child) that produced this row. |
Example — summary row (real output, subject: "Anthropic", sources: ["hackernews","github"])
{"source": "search_bundle","subject": "Anthropic","signals": [{"signal_id": "search_bundle:TQifrPdkrzhIbsxfq:summary","source": "search_bundle","event_type": "bundle_summary","subject": "Anthropic","summary": "2 sources requested, 2 succeeded, 0 failed; 20 signals total","severity": "info","source_confidence": "high","delta": "info","observed_at": "2026-08-15T11:41:51.049Z","evidence": {"bundle_run_id": "TQifrPdkrzhIbsxfq","requested_sources": ["hackernews", "github"],"successful_sources": ["hackernews", "github"],"failed_sources": [],"failures_detail": [],"total_signals": 20,"total_billable_results": 20,"estimated_gross_cost_usd": 0.7}}],"available": true,"error": null,"fetched_at": "2026-08-15T11:41:51.049Z","actor_version": "0.1.10"}
Example — hackernews source row (real output)
{"source": "hackernews","subject": "Anthropic","signals": [{"signal_id": "hackernews:Anthropic:story:49308395","source": "hackernews","event_type": "story","subject": "Anthropic","summary": "OpenAI and Anthropic in price war as Chinese AI rivals gain ground (↑3)","severity": "info","source_confidence": "high","delta": "info","observed_at": "2026-08-15T07:01:41Z","evidence": {"object_id": "49308395","title": "OpenAI and Anthropic in price war as Chinese AI rivals gain ground","url": "https://arstechnica.com/ai/2026/08/openai-and-anthropic-in-price-war-as-chinese-ai-rivals-gain-ground/","author": "joozio","points": 3,"num_comments": 1}}],"available": true,"error": null,"fetched_at": "2026-08-15T11:41:47.887Z","actor_version": "0.1.0"}
Example — github source row (real output; org_summary + one repo signal)
{"source": "github","subject": "anthropic","signals": [{"signal_id": "github:anthropic:summary","source": "github","event_type": "org_summary","subject": "anthropic","summary": "18 repos · 0 created in 30d · top lang: JavaScript","severity": "info","source_confidence": "high","delta": "info","observed_at": "2026-08-15T11:41:50.710Z","evidence": { "total_public_repos": 18, "new_repos_30d": 0, "top_language": "JavaScript", "language_counts": { "JavaScript": 9, "TypeScript": 2, "HTML": 3, "Makefile": 1, "Unknown": 3 } }},{"signal_id": "github:anthropic:repo:302289032","source": "github","event_type": "repo","subject": "anthropic","summary": "react (★1) — —","severity": "info","source_confidence": "high","delta": "info","observed_at": "2026-08-15T11:41:50.710Z","evidence": { "full_name": "Anthropic/react", "id": 302289032, "stargazers_count": 1, "forks_count": 1, "language": null, "fork": true, "archived": false, "created_at": "2020-10-08T09:18:29Z", "pushed_at": "2020-10-08T06:10:24Z", "description": "A declarative, efficient, and flexible JavaScript library for building user interfaces." }}],"available": true,"error": null,"fetched_at": "2026-08-15T11:41:50.710Z","actor_version": "0.1.0"}
Example — unavailable source row (real output; reddit on a 403)
{"source": "reddit","subject": "Anthropic","signals": [],"available": false,"error": "reddit status 403 Forbidden","fetched_at": "2026-08-15T11:42:43.031Z","actor_version": "0.1.0"}
Error semantics
- Empty
subjector emptysources— the run fails immediately (exit code 1) with a descriptive message. - A source fails at the HTTP/parse level (rate limit, timeout, upstream error) — its row is still pushed, with
available: falseanderrorset. The rest of the run continues. It is also listed in thesearch_bundlesummary row'sevidence.failed_sources/evidence.failures_detail. - An unrecognized source key (not one of the 14 wired sources) — no row is pushed for it at all. It is dropped silently from the dataset and recorded only in the summary row's
evidence.failed_sourcesas"unknown source: <name>". Nothing is charged for it. Checkevidence.successful_sourcesagainst your requestedsourcesif you need to detect this. estimated_gross_cost_usdin the summary row'sevidenceis the Actor's own internal per-signal cost model (used formax_results_per_sourcecapping), not necessarily the platform's live configured pricing — see Pricing below.- Rows are pushed as each source finishes, so a run that ends early for any reason still leaves every completed source's row in the dataset.
Use from AI agents (MCP)
{"mcpServers": {"apify": {"url": "https://mcp.apify.com/?tools=apricot_blackberry/pythia-search-bundle","headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }}}}
Works in Claude, Cursor, ChatGPT deep research connectors, and any MCP client; the input schema above is the tool's parameter schema.
Use from code
curl
curl -X POST "https://api.apify.com/v2/acts/apricot_blackberry~pythia-search-bundle/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"subject":"Anthropic","sources":["hackernews","github"],"since_days":14,"max_results_per_source":10}'
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('apricot_blackberry/pythia-search-bundle').call({subject: 'Anthropic',sources: ['hackernews', 'github', 'sec_edgar'],since_days: 30,max_results_per_source: 25,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.filter((row) => row.available === false));
Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("apricot_blackberry/pythia-search-bundle").call(run_input={"subject": "Anthropic","sources": ["hackernews", "github", "gdelt", "google_news"],"since_days": 30,"max_results_per_source": 25,})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["source"], row["available"], len(row.get("signals", [])))
Use from automation platforms
- n8n / Make / Zapier — use the native Apify integration, pick "Run Actor", and choose
pythia-search-bundleby name. - LangChain / LlamaIndex — wrap it with the Apify Actor tool wrappers (
apricot_blackberry/pythia-search-bundle); the input schema becomes the tool signature. - Webhooks — Apify webhooks can fire on run completion, so a downstream pipeline can pick up a finished intelligence sweep without polling.
Pricing
Not yet monetized on the Apify Console at time of writing — runs are free while this listing is finalized. The code itself carries an internal per-source cost model (used to cap max_results_per_source and reported as estimated_gross_cost_usd in every summary row) that reflects the intended pricing shape:
| Source | Internal price per signal |
|---|---|
sec_edgar, federal_register | $0.10 |
reddit, stackoverflow, github, statuspage, wayback | $0.05 |
greenhouse, lever, hackernews, gdelt, npm, pypi, google_news | $0.02 |
Check the Apify Console for this Actor's live configured pricing before relying on these figures for a production budget.
FAQ
What is this actor, really? One Apify call that fans out to 14 separate public-data source Actors for the same subject and returns their results as normalized rows. It replaces 19 single-source Pythia Actors that were deprecated and redirected here.
Does subject need to be a domain, a company name, or something else? It depends on the source — see the Sources table's "Input kind" column. The same literal subject string is sent to every selected source, wrapped appropriately (a bare login for github, a search query for hackernews/gdelt/google_news/reddit/stackoverflow, a package name for npm/pypi, a URL for wayback).
Why did I get a GitHub org I didn't expect? github matches subject as an exact org login. If the exact-name org isn't the company you meant (a decommissioned shell org, a name squat, etc.), you'll get real data for the wrong entity. Check evidence.full_name on the first repo signal to confirm identity before trusting results at scale.
Can I request opencorporates, opensanctions, producthunt, or uspto_trademark? The input schema accepts them, but they aren't wired into this Actor's fan-out registry yet. You'll get no row for that source and a "unknown source" entry in the summary — see Error semantics.
How do I keep a run's cost predictable? Set max_results_per_source — the summary row's evidence.estimated_gross_cost_usd shows what the run would cost against the internal per-signal price table, before you scale up.
Does this work for private companies or people who don't file with the SEC? Yes — hackernews, gdelt, google_news, reddit, stackoverflow, github, npm, pypi, greenhouse, lever, statuspage, and wayback all cover subjects with no SEC presence. Only sec_edgar and federal_register are limited to entities that file with US federal bodies.
Changelog
0.1 — Consolidated fan-out Actor covering 14 wired sources (SEC EDGAR, Statuspage, GDELT, Google News, HackerNews, GitHub, Greenhouse, Lever, npm, PyPI, Reddit, Stack Overflow, Federal Register, Wayback). Typed dataset schema, per-source failure isolation, redaction guard on every push, internal per-signal cost model for predictable-bill capping. Supersedes 19 deprecated single-source Pythia Actors.