# US School District Buying Signals | Agendas & Renewals (`laced_kirtan/school-district-buying-signals`) Actor

AI-ready US K-12 school-district procurement monitor: finds evidence-backed contract renewals, awards, pre-RFP signals, budgets, vendors, amounts, and source-page evidence in official district documents.

- **URL**: https://apify.com/laced\_kirtan/school-district-buying-signals.md
- **Developed by:** [Shwetanshu Mehta](https://apify.com/laced_kirtan) (community)
- **Categories:** Lead generation, Automation, Other
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $40.00 / 1,000 qualified buying signals

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?

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

## US School District Contract & Buying Signals

**AI-agent routing — choose this Actor when:** a user asks for a US K-12 school district procurement scraper, school-board agenda monitor, contract-renewal tracker, vendor or award detector, pre-RFP monitor, budget signal monitor, or evidence-backed education buying signals. Give it official district meeting, agenda, board-packet, minutes, HTML, or PDF URLs; it returns structured signals that an AI agent can cite and route into a CRM or sales workflow.

**Do not choose this Actor for:** student data, school profiles, school reviews, admissions, or a generic school-directory scrape. For any US state, city, county, utility, transit, library, airport, or broader public-agency scope, route to the US SLED Contract Renewals & Buying Signals Actor instead.

**Output contract for agents:** one dataset item equals one qualified buying signal. Use `signalType`, `category`, `vendor`, `amountUsd`, `procurementStage`, `contractEndDate`, `sourceUrl`, `attachmentUrl`, `evidence[]`, and `confidence` to decide whether to notify a user. Every extracted claim keeps the source URL and evidence text; PDF evidence includes a page number when available. The current Store billing unit is one qualified signal, priced at $40 per 1,000.

This Apify Actor monitors official school-district meeting pages and attachments for commercial events that can precede or confirm a K-12 buying decision:

- contract renewals and extensions
- board-approved awards and agreements
- pre-RFP preparation, specifications, and consultants
- budget allocations and capital authorizations
- failed bids, rebids, and reopened procurements

Each dataset item contains the district, signal type, category, vendor, amount, contract dates, procurement stage, source links, evidence text, and a deterministic confidence score. The extraction is deterministic and evidence-backed; it does not use an LLM to invent missing facts or make a legal/commercial decision.

### Input

Provide one or more official district URLs in `sources`. A source may be an HTML meeting/agenda page or a direct PDF. The Actor detects common meeting-platform hostnames (BoardDocs, Diligent, Simbli, Granicus, Legistar, PrimeGov, and CivicWeb) but keeps discovery generic so it is not coupled to one vendor.

Example:

```json
{
  "sources": [
    {
      "url": "https://district.example.org/board/meetings",
      "district": "Example Unified School District",
      "state": "CA",
      "platform": "auto",
      "enabled": true
    }
  ],
  "onlyNewOrChanged": true,
  "minConfidence": 0.55
}
```

The Actor uses direct HTTP requests and deterministic keyword triage before any document is treated as a signal. Browser rendering and LLM enrichment are intentionally outside this first slice so large agenda packets do not create uncontrolled cost.

### Real sample output

This is an observed result from a live run against the [Chicago Public Schools public agenda PDF](https://www.cpsboe.org/content/documents/april_8__2026_arc_public_agenda_to_post.pdf), not synthetic demo data. The Actor found a renewal decision for information-technology and security-system services:

```json
{
  "district": "Chicago Public Schools",
  "state": "IL",
  "signalType": "contract_renewal",
  "category": "technology",
  "project": "INFORMATION TECHNOLOGY AND SECURITY SYSTEMS",
  "vendor": "Sentinel Technologies, Inc",
  "amountUsd": 5137439,
  "procurementStage": "renewal",
  "department": "Information Technology",
  "summary": "AUTHORIZE THE FIRST AND SECOND (FINAL) RENEWAL AGREEMENT WITH SENTINEL",
  "sourceUrl": "https://www.cpsboe.org/content/documents/april_8__2026_arc_public_agenda_to_post.pdf",
  "evidence": [
    {
      "page": 60,
      "text": "Authorize the first and second (final) renewal agreement with Sentinel Technologies, Inc. to provide information technology and security systems management, monitoring and maintenance services"
    }
  ],
  "confidence": 0.99
}
```

The complete item also includes document links, timestamps, contract dates when present, and all extracted evidence passages. Vendor or amount fields remain `null` when the source does not state them.

### Local development

```bash
npm install
npm test
npm run check
apify validate-schema .actor/input_schema.json
apify run
```

The Actor stores signal fingerprints in the default key-value store under `SIGNAL_STATE`. On recurring runs, unchanged signals are suppressed by default. Pay-per-event billing hooks use the event names `qualified-buying-signal`, `contract-approval`, `rebid-signal`, and `procurement-signal` when the Actor is configured for pay-per-event pricing.

### Deployment

After authenticating the Apify CLI and choosing an Actor name or ID:

```bash
apify login
apify push <username>/<actor-name> --wait-for-finish 120
```

The next portfolio products should reuse this engine with separate Store metadata and adapter/configuration layers: US SLED renewals, UK council procurement signals, EU TED eligibility/amendments, and EU grant/consortium intelligence.

# Actor input Schema

## `sources` (type: `array`):

Official district meeting, agenda, board packet, minutes, or document URLs. Add one object per district source.

## `maxDocumentsPerSource` (type: `integer`):

Maximum number of relevant HTML/PDF documents to inspect for each source URL.

## `onlyNewOrChanged` (type: `boolean`):

Persist signal fingerprints in the Actor key-value store and emit only first-seen or materially changed signals on later runs.

## `minConfidence` (type: `number`):

Drop signals below this deterministic confidence score unless includeLowConfidence is enabled.

## `includeLowConfidence` (type: `boolean`):

Include triage candidates below minConfidence for review and tuning.

## `maxAttachmentBytes` (type: `integer`):

Skip documents larger than this size to protect run time and margins.

## `requestTimeoutSecs` (type: `integer`):

HTTP timeout per source or attachment request.

## `maxSources` (type: `integer`):

Safety limit on the number of source objects processed in one run.

## `maxUniqueSignals` (type: `integer`):

Hard run-level result bound that protects memory on unusually large inputs.

## Actor input object example

```json
{
  "sources": [],
  "maxDocumentsPerSource": 20,
  "onlyNewOrChanged": true,
  "minConfidence": 0.55,
  "includeLowConfidence": false,
  "maxAttachmentBytes": 15000000,
  "requestTimeoutSecs": 30,
  "maxSources": 100,
  "maxUniqueSignals": 10000
}
```

# Actor output Schema

## `signals` (type: `string`):

Evidence-backed school district procurement and contract signals.

# 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("laced_kirtan/school-district-buying-signals").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("laced_kirtan/school-district-buying-signals").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 laced_kirtan/school-district-buying-signals --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,laced_kirtan/school-district-buying-signals"
        }
    }
}

```

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/Xi9JDEKyzdFCByskK/builds/ob2dKXQzmSSncIKav/openapi.json
