# Connecticut Open Expenditures - Every State Payment (`j0401/ct-open-expenditure`) Actor

Every payment Connecticut's state government made for goods and services (public open data, ~6.16M payment lines, FY2020-2027): service, department, program, expense category, fund and type, vendor with exact vendor id, payment method and status, payment and invoice dates, and amount.

- **URL**: https://apify.com/j0401/ct-open-expenditure.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 connecticut payment 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/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

## Connecticut Open Expenditures - Every State Payment

Every payment the State of Connecticut made for goods and services, straight
from the State's open expenditure ledger. **~6.17 million payment lines**, from
fiscal 2020 through fiscal 2027.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.** Pay only for the
records you actually receive - the whole ledger stays queryable, you are never
billed for the scan behind it.

### What you get

One row per payment line, with the full money trail attached:

- **Who was paid** - vendor name, plus the **exact vendor id** (a stable key,
  unlike the free-text name)
- **What kind of vendor** - Corporation, LLC, Sole Proprietor, Non-Profit,
  P-card Merchant, Governmental
- **Who paid** - the government function, the department (agency) and the
  budget program, and the account
- **What for** - the expense category, from the State's own chart
- **Out of what** - the fund and the fund type (General, Special Revenue,
  Capital Projects, Enterprise)
- **When and how** - payment date, invoice date, payment method and status
- **How much** - the amount, plus the contract and purchase-order references
  behind it

That is the full chain: function -> department -> program -> expense -> fund ->
vendor -> amount.

#### One thing to know up front

The State publishes this ledger as **two near-duplicate tables** -
`corpus=current` (Ledger Current, the default) and `corpus=archive` (Ledger
Archive) - and they cover the same payments. As of 2026-10-01 their
per-fiscal-year row counts run ~1.7-2.5% apart (FY2027, the current year, is
\~62% apart, since it is mid-year) - they are almost the same payments, but not
byte-for-byte. **Read one; never sum them.**

Which table advances tracks the State's migration - and the labels inverted
during a Sep-2026 maintenance window. **As of 2026-10-01 the default
`current` is the live one** (payments through 2026-09-30) while `archive`
stopped at 2026-09-25 - so the default already gives you the freshest data, and
you only pass `corpus` to reach the other table deliberately.

### Filter it

- **Vendor** - `vendor="Amazon"` (substring) or `vendorId="0000053057"`
  (exact).
- **Function, department, program** - `service="HEALTH"`,
  `department="Transportation"` (agencies, ~90 of them), `program="Tax Relief"`
  (budget programs, ~3,400 of them). `department` and `program` are normalized
  across both tables, so the same field means the same thing whichever corpus
  you read.
- **Expense category** - `expenseCategory="State Aid"`,
  `expenseCategory="Electricity"`. 387 categories in total.
- **Fund** - `fund="Federal"` (the fund name, substring) or `fundType="GENERAL"`
  (the fund *category*: General, Special Revenue, Capital Projects, Enterprise,
  Agency, Internal Service, Pension Trust, Other Trust Funds - 8 in all).
- **Vendor type** - Corporation, Non-Profit, Sole Proprietor
- **Amount** - `minAmount=1000000` for seven-figure payments.
- **Date range** and **last-N-days**.

### Example inputs

**Payments to one supplier** - `vendor` is a substring match.

```json
{ "vendor": "AMAZON", "maxResults": 25 }
```

**One function's spending on one thing** - combine function and category.

```json
{ "service": "TRANSPORTATION", "expenseCategory": "Highway", "maxResults": 50 }
```

**The largest payments** - seven figures and up.

```json
{ "minAmount": 1000000, "maxResults": 50 }
```

**Where the money goes** - `mode=aggregate` returns one count row per function;
every group comes back.

```json
{ "mode": "aggregate", "groupBy": "service" }
```

### Or roll it up

