# Contract & Grant Fit Scout (`leisurely_wellhead/contract-fit-scout`) Actor

Find and qualify live US grants and UK public tenders against a company profile, with evidence-backed AI scoring.

- **URL**: https://apify.com/leisurely\_wellhead/contract-fit-scout.md
- **Developed by:** [James Allen](https://apify.com/leisurely_wellhead) (community)
- **Categories:** AI, Business, Lead generation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $340.00 / 1,000 qualified opportunities

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.

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

## Contract & Grant Fit Scout

Turn a company profile into a ranked shortlist of live public opportunities.

The Actor scans official US and UK sources, cheaply screens every notice, then uses AI only on the strongest candidates. Each returned match includes the deadline, value, buyer or agency, risks, next steps, and short evidence excerpts so a user can decide what deserves human attention.

### Why buyers use it

- Stop reading dozens of irrelevant notices.
- Find newly published work on a schedule.
- Explain why an opportunity fits instead of returning keyword-only search results.
- Surface disqualifiers and uncertainty before a team spends hours on a bid.
- Export the result to JSON, CSV, Excel, Zapier, Make, or the Apify API.

This is a qualification tool, not an automated bid writer. It deliberately links back to the original notice for final verification.

### Official sources

- [Grants.gov search API](https://www.grants.gov/api/common/search2) and [opportunity-detail API](https://www.grants.gov/api/common/fetchopportunity) for US federal grants. These retrieval endpoints do not require a customer API key.
- [UK Contracts Finder OCDS API](https://www.contractsfinder.service.gov.uk/apidocumentation) for current UK public-sector tender notices. Public retrieval does not require a customer account.

SAM.gov is intentionally not included in version 1 because its API requires each user to protect a private SAM.gov API key. It can be added later as an optional source without weakening the current no-extra-key setup.

### How it works

1. The user describes their organization and supplies a few search terms.
2. The Actor retrieves live notices from the selected official sources.
3. A deterministic scorer ranks phrase matches, company-profile overlap, exclusions, deadline timing, notice status, and available value.
4. Only the top `maxAiAnalyses` candidates go to the hosted AI reviewer.
5. The reviewer must return strict JSON, cite evidence from the notice, and list uncertainty and risks.
6. Only results at or above `minScore` are stored. Automatic-exclusion terms always win.
7. In pay-per-event mode, the Actor charges the `qualified-opportunity` event only when that result is pushed to the dataset.

This two-stage design keeps model usage controlled and prevents a customer from paying the result fee for rejected notices.

### Inputs

The generated Apify form is suitable for nontechnical users. The most important fields are:

| Field | Purpose | Good starting value |
|---|---|---|
| `companyProfile` | Capabilities, customers, regions, credentials, and exclusions | 1–3 specific paragraphs |
| `searchKeywords` | Services, industries, or problems to find | 3–8 phrases |
| `positiveKeywords` | Signals that improve fit | Certifications, buyer types, delivery models |
| `negativeKeywords` | Hard exclusions | Work the company cannot or will not perform |
| `minScore` | Strictness of returned results | `60` |
| `maxAiAnalyses` | Maximum candidates receiving AI review | `10` |
| `maxResultsPerSource` | Source candidates retained for scoring | `25` |
| `daysBack` | Newly published UK tender window | `14` |

See [`examples/INPUT.json`](examples/INPUT.json) for a complete sample.

### Output

Every dataset item is one qualified opportunity:

```json
{
  "rank": 1,
  "fitScore": 84.5,
  "verdict": "STRONG",
  "title": "Example data platform opportunity",
  "source": "UK Contracts Finder",
  "organization": "Example public buyer",
  "deadline": "2026-09-14T11:00:00+01:00",
  "value": 125000,
  "currency": "GBP",
  "summary": "The requested data integration and training align with the supplied profile.",
  "matchedCapabilities": ["Data integration", "Training"],
  "risks": ["The notice does not confirm required security accreditation."],
  "nextSteps": ["Verify accreditation requirements in the tender documents."],
  "evidence": [
    {"claim": "Training is in scope", "sourceText": "provide user training"}
  ],
  "url": "https://www.contractsfinder.service.gov.uk/Notice/example"
}
```

The default dataset offers a compact “Best matches” view and a detailed “Qualification detail” view. A `RUN_SUMMARY` record reports fetched, scored, qualified, stored, and failed-source counts.

### AI and privacy

AI review uses the [Apify OpenRouter integration](https://apify.com/apify/openrouter). On the Apify platform, the Actor receives `APIFY_TOKEN` automatically, so users do not paste an OpenAI or OpenRouter key into the input.

The company profile and selected opportunity text are sent through that hosted gateway to the selected model provider. Do not put passwords, private keys, personal records, export-controlled data, or confidential bid strategy in the profile. Source notices are treated as untrusted data; their text cannot change the review instructions.

Set `includeAiAnalysis` to `false` for deterministic-only screening. That mode is cheaper but less nuanced.

### Accuracy boundaries

- A high score is not proof of eligibility or a prediction of winning.
- Dates, values, and requirements can be amended at the source.
- Currency values are not converted; a single numeric floor is applied to the source currency.
- Grants.gov search results are limited by the supplied terms and official API behavior.
- Contracts Finder provides date/stage filtering but no text query on its public OCDS search endpoint, so the Actor retrieves a wider recent set and filters it locally.
- A missing published value is retained rather than incorrectly treated as zero.
- Always read the original notice and attached documents before bidding or applying.

### Run locally

Python 3.11 or newer is required.

```bash
python -m venv .venv
.venv/Scripts/pip install -r requirements.txt
copy examples\INPUT.json storage\key_value_stores\default\INPUT.json
.venv/Scripts/python -m src
```

For a hosted AI review, set `APIFY_TOKEN` in the environment. Never commit it. Without a token, use `"includeAiAnalysis": false`.

Run the offline checks:

```bash
python -m unittest discover -s tests -v
```

The Dockerfile follows Apify's current Python Actor template and can be built by the Apify platform.

### Monetization and schedules

Configure pay-per-event in Apify Console with the event name `qualified-opportunity`. The code already respects the customer's maximum total charge and stops when the event limit is reached. Pricing is configured in Console, not hard-coded in source.

For recurring prospecting, save a configured input as an Apify Task and add a weekly or weekday schedule. Results remain accessible through the task's dataset and standard integrations.

Follow [`PUBLISHING.md`](PUBLISHING.md) for the beginner-friendly launch steps and [`ECONOMICS.md`](ECONOMICS.md) for the pricing guardrails.

### Reliability

- Three-attempt retry policy for official HTTP sources.
- Source failures are isolated; one healthy source can still produce results.
- Grants.gov detail retrieval uses bounded concurrency.
- AI output is schema-checked, length-limited, and score-clamped.
- Exact negative terms are hard exclusions.
- Dataset items are stored with pay-per-event charging in one SDK operation.
- The run summary records partial source failures and spending-limit stops.

Built with the [Apify Python SDK](https://docs.apify.com/sdk/python/docs/overview) and its [pay-per-event safeguards](https://docs.apify.com/sdk/python/docs/concepts/pay-per-event).

# Actor input Schema

## `companyProfile` (type: `string`):

Describe services, customers, regions served, certifications, team experience, and anything you cannot do. This text is used to score fit.

## `searchKeywords` (type: `array`):

One service, industry, problem, or theme per line. These drive the official-source searches.

## `positiveKeywords` (type: `array`):

Optional terms that should increase a match score.

## `negativeKeywords` (type: `array`):

Any result containing one of these terms is excluded, even if its other signals are strong.

## `source` (type: `string`):

Search curated US state, local, and private funding; US federal grants; UK public tenders; or all sources.

## `minScore` (type: `number`):

Only return opportunities meeting this 0–100 score. Start at 60; raise it for fewer, stricter matches.

## `maxAiAnalyses` (type: `integer`):

The local scorer screens everything first. AI reviews only this many top candidates. In AI mode, only candidates with a successful evidence-backed review can become paid results.

## `includeAiAnalysis` (type: `boolean`):

Recommended. A failed or missing AI review is never stored as a paid result. Uses Apify OpenRouter; no separate model-provider key is needed on Apify.

## `maxResultsPerSource` (type: `integer`):

Maximum raw candidates collected from each source before filtering.

## `daysBack` (type: `integer`):

How far back to look for newly published UK tenders.

## `minOpportunityValue` (type: `number`):

Optional. Results with a stated maximum value below this are excluded. Results with no published value remain eligible.

## `grantsEligibilityCodes` (type: `array`):

Optional advanced Grants.gov filters, one official applicant-type code per line.

## `grantsAgencies` (type: `array`):

Optional advanced agency filters such as NSF or HHS.

## `grantsFundingCategories` (type: `array`):

Optional official funding-category codes, one per line.

## `model` (type: `string`):

OpenRouter model identifier used for qualification.

## Actor input object example

```json
{
  "companyProfile": "We are a small US-based software consultancy that builds secure data platforms, AI workflow automation, and analytics dashboards for nonprofits, universities, and public agencies. We can deliver discovery, prototypes, integrations, training, and ongoing support. We do not provide construction, medical care, or academic laboratory research.",
  "searchKeywords": [
    "artificial intelligence",
    "data analytics",
    "software development"
  ],
  "positiveKeywords": [
    "small business",
    "prototype",
    "automation"
  ],
  "negativeKeywords": [
    "construction",
    "clinical trial"
  ],
  "source": "all",
  "minScore": 60,
  "maxAiAnalyses": 10,
  "includeAiAnalysis": true,
  "maxResultsPerSource": 25,
  "daysBack": 14,
  "grantsEligibilityCodes": [],
  "grantsAgencies": [],
  "grantsFundingCategories": [],
  "model": "openai/gpt-5.4-mini"
}
```

# Actor output Schema

## `matches` (type: `string`):

No description

## `runSummary` (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 = {
    "companyProfile": "We are a small US-based software consultancy that builds secure data platforms, AI workflow automation, and analytics dashboards for nonprofits, universities, and public agencies. We can deliver discovery, prototypes, integrations, training, and ongoing support. We do not provide construction, medical care, or academic laboratory research."
};

// Run the Actor and wait for it to finish
const run = await client.actor("leisurely_wellhead/contract-fit-scout").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 = { "companyProfile": "We are a small US-based software consultancy that builds secure data platforms, AI workflow automation, and analytics dashboards for nonprofits, universities, and public agencies. We can deliver discovery, prototypes, integrations, training, and ongoing support. We do not provide construction, medical care, or academic laboratory research." }

# Run the Actor and wait for it to finish
run = client.actor("leisurely_wellhead/contract-fit-scout").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 '{
  "companyProfile": "We are a small US-based software consultancy that builds secure data platforms, AI workflow automation, and analytics dashboards for nonprofits, universities, and public agencies. We can deliver discovery, prototypes, integrations, training, and ongoing support. We do not provide construction, medical care, or academic laboratory research."
}' |
apify call leisurely_wellhead/contract-fit-scout --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leisurely_wellhead/contract-fit-scout"
        }
    }
}

```

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/8tNzMS8SwAkC8axzL/builds/kMlczSAa2LOlrZstH/openapi.json
