# Company Dossier API: SEC, Companies House, State Registries (`lmhsolutions/company-dossier`) Actor

Cited company dossier from a name or domain: SEC EDGAR filings and financials, UK Companies House, NY/CO/OR/CT registries, website contacts. Every field has source URL, fetch time and SHA-256; signed. $0.03 basic, $0.15 full; no match free.

- **URL**: https://apify.com/lmhsolutions/company-dossier.md
- **Developed by:** [LMH Solutions](https://apify.com/lmhsolutions) (community)
- **Categories:** Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $150.00 / 1,000 full company dossiers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Company Dossier API for AI Agents: SEC EDGAR, UK Companies House, US State Registries, Website Contacts, Every Field Cited

Give it a **company name and/or domain**. Get back **one cited company dossier**: SEC EDGAR profile, filings and financials, UK Companies House registration, US state business-registry records (New York, Colorado, Oregon, Connecticut), and the company website's emails, phones and social links. **Every single field carries the source URL it came from, the time it was fetched and a SHA-256 hash of the exact bytes received.** Full dossiers are **Ed25519-signed** so an agent, auditor or downstream system can prove the record was not altered.

Built for **AI agents (MCP), KYC / KYB and due-diligence checks, vendor onboarding, B2B lead generation and CRM enrichment.**

### Why this Actor

- **Five official sources in one call**: SEC EDGAR (US public companies), UK Companies House, four US state registries, plus the company's own website and contact pages.
- **Cited at field level, not just "sources: \[...]"**: each value is `{value, sourceUrl, fetchedAt, contentSha256}`. Your agent can quote it, your compliance team can re-check it.
- **Signed**: full dossiers include an Ed25519 signature over the canonical JSON. Public key below; verify offline in a few lines.
- **No match, no charge**: if no registry matches (full) or nothing at all is found (basic), you pay nothing.
- **Official, free public data only**: SEC's JSON APIs (with a declared contact User-Agent and polite retry), Companies House, state open-data portals. No scraping of paywalled databases, no logins.
- **Fast, no browser**: plain HTTP. A full dossier usually takes 2 to 10 seconds.

### Pricing (pay per event)

| Event | Price | When it is charged |
|---|---|---|
| `full-dossier` | **$0.15** per company | Full mode, at least one registry (SEC, Companies House or a state) matched. All sources, financials, filings, signature. |
| `basic-profile` | **$0.03** per company | Basic mode, website and/or one registry match found. |
| No match / failed lookup | **free** | Nothing charged. |

Apify adds its tiny standard start event. Set a max charge per run and the Actor stops cleanly when it is reached.

### Coverage compared

| | **Company Dossier (this Actor)** | Typical SEC + Companies House MCP tools |
|---|---|---|
| SEC EDGAR profile, filings | Yes | Yes |
| SEC XBRL financials (revenue, net income, assets, cash, shares, float) | Yes, latest annual 10-K values with concept, period and filing date | Varies |
| UK Companies House | Yes (official API when a key is configured, public register pages otherwise) | Yes |
| US state registries | **NY, CO, OR, CT** | No |
| Company website: emails, phones, socials, address | **Yes, with the page each item came from** | No |
| Per-field source URL + fetch time + SHA-256 | **Yes** | No |
| Cryptographic signature | **Ed25519** | No |
| One-shot "dossier" across sources | **Yes** | Usually one tool call per source |
| Price | $0.03 basic / $0.15 full, no match free | per call |

### Input

```json
{
  "companies": [
    { "name": "Apple Inc.", "domain": "apple.com" },
    { "name": "Tesco PLC", "country": "GB" },
    { "name": "Nike, Inc.", "state": "OR" },
    "stripe.com"
  ],
  "mode": "full"
}
```

- `companies`: strings (name or domain) or objects `{name, domain, ticker, country, state}`.
- Or single-company shortcuts: `name`, `domain`, `country` (`US`/`GB`), `state` (two letters).
- `mode`: `full` (default) or `basic`.

### Output (one item per company, trimmed)

```json
{
  "query": { "name": "Apple Inc.", "domain": "apple.com" },
  "mode": "full", "status": "ok", "chargedEvent": "full-dossier",
  "summary": { "secName": "Apple Inc.", "cik": "0000320193", "tickers": ["AAPL"], "domain": "apple.com", "socials": ["linkedin", "youtube"] },
  "coverage": { "website": "fetched", "sec": "matched", "companiesHouse": "no_match", "stateRegistries": "NY:no_match CO:no_match OR:no_match CT:no_match" },
  "sec": {
    "name": { "value": "Apple Inc.", "sourceUrl": "https://data.sec.gov/submissions/CIK0000320193.json", "fetchedAt": "2026-11-02T13:10:00.000Z", "contentSha256": "9f2c..." },
    "stateOfIncorporation": { "value": "CA", "sourceUrl": "...", "fetchedAt": "...", "contentSha256": "..." },
    "financials": { "revenue": { "value": { "value": 416161000000, "unit": "USD", "fiscalYear": 2025, "periodEnd": "2025-09-27", "form": "10-K", "concept": "us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax" }, "sourceUrl": "https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json", "fetchedAt": "...", "contentSha256": "..." } },
    "recentFilings": { "value": [{ "form": "10-K", "filingDate": "2025-10-31", "url": "https://www.sec.gov/Archives/edgar/data/320193/..." }], "sourceUrl": "...", "fetchedAt": "...", "contentSha256": "..." }
  },
  "companiesHouse": null,
  "stateRegistries": [{ "state": "NY", "status": "no_match" }],
  "website": { "domain": "apple.com", "phones": [{ "value": "...", "sourceUrl": "https://www.apple.com/contact/", "fetchedAt": "...", "contentSha256": "..." }], "socials": { "linkedin": { "value": "https://www.linkedin.com/company/apple", "sourceUrl": "https://www.apple.com/" } } },
  "sources": [{ "url": "https://data.sec.gov/submissions/CIK0000320193.json", "fetchedAt": "...", "contentSha256": "...", "httpStatus": 200, "source": "sec-edgar" }],
  "signature": { "alg": "Ed25519", "keyId": "p2j-JX8i4uxGCZqSSDrd", "domain": "company-dossier-v1", "payloadSha256": "...", "signature": "base64url..." }
}
```

Fields: SEC (CIK, name, tickers, exchanges, EIN, LEI, SIC and description, state of incorporation, fiscal year end, business and mailing address, phone, former names, last 8 filings with links, XBRL financials); Companies House (company number, name, status, type, incorporation and dissolution date, registered office, SIC codes, other close matches); state registries (entity ID, name, entity type, jurisdiction, formation date, status, registered agent / process address); website (name, description, address, emails, phones, socials, pages scanned).

**Matching note:** registries are matched by company name (score 1 = identical after removing suffixes like Inc or Ltd; 0.85 = name plus extra trailing words). Different companies can share a name, so confirm the registry number before relying on a match for KYC. Adding `domain`, `country` and `state` gives better results.

### Verify the signature

Signed bytes = `"company-dossier-v1\n" + canonicalJson(dossier without "signature")` (keys sorted, no whitespace, undefined dropped). Public key (JWK): `{"kty":"OKP","crv":"Ed25519","x":"W7fo3MOr-WnJe__hpWGTHlhucxLhhp_LCKGvTLBlAMc"}`, key ID `p2j-JX8i4uxGCZqSSDrd`.

```js
const canon = (v) => v === null || typeof v !== "object" ? JSON.stringify(v) : Array.isArray(v) ? `[${v.map(canon).join(",")}]`
  : `{${Object.keys(v).filter((k) => v[k] !== undefined).sort().map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",")}}`;
const { signature, ...rest } = dossier;
const key = await crypto.subtle.importKey("jwk", { kty: "OKP", crv: "Ed25519", x: "W7fo3MOr-WnJe__hpWGTHlhucxLhhp_LCKGvTLBlAMc" }, { name: "Ed25519" }, false, ["verify"]);
const ok = await crypto.subtle.verify({ name: "Ed25519" }, key, Buffer.from(signature.signature, "base64url"), new TextEncoder().encode("company-dossier-v1\n" + canon(rest)));
```