Set `mode=aggregate` and get a rolled-up count by **service**,
**department**, **program**, **expense category**, **fund**, **fund type**,
**payment status**, **payment method**, **vendor type**, **fiscal year** or
**fiscal year period**. Every group comes back - not cut off by `maxResults`.
The default dimension is `service` (10 values); `program` has ~3,400 values
and returns a long result.

### Then follow the money

- Total state spending by function or department, over any window.
- Every payment a supplier has received from the State, and for what.
- General, Special Revenue, Capital Projects and Enterprise spend, side by
  side - or the fund breakdown, federal money included.
- Payments by method and status - what clears, what is stopped or void.
- The biggest payments, newest first.

### Example output

**One payment line** - `vendor="CDW"`, default corpus:

```json
{
 "platform": "ct-open-expenditure",
 "source": "ct-open-expenditures-current",
 "mode": "rows",
 "groupKey": "",
 "groupCount": "",
 "groupBy": "",
 "fiscalYear": "2027",
 "fiscalYearPeriod": "3",
 "service": "EDUCATION",
 "department": "State Dept of Education",
 "program": "CT Tech Educ and Career Sys",
 "account": "54154",
 "expenseCategory": "IT Hardware Non-Controllable",
 "fundCode": "11000",
 "fund": "General Fund",
 "fundType": "GENERAL",
 "vendor": "CDW GOVERNMENT LLC",
 "vendorId": "0000010232",
 "vendorType": "LLC - Corporation",
 "paymentId": "0020327484",
 "paymentCount": "1",
 "paymentMethod": "Automated Clearing House",
 "paymentStatus": "Paid-Unreconciled",
 "paymentDate": "2026-09-29T00:00:00.000",
 "paymentDescription": "Paid",
 "invoiceId": "TECM100109994",
 "invoiceDate": "2026-09-29T00:00:00.000",
 "invoiceLineNumber": "1",
 "amount": "250.14",
 "contractNumber": "24PSX0154AA",
 "purchaseOrderNumber": "TECM10000031534",
 "purchaseOrderLineNumber": "1",
 "corpus": "current",
 "sourceUpdatedAt": "2026-09-30"
}
```

**`mode=aggregate`, `groupBy=service`** - one count row per government function
(default corpus; the archive table gives slightly different counts):

```
HEALTH & HOSPITALS            1,152,721
TRANSPORTATION                  896,973
GENERAL GOVERNMENT              799,446
JUDICIAL                        710,735
CORRECTIONS                     669,113
REGS & PROTECTION               641,626
```

### Notes on the data, from the source

- **A row is a payment line, not a payment.** One payment id covers several
  accounting lines (~6.16M lines carry ~1.95M distinct payment ids). The
  payment id is a grouping key, not a row key.
- **Refunds and reversals are in here.** 59,707 lines are negative on
  `archive` and 116,639 on `current` - real
  accounting entries, returned as they stand. Set `minAmount=0.01` for payments
  only.
- **Two ledger tables, near-duplicates.** See above - read one, never sum them.
- **Some rows have no vendor type.** ~322,000 lines carry none; filtering on a
  vendor type excludes them.
- **Vendor names are free text as typed into the system** - `AMAZON RETAIL`,
  `AMAZON.COM*5H0SB5182` and `AMAZON MKTPL*5H1353XI1` are all the same
  supplier. Use `vendorId` when you need one identity.
- **The ledger follows the State's accounting cycle**, not a daily feed;
  `sourceUpdatedAt` carries the dataset's own refresh date.

# Actor input Schema

## `vendor` (type: `string`):

Substring match on the payee name, e.g. 'AMAZON', 'DELL', 'MEDICAL'. Vendor names are free text as typed into the accounting system, so the same supplier can appear under several spellings. Blank = any.

## `vendorId` (type: `string`):

Substring match on the exact vendor identifier, e.g. '0000053057'. This is a stable key, unlike the free-text vendor name. Blank = any.

## `department` (type: `string`):

Substring match on the department (state agency), e.g. 'Transportation', 'Correction', 'Mental Health'. 90 agencies in total. Normalized across both ledger tables. Blank = any.

## `service` (type: `string`):

