# FEC Campaign-Finance Delta, Concentration & Donor Graph API (`malonestar/fec-campaign-finance-delta`) Actor

Track FEC filings & receipts: new-filing delta feed, donor/vendor concentration (HHI) analytics, and a contributor-committee graph. OpenFEC source.

- **URL**: https://apify.com/malonestar/fec-campaign-finance-delta.md
- **Developed by:** [Kyle Maloney](https://apify.com/malonestar) (community)
- **Categories:** Lead generation, Developer tools, Agents
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.40 / 1,000 results

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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## FEC Campaign-Finance Delta, Concentration & Donor Graph

Turn the FEC's raw itemized data into the three views political-intel teams
actually use: a **new-filing / new-receipt delta feed**, **donor & vendor
concentration analytics (Herfindahl / HHI)**, and a **contributor ↔ committee
graph**. Sourced live from the official **OpenFEC API**
(`api.open.fec.gov`).

> **Bring your own free api.data.gov key.** Register in seconds at
> https://api.open.fec.gov/developers and paste it into `apiKey`. `DEMO_KEY`
> works only for light testing (~30 requests/hour, shared IP).

### Who it's for
- **Political-intelligence & opposition research** — monitor a committee or
  candidate for new money as it's filed.
- **Journalists & watchdogs** — surface the biggest donors, employers, and
  vendors behind a committee, and how concentrated its funding is.
- **PAC / campaign compliance & finance teams** — track receipts and
  disbursements, reconcile filings, and watch counterparties.
- **Data & AI agents** — a clean, chainable tool over FEC data (see MCP note).

### What it does
- **search** — list matching receipts (schedule_a), disbursements
  (schedule_b), or filings (/filings).
- **delta** — only NEW rows since a date and/or not seen in a prior run
  (a rolling seen-set is kept for scheduled monitoring).
- **concentration** — top donors/vendors by summed amount plus a Herfindahl
  (HHI) score (0–10000) measuring how concentrated the funding is.
- **graph** — a contributor ↔ committee (or vendor ↔ committee) edge list.

### Example input
```json
{
  "apiKey": "YOUR_API_DATA_GOV_KEY",
  "mode": "concentration",
  "dataType": "receipts",
  "committeeId": "C00401224",
  "sinceDate": "2025-01-01",
  "concentrationBy": "employer",
  "topN": 50,
  "maxResults": 2000
}
````

New-filings monitor:

```json
{ "apiKey": "YOUR_KEY", "mode": "delta", "dataType": "filings", "committeeId": "C00401224", "sinceDate": "2025-09-01" }
```

### Output fields

Every row uses one stable, snake\_case schema (nulls where a field doesn't apply):

| field | meaning |
|-------|---------|
| `record_type` | receipt / disbursement / filing / concentration / concentration\_summary / edge |
| `committee_id`, `committee_name` | the FEC committee |
| `candidate_id`, `candidate_name` | linked candidate, if any |
| `contributor_name`, `contributor_employer`, `contributor_occupation` | donor details (receipts) |
| `amount` | transaction amount (USD) |
| `date` | transaction/filing date, `YYYY-MM-DD` |
| `recipient_or_payee` | receiving committee (receipts) or vendor/payee (disbursements) |
| `state` | contributor / recipient / committee state |
| `memo` | purpose / receipt type / document type |
| `source_url` | link to the FEC source image/PDF |
| `retrieved_at` | ISO fetch timestamp |
| `entity`, `counterparty` | concentration/graph rollup + its committee |
| `total_amount`, `txn_count` | summed amount + transaction count for the entity/edge |
| `concentration_score` | Herfindahl points — total HHI on a summary row; share%² on an entity/edge row |

### Use as an MCP tool

This actor is callable by AI agents (Claude, Cursor, etc.) via
[mcp.apify.com](https://mcp.apify.com). Field-level output descriptions make it
a clean, chainable tool: an agent can pull a committee's receipts, then feed the
donor/employer concentration or the contributor→committee edge list into the
next step.

### FAQ

**Do I need an API key?** Yes — a free api.data.gov key. Get one at
https://api.open.fec.gov/developers . DEMO\_KEY is rate-limited to ~30/hr.

**How do I find a committee or candidate ID?** Search on
[fec.gov](https://www.fec.gov/data/) — committee ids look like `C00401224`,
candidate ids like `P80001571`.

**How does the delta / new-filings feed work?** Pass `mode=delta` with a
`sinceDate` and/or the prior run's ids in `priorItems`; the actor also keeps a
rolling seen-set so scheduled runs emit only new activity.

**What is the concentration score?** A Herfindahl-Hirschman Index (HHI) over the
selected entities' shares of total dollars, on the standard 0–10000 scale — high
values mean a committee's money comes from a few donors/employers/vendors.

**Which data can I pull?** Itemized contributions (schedule\_a), disbursements
(schedule\_b), and report filings (/filings), scoped by committee, candidate,
name, state, date range, and minimum amount.

### Notes

- Data is sourced from the official OpenFEC API; amounts and names are as filed
  with the FEC.
- Billing is a single automatic Result event per dataset item.

# Actor input Schema

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

Your FREE api.data.gov key for the OpenFEC API, sent as ?api\_key=. Register in seconds at https://api.open.fec.gov/developers . DEMO\_KEY works only for light testing (~30 requests/hour, shared IP) — bring your own key for real runs.

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

search = list matching filings/receipts/disbursements; delta = only NEW rows (since a date and/or not seen in a prior run); concentration = top donors/vendors by summed amount with a Herfindahl (HHI) score; graph = contributor<->committee edge list.

## `dataType` (type: `string`):

Which OpenFEC feed to pull: receipts = itemized contributions (schedule\_a), disbursements = committee spending / vendor payments (schedule\_b), filings = report filings feed (/filings). Concentration/graph work on receipts (donors) or disbursements (vendors).

## `committeeId` (type: `string`):

FEC committee id to scope to, e.g. C00401224 (ActBlue). Strongly recommended for receipts/disbursements — narrows the huge itemized tables and avoids rate limits.

## `candidateId` (type: `string`):

FEC candidate id to scope to, e.g. P80001571. Returns rows tied to that candidate's committees.

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

Free-text name filter. For receipts it matches the contributor name; for disbursements it matches the recipient/payee name. Ignored for filings.

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

Two-letter state code, e.g. CA. For receipts = contributor state; for disbursements = recipient state; for filings = committee state.

## `sinceDate` (type: `string`):

Lower date bound. Maps to min\_date (receipts/disbursements) or min\_receipt\_date (filings). Drives the delta/monitoring window. Empty = no lower bound.

## `untilDate` (type: `string`):

Upper date bound. Maps to max\_date (receipts/disbursements) or max\_receipt\_date (filings). Empty = no upper bound.

## `minAmount` (type: `string`):

Only return transactions at or above this dollar amount (receipts/disbursements only). Empty = no minimum.

## `priorItems` (type: `array`):

Delta mode: the previous run's results (or a list of sub\_id strings). Any row already present is treated as seen and excluded, leaving only new activity. The actor also keeps its own rolling seen-set in the key-value store for scheduled runs.

## `concentrationBy` (type: `string`):

Which entity to roll up for concentration/graph modes: contributor = donor name, employer = donor employer (industry concentration), recipient = vendor/payee (disbursements), committee = receiving committee.

## `topN` (type: `integer`):

Keep only the top N entities (concentration) or edges (graph), ranked by summed amount.

## `maxResults` (type: `integer`):

Maximum number of itemized rows to fetch before delta/concentration/graph processing. Higher = more complete analytics but more API calls.

## Actor input object example

```json
{
  "apiKey": "DEMO_KEY",
  "mode": "search",
  "dataType": "receipts",
  "priorItems": [],
  "concentrationBy": "contributor",
  "topN": 100,
  "maxResults": 1000
}
```

# Actor output Schema

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

The default dataset.

# 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 = {
    "apiKey": "DEMO_KEY"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/fec-campaign-finance-delta").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 = { "apiKey": "DEMO_KEY" }

# Run the Actor and wait for it to finish
run = client.actor("malonestar/fec-campaign-finance-delta").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 '{
  "apiKey": "DEMO_KEY"
}' |
apify call malonestar/fec-campaign-finance-delta --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malonestar/fec-campaign-finance-delta",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "FEC Campaign-Finance Delta, Concentration & Donor Graph API",
        "description": "Track FEC filings & receipts: new-filing delta feed, donor/vendor concentration (HHI) analytics, and a contributor-committee graph. OpenFEC source.",
        "version": "1.0",
        "x-build-id": "zlIQybbXBxXqZxRtt"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/malonestar~fec-campaign-finance-delta/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-malonestar-fec-campaign-finance-delta",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/malonestar~fec-campaign-finance-delta/runs": {
            "post": {
                "operationId": "runs-sync-malonestar-fec-campaign-finance-delta",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/malonestar~fec-campaign-finance-delta/run-sync": {
            "post": {
                "operationId": "run-sync-malonestar-fec-campaign-finance-delta",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "apiKey": {
                        "title": "api.data.gov API key",
                        "type": "string",
                        "description": "Your FREE api.data.gov key for the OpenFEC API, sent as ?api_key=. Register in seconds at https://api.open.fec.gov/developers . DEMO_KEY works only for light testing (~30 requests/hour, shared IP) — bring your own key for real runs."
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "search",
                            "delta",
                            "concentration",
                            "graph"
                        ],
                        "type": "string",
                        "description": "search = list matching filings/receipts/disbursements; delta = only NEW rows (since a date and/or not seen in a prior run); concentration = top donors/vendors by summed amount with a Herfindahl (HHI) score; graph = contributor<->committee edge list.",
                        "default": "search"
                    },
                    "dataType": {
                        "title": "Data type",
                        "enum": [
                            "receipts",
                            "disbursements",
                            "filings"
                        ],
                        "type": "string",
                        "description": "Which OpenFEC feed to pull: receipts = itemized contributions (schedule_a), disbursements = committee spending / vendor payments (schedule_b), filings = report filings feed (/filings). Concentration/graph work on receipts (donors) or disbursements (vendors).",
                        "default": "receipts"
                    },
                    "committeeId": {
                        "title": "Committee ID",
                        "type": "string",
                        "description": "FEC committee id to scope to, e.g. C00401224 (ActBlue). Strongly recommended for receipts/disbursements — narrows the huge itemized tables and avoids rate limits."
                    },
                    "candidateId": {
                        "title": "Candidate ID",
                        "type": "string",
                        "description": "FEC candidate id to scope to, e.g. P80001571. Returns rows tied to that candidate's committees."
                    },
                    "name": {
                        "title": "Contributor / recipient name",
                        "type": "string",
                        "description": "Free-text name filter. For receipts it matches the contributor name; for disbursements it matches the recipient/payee name. Ignored for filings."
                    },
                    "state": {
                        "title": "State",
                        "type": "string",
                        "description": "Two-letter state code, e.g. CA. For receipts = contributor state; for disbursements = recipient state; for filings = committee state."
                    },
                    "sinceDate": {
                        "title": "Since date (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Lower date bound. Maps to min_date (receipts/disbursements) or min_receipt_date (filings). Drives the delta/monitoring window. Empty = no lower bound."
                    },
                    "untilDate": {
                        "title": "Until date (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Upper date bound. Maps to max_date (receipts/disbursements) or max_receipt_date (filings). Empty = no upper bound."
                    },
                    "minAmount": {
                        "title": "Minimum amount",
                        "type": "string",
                        "description": "Only return transactions at or above this dollar amount (receipts/disbursements only). Empty = no minimum."
                    },
                    "priorItems": {
                        "title": "Prior items (delta mode)",
                        "type": "array",
                        "description": "Delta mode: the previous run's results (or a list of sub_id strings). Any row already present is treated as seen and excluded, leaving only new activity. The actor also keeps its own rolling seen-set in the key-value store for scheduled runs.",
                        "default": []
                    },
                    "concentrationBy": {
                        "title": "Concentration / graph entity",
                        "enum": [
                            "contributor",
                            "employer",
                            "recipient",
                            "committee"
                        ],
                        "type": "string",
                        "description": "Which entity to roll up for concentration/graph modes: contributor = donor name, employer = donor employer (industry concentration), recipient = vendor/payee (disbursements), committee = receiving committee.",
                        "default": "contributor"
                    },
                    "topN": {
                        "title": "Top N (concentration / graph)",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Keep only the top N entities (concentration) or edges (graph), ranked by summed amount.",
                        "default": 100
                    },
                    "maxResults": {
                        "title": "Max results",
                        "minimum": 1,
                        "maximum": 500000,
                        "type": "integer",
                        "description": "Maximum number of itemized rows to fetch before delta/concentration/graph processing. Higher = more complete analytics but more API calls.",
                        "default": 1000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
