# PCAOB Form AP Auditor Engagement Scraper (`jungle_synthesizer/pcaob-form-ap-auditor-engagement-scraper`) Actor

Every Form AP filing PCAOB has published since 2017: which audit firm and named engagement partner signed each U.S. issuer's audit report, participating firms and their share, fiscal period and report dates, plus computed partner-tenure and auditor-change signals per issuer.

- **URL**: https://apify.com/jungle\_synthesizer/pcaob-form-ap-auditor-engagement-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 record scrapeds

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/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

## PCAOB Form AP Auditor Engagement Scraper

Extracts the complete PCAOB AuditorSearch / Form AP engagement register: for every issuer audit
report filed since 2017, which registered audit firm signed it, which individual engagement
partner signed it (by name and PCAOB Partner ID), which other accounting firms participated and
at what percentage, and the audit and fiscal-period dates. This is the authoritative issuer-to
-auditor-to-partner mapping for every US-listed issuer.

### What data does this actor extract?

Each record is one Form AP filing — one issuer audit report. Beyond the raw filing fields, the
actor computes two signals that require the full register in memory at once and are not present
in the raw PCAOB data:

- **`partner_tenure_years`** — consecutive fiscal years the same engagement partner has signed
  for the same issuer, the clock SOX caps at five years before a mandatory partner rotation
- **`auditor_change_flag`** — the issuer's audit firm differs from its prior fiscal period's
  filing, an auditor-change event
- **`other_participating_firms`** — other accounting firms disclosed as auditing more than 5% of
  the issuer, exploded into a clean array of `{ firm_name, country, percentage_or_range }`
  instead of the raw nested JSON PCAOB publishes

Both derived clocks are computed from `is_latest_form_ap_filing` rows — the PCAOB-resolved
current state of each engagement — so a superseded or amended-away filing never manufactures a
phantom partner-year or firm switch. A superseded row is then backfilled with its canonical
twin's clock when the two describe the same issuer, fiscal period, firm and partner; otherwise
those three fields are `null`.

**Sample output record:**

```json
{
  "form_filing_id": "5",
  "is_latest_form_ap_filing": true,
  "firm_id": "248",
  "firm_name": "Grant Thornton LLP",
  "firm_other_name": null,
  "firm_country": "United States",
  "firm_issuing_country": "United States",
  "firm_issuing_city": "Chicago",
  "firm_issuing_state": "Illinois",
  "audit_report_type": "Investment Company",
  "issuer_id": "581613",
  "issuer_name": "Advisors Disciplined Trust 1243",
  "issuer_cik": "0001600931",
  "audit_fund_series": null,
  "audit_report_date": "2017-01-31",
  "fiscal_period_end_date": "2016-09-30",
  "engagement_partner_last_name": "Mleko",
  "engagement_partner_first_name": "Frank",
  "engagement_partner_middle_name": "Michael",
  "engagement_partner_suffix": null,
  "engagement_partner_id": "0024800138",
  "engagement_partner_other_ids": null,
  "secondary_engagement_partner_last_name": null,
  "secondary_engagement_partner_first_name": null,
  "secondary_engagement_partner_id": null,
  "is_multiple_audit_period": false,
  "audit_period_information": null,
  "dual_dated": false,
  "audit_dual_date": null,
  "is_audit_divided": false,
  "is_audit_not_divided": false,
  "audit_not_divided_percent_information": null,
  "number_of_participants": null,
  "participant_percentage": null,
  "participant_range": null,
  "other_participating_firms": [],
  "is_amendment": false,
  "amendment_scope": [],
  "partner_tenure_years": 1,
  "auditor_change_flag": false,
  "partner_rotation_due": false
}
```

### Use cases

- **Audit firm business development** — identify issuers whose engagement partner is approaching
  the five-year SOX rotation ceiling, before a competitor's audit team does
- **Short sellers and forensic-accounting research** — screen the `auditor_change_flag` event feed
  for issuers that recently switched audit firms
- **Academic accounting research** — Form AP is a standard dataset in the audit-quality
  literature, and `partner_tenure_years` is the field most of that literature computes by hand
- **Issuer-side audit committees** — benchmark their own engagement partner's tenure and
  participating-firm disclosures against the full market

### How it works

The actor downloads PCAOB's own daily-refreshed bulk export directly — no browser automation, no
per-issuer lookups. PCAOB republishes the entire Form AP register as a single ZIP archive every
day; the actor extracts, parses and joins it in one pass, then computes the two derived clocks
described above across the full corpus before saving records.

**Data source:** `https://assets.pcaobus.org/firm-filings/FirmFilings.zip`

### Input

| Field      | Type    | Description                         | Default |
|------------|---------|-------------------------------------|---------|
| `maxItems` | Integer | Maximum number of records to return | 10      |

### Output

One record per Form AP filing. The current register holds roughly **156,000 filings** covering
every issuer audit report filed since the 2017 requirement took effect, growing by about 20,000
filings a year.