Substring match on the top-level government function, e.g. 'HEALTH', 'TRANSPORTATION', 'JUDICIAL', 'CORRECTIONS'. 10 functions in total. Blank = any.

## `program` (type: `string`):

Substring match on the budget program, e.g. 'Other Expenses', 'Tax Relief', 'Renters Rebate'. 3,381 programs in total - fine-grained. Normalized across both ledger tables. Blank = any.

## `expenseCategory` (type: `string`):

Substring match on the spending category, e.g. 'STATE AID', 'ELECTRICITY', 'SUPPLIES', 'GRANT'. 387 categories in total. Blank = any.

## `fund` (type: `string`):

Substring match on the fund, e.g. 'GENERAL', 'FEDERAL', 'TRANSPORTATION'. 87 funds in total. Blank = any.

## `account` (type: `string`):

Substring match on the account code, e.g. '54010'. Blank = any.

## `contractNumber` (type: `string`):

Substring match on the contract number. Blank = any.

## `purchaseOrderNumber` (type: `string`):

Substring match on the purchase order number. Blank = any.

## `paymentId` (type: `string`):

Substring match on the payment identifier. One payment covers several accounting lines, so the same id appears on multiple rows - it is a grouping key, not a row key. Blank = any.

## `fundType` (type: `string`):

Exact fund type the payment was charged to. Blank = any.

## `paymentStatus` (type: `string`):

Exact payment status. Blank = any.

## `paymentMethod` (type: `string`):

Exact payment method. Blank = any.

## `vendorType` (type: `string`):

Exact vendor type. Note 322,330 rows carry no vendor type at all - filter on a type and they are excluded. Blank = any.

## `fiscalYear` (type: `integer`):

Exact state fiscal year (July-June), e.g. 2025. Blank = any. FY2020-FY2027 are present.

## `paymentFrom` (type: `string`):

Earliest payment date, YYYY-MM-DD. Blank = any.

## `paymentTo` (type: `string`):

Latest payment date, YYYY-MM-DD. Blank = any.

## `minAmount` (type: `number`):

Smallest payment amount in dollars. Leave blank to include refunds and reversals, which are negative (59,707 lines on the archive ledger, 116,639 on current). Set 0.01 for payments only.

## `maxAmount` (type: `number`):

Largest payment amount in dollars. Blank = no upper bound.

## `recentDays` (type: `integer`):

Only payments whose payment date falls within the last N days. Ignored when 'Payment date from' is set. 0 = off.

## `corpus` (type: `string`):

Which ledger table: 'current' = Ledger Current (default), 'archive' = Ledger Archive. The two are near-duplicate copies of the same payments - read one, never sum them.

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

rows = payment lines matching your filters (default). aggregate = one count row per group (see groupBy).

## `groupBy` (type: `string`):

Which dimension to aggregate over (mode=aggregate). Blank = service (10 values). Note 'program' has 3,375 values and returns a long result. Every group is returned.

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

Cap the number of records pushed in rows mode (0 = default 50; up to 2,000 per run). Each record is metered individually, so there is no per-run charge cap. Aggregate mode returns every group.

## Actor input object example

```json
{
  "vendor": "",
  "vendorId": "",
  "department": "",
  "service": "",
  "program": "",
  "expenseCategory": "",
  "fund": "",
  "account": "",
  "contractNumber": "",
  "purchaseOrderNumber": "",
  "paymentId": "",
  "fundType": "",
  "paymentStatus": "",
  "paymentMethod": "",
  "vendorType": "",
  "paymentFrom": "",
  "paymentTo": "",
  "recentDays": 0,
  "corpus": "current",
  "mode": "rows",
  "groupBy": "",
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

Connecticut state payment records - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/ct-open-expenditure").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/ct-open-expenditure").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 '{}' |
apify call j0401/ct-open-expenditure --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/ct-open-expenditure"
        }
    }
}
```

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/MMP77dvgxnhueBGdl/builds/0WcNfSyIZBxynotvY/openapi.json