### Use it from an AI agent (MCP)

Add the Actor as a tool on Apify's hosted MCP server:

```
https://mcp.apify.com/?tools=lmhsolutions/company-dossier
```

Claude, Cursor, ChatGPT connectors, LangChain, n8n and other MCP clients can then call it with `{ "name": "...", "domain": "..." }` and get the cited dossier back. Tool description for your agent: *"Look up a company in SEC EDGAR, UK Companies House, US state registries and its website; returns a cited, signed dossier."*

### Synchronous HTTP API (Standby)

```bash
curl -H "Authorization: Bearer $APIFY_TOKEN" "https://lmhsolutions--company-dossier.apify.actor/?name=Apple%20Inc.&domain=apple.com&mode=full"
curl -X POST -H "Authorization: Bearer $APIFY_TOKEN" -H "content-type: application/json" \
  -d '{"name":"Tesco PLC","country":"GB","mode":"basic"}' https://lmhsolutions--company-dossier.apify.actor/
```

Same events and prices per request; no-match responses are free. `GET /keys` returns the public signing key. Standby runs also use some platform compute per Apify's Standby billing rules.

### Run from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/lmhsolutions~company-dossier/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "content-type: application/json" -d '{"companies":[{"name":"Apple Inc.","domain":"apple.com"}],"mode":"full"}'
```

### FAQ

**Which US states are covered?** New York, Colorado, Oregon and Connecticut, via their official open-data registries. More states will follow where free official data exists.
**Does it cover private US companies?** Yes where they are registered in a covered state; SEC only lists companies that file with the SEC.
**Is the data current?** Everything is fetched live at request time; `fetchedAt` shows exactly when.
**Is this legal advice or a KYC decision?** No. It gathers public registry data with citations so your own process can decide.
**Data sources and terms:** SEC EDGAR (sec.gov fair-access policy, declared User-Agent), Companies House (Crown copyright, Open Government Licence), state open-data portals (their own open licences), and the company's public website.

Questions or a state you need? Open an issue on the Actor page.

# Actor input Schema

## `companies` (type: `array`):

One entry per company. Either a string (a company name like "Tesco PLC" or a domain like "stripe.com") or an object {"name", "domain", "ticker", "country" (US or GB), "state" (two-letter US state)}. Name plus domain gives the best match.

## `name` (type: `string`):

Shortcut for one company, e.g. "Apple Inc.". Combined with the fields below and added to 'companies'.

## `domain` (type: `string`):

Company website or bare domain, e.g. apple.com. Enables the website + contacts section.

## `country` (type: `string`):

Optional. In basic mode, US skips Companies House and GB skips SEC. Full mode always checks every source.

## `state` (type: `string`):

Optional two-letter US state for the state-registry lookup. Covered: NY, CO, OR, CT. Full mode without a state checks all four.

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

full = every source, SEC financials and filings, all covered state registries, Ed25519 signature ($0.15 per company with a registry match). basic = website + contacts + the first registry match ($0.03 per company with any result). Companies with no match are free.

## `maxConcurrency` (type: `integer`):

Companies processed in parallel. Registries are rate-limited politely regardless.

## Actor input object example

```json
{
  "companies": [
    {
      "name": "Apple Inc.",
      "domain": "apple.com"
    },
    {
      "name": "Tesco PLC",
      "country": "GB"
    }
  ],
  "country": "",
  "mode": "full",
  "maxConcurrency": 3
}
```

# Actor output Schema

## `dossiers` (type: `string`):

No description

## `full` (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 = {
    "companies": [
        {
            "name": "Apple Inc.",
            "domain": "apple.com"
        },
        {
            "name": "Tesco PLC",
            "country": "GB"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lmhsolutions/company-dossier").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 = { "companies": [
        {
            "name": "Apple Inc.",
            "domain": "apple.com",
        },
        {
            "name": "Tesco PLC",
            "country": "GB",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lmhsolutions/company-dossier").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "companies": [
    {
      "name": "Apple Inc.",
      "domain": "apple.com"
    },
    {
      "name": "Tesco PLC",
      "country": "GB"
    }
  ]
}' |
apify call lmhsolutions/company-dossier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lmhsolutions/company-dossier"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DO7m5FP5Eh8EfzjdK/builds/EgiX7AdllcyW1MjMq/openapi.json