| Field                                     | Type    | Description |
|-------------------------------------------|---------|-------------|
| `form_filing_id`                          | String  | PCAOB's unique identifier for this Form AP filing |
| `is_latest_form_ap_filing`                | Boolean | True if this is the current, non-superseded version of the filing (false on an original filing that was later amended) |
| `firm_id`                                 | String  | PCAOB-registered identifier of the audit firm that signed the report |
| `firm_name`                               | String  | Audit firm name |
| `firm_other_name`                         | String  | Alternate/trade name for the firm, when disclosed |
| `firm_country`                            | String  | Audit firm's country of registration |
| `firm_issuing_country`                    | String  | Country of the office that issued the report |
| `firm_issuing_city`                       | String  | City of the office that issued the report |
| `firm_issuing_state`                      | String  | US state of the office that issued the report, when applicable |
| `audit_report_type`                       | String  | Filing category (e.g. "Investment Company", "Issuer, other than Employee Benefit Plan or Investment Company") |
| `issuer_id`                               | String  | PCAOB identifier for the issuer whose audit report this is |
| `issuer_name`                             | String  | Issuer name |
| `issuer_cik`                              | String  | SEC Central Index Key (CIK) for the issuer |
| `audit_fund_series`                       | String  | Fund series name, for investment-company filings that cover one |
| `audit_report_date`                       | String  | Date the audit report was issued (YYYY-MM-DD) |
| `fiscal_period_end_date`                  | String  | End date of the fiscal period covered by the audit report (YYYY-MM-DD) |
| `engagement_partner_last_name`            | String  | Engagement partner's last name |
| `engagement_partner_first_name`           | String  | Engagement partner's first name |
| `engagement_partner_middle_name`          | String  | Engagement partner's middle name |
| `engagement_partner_suffix`               | String  | Engagement partner's name suffix (Jr., III, etc.) |
| `engagement_partner_id`                   | String  | PCAOB Partner ID of the signing engagement partner — the join key for partner-tenure analysis |
| `engagement_partner_other_ids`            | String  | Other PCAOB IDs disclosed for the same partner, when present |
| `secondary_engagement_partner_last_name`  | String  | Second signing partner's last name, for dual-signed reports |
| `secondary_engagement_partner_first_name` | String  | Second signing partner's first name |
| `secondary_engagement_partner_id`         | String  | Second signing partner's PCAOB Partner ID |
| `is_multiple_audit_period`                | Boolean | True when the report covers more than one fiscal period |
| `audit_period_information`                | String  | Free-text description of the covered period(s), when disclosed |
| `dual_dated`                              | Boolean | True when the report carries two report dates |
| `audit_dual_date`                         | String  | The second report date, when dual-dated (YYYY-MM-DD) |
| `is_audit_divided`                        | Boolean | True when audit responsibility was divided among firms by a criterion (assets, revenue, etc.) |
| `is_audit_not_divided`                    | Boolean | True when other firms participated without a formal division of responsibility |
| `audit_not_divided_percent_information`   | String  | Raw PCAOB participant-disclosure JSON backing `other_participating_firms` for a not-divided filing |
| `number_of_participants`                  | Number  | Count of other firms that participated in the audit |
| `participant_percentage`                  | Number  | Disclosed participation percentage, when PCAOB reports an exact figure |
| `participant_range`                       | String  | Disclosed participation percentage range, when PCAOB reports a band instead of an exact figure |
| `other_participating_firms`               | Array   | Other firms disclosed as auditing >5% of the issuer, exploded from the raw participant JSON: firm name, country, and disclosed percentage or range |
| `is_amendment`                            | Boolean | True when this filing amends an earlier one |
| `amendment_scope`                         | Array   | Which Form AP sections this filing amended (previous filing, firm identification, audit report, other firms, divided responsibility, participants >5%, participants <5%, audit divided). Empty on an original filing |
| `partner_tenure_years`                    | Number  | Consecutive fiscal years (ending at this filing's year) the same partner has signed for this issuer, computed from current filings only. Null on a superseded filing with no matching current filing |
| `auditor_change_flag`                     | Boolean | True when this issuer's audit firm differs from its prior fiscal period's current filing. False on the issuer's earliest observed filing. Null on a superseded filing with no matching current filing |
| `partner_rotation_due`                    | Boolean | True when `partner_tenure_years` >= 5, the SOX engagement-partner rotation ceiling |

### Notes

- PCAOB republishes the full register daily — each run picks up that day's file, so a filing
  amended this morning is reflected the same day
- `partner_tenure_years`, `auditor_change_flag` and `partner_rotation_due` are computed from
  `is_latest_form_ap_filing` filings; a superseded/amended-away filing inherits its canonical
  replacement's values when one matches on issuer, fiscal period, firm and partner, and is
  otherwise `null` rather than a guess
- `other_participating_firms` is populated only for filings that disclosed participating firms —
  most filings involve a single audit firm and this array is empty

# Actor input Schema

## `sp_intended_usage` (type: `string`):

What will this data feed? E.g. lead lists, KYB checks, price tracking.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

We'll personally help with your use case. No spam.

## `maxItems` (type: `integer`):

Maximum number of records to scrape

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 10
}
```

# 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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/pcaob-form-ap-auditor-engagement-scraper").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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/pcaob-form-ap-auditor-engagement-scraper").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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "maxItems": 10
}' |
apify call jungle_synthesizer/pcaob-form-ap-auditor-engagement-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jungle_synthesizer/pcaob-form-ap-auditor-engagement-scraper"
        }
    }
}
```

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/sNHjZWGJD8sX1DfCx/builds/PPNOGBO1R2drfooTU/openapi.json
