# Aleph FollowTheMoney Extractor — investigative entity graphs (`datamule/aleph-followthemoney-extractor`) Actor

Point at an Aleph (OCCRP FollowTheMoney) instance and extract investigative-graph data via its /api/2 API — collections, entities (people, companies, sanctions), and schema metadata. For AML, due-diligence, and OSINT research.

- **URL**: https://apify.com/datamule/aleph-followthemoney-extractor.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 entity records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Aleph FollowTheMoney Extractor

Point at **an Aleph deployment you can access** and pull structured
**FollowTheMoney (FtM)** investigative-graph data from its `/api/2` API. Aleph is the entity-graph
platform that [OCCRP](https://occrp.org) and the investigative-journalism network
run on top of the [FollowTheMoney](https://followthemoney.tech) data standard —
this actor turns a reachable Aleph base into clean, structured rows for **AML,
due-diligence, and OSINT** research.

> Buyer-first anonymous source: `https://source.bird.tools` exposes a verified
> public collections catalogue. API keys are optional only for deployments or
> public subsets proven anonymous. Access varies by deployment and endpoint;
> current OCCRP collections/entities are auth-gated and require an API key.

### Three modes

| Mode | Endpoint | One row = |
| --- | --- | --- |
| `collections` | `/api/2/collections` | one dataset/collection in the instance (label, category, count, `restricted`/`secret` flags, frequency, dates) |
| `entities` | `/api/2/entities` | one FtM entity — Person, Company, Sanction, Address … (id, schema, extracted name/countries/dates + the full multi-valued `properties` blob, its collection) |
| `metadata` | `/api/2/metadata` | one FtM **schema** the instance self-describes (Person, Company, …) with its label, plural, description, and property count — the discovery map of what an instance can serve |

### Input

| Field | Type | Notes |
| --- | --- | --- |
| `alephUrl` | string (required) | An Aleph base, e.g. `https://source.bird.tools`. Bare host or a `/api/2` URL both work. |
| `mode` | enum | `collections` | `entities` | `metadata` (default `collections`). |
| `query` | string | Entities: `q=` full-text (e.g. a name). See the note below. |
| `schema` | string | Entities: restrict to one FtM schema (`Person`, `Company`, `Sanction`, …). The reliable structured query path. |
| `collectionId` | string | Entities: scope to one collection by its numeric `collection_id`. |
| `maxRecords` | integer | Cap on emitted rows (default 5). One row = one billable record. |
| `apiKey` | string (secret) | Optional only for deployments/public subsets proven anonymous; required for restricted content or auth-gated deployments, including current OCCRP collections/entities. |
| `extraHeaders` | object | Optional extra request headers. |

#### Example inputs

```json
{"alephUrl":"https://source.bird.tools","maxRecords":5,"mode":"collections"}
```

This bounded BIRN collections input is the proven anonymous buyer default. It
returns at most five genuine catalogue rows, keeping the first run cheap and
predictable.

**Entity mode is not proven as an anonymous buyer default** on BIRN or the
independent DDoSecrets corroboration deployment. Use `entities` only against a
deployment and filter you have verified, and provide `apiKey` when required.

```json
{"alephUrl":"https://source.bird.tools","maxRecords":5,"mode":"metadata"}
```

### Notes on reliability

- **Pagination** is standard offset paging (`page`/`limit`/`total`/`pages` with an
  absolute `next` link) — the actor follows it to `maxRecords`.
- **Full-text search can 500 transiently.** Aleph's `q=` backend can return a
  transient `HTTP 500` under load while structured `filter:schema=` queries stay
  healthy. The actor retries 5xx/429 with backoff and treats a 500 as a
  server-side condition, **not** an empty result — so it never fabricates or
  silently reports empty. If a `query` run struggles, prefer a `schema` filter.
- **Restricted / secret collections** are surfaced with their flags so a private
  collection is never mistaken for empty. Provide `apiKey` whenever the
  deployment requires authorization; current OCCRP collections/entities do.
- **No fabricated output.** An unreachable base, a non-Aleph host, or a genuinely
  empty result fails fast rather than emitting invented rows.

### Output

One flat, fully-nullable JSON row per record. Only `_mode` and `_alephUrl` are
always set; every domain field is nullable because the three modes and the wildly
varying FtM schemas populate different columns. The multi-valued FtM `properties`
are preserved as a JSON string in `properties`, with common values also extracted
to `name` / `countries` / `dates`.

### Pricing

**Pay-per-event** — one `record` charge per emitted entity / collection / schema.

# Actor input Schema

## `alephUrl` (type: `string`):

Base URL of an Aleph (FollowTheMoney) deployment, e.g. https://source.bird.tools. The actor calls /api/2/{collections,entities,metadata}. Anonymous access varies by deployment and endpoint; use credentials when the requested data is restricted or auth-gated. You can pass a bare host or a URL already containing /api/2.

## `mode` (type: `string`):

What to extract. 'collections' = the instance's dataset catalogue (one row per collection). 'entities' = FollowTheMoney entities (people, companies, sanctions, addresses …) filtered by query/schema/collection; anonymous entity rows are not proven as a buyer default, so verify source access first. 'metadata' = the instance's self-describing FtM schema catalogue (one row per entity type).

## `query` (type: `string`):

Entities mode only — a q= full-text search across entities (e.g. a person or company name). Note: Aleph's full-text backend can 500 transiently under load; a schema filter is a more reliable structured alternative. Ignored for collections/metadata.

## `schema` (type: `string`):

Entities mode only — restrict to one FollowTheMoney schema: Person, Company, Sanction, Address, Organization, LegalEntity, … (see 'metadata' mode for the full list an instance supports). This is the reliable structured query path. Ignored for collections/metadata.

## `collectionId` (type: `string`):

Entities mode only — scope entities to a single collection/dataset by its numeric collection\_id (from 'collections' mode). Ignored for collections/metadata.

## `maxRecords` (type: `integer`):

Stop after emitting this many rows. The bounded first run emits at most 5 rows. Each emitted entity / collection / schema is billed as one record.

## `apiKey` (type: `string`):

Optional only for deployments or public subsets proven anonymous. Required for restricted content or auth-gated deployments, including current OCCRP collections/entities. Sent as Authorization: ApiKey \*\*\* and never logged.

## `extraHeaders` (type: `object`):

Optional extra HTTP headers sent with every request, for example a proxy header or deployment-specific authentication. Public access varies by deployment and endpoint.

## `userAgent` (type: `string`):

Override the default descriptive User-Agent. Please keep a descriptive agent when hitting public investigative-journalism infrastructure.

## Actor input object example

```json
{
  "alephUrl": "https://source.bird.tools",
  "mode": "collections",
  "schema": "Person",
  "maxRecords": 5
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "alephUrl": "https://source.bird.tools",
    "mode": "collections",
    "maxRecords": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/aleph-followthemoney-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "alephUrl": "https://source.bird.tools",
    "mode": "collections",
    "maxRecords": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("datamule/aleph-followthemoney-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "alephUrl": "https://source.bird.tools",
  "mode": "collections",
  "maxRecords": 5
}' |
apify call datamule/aleph-followthemoney-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=datamule/aleph-followthemoney-extractor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/gu4IDK8Ivmx2CTUlE/builds/hTYifP4ck03CCkVcF/openapi.json
