# Texas Government Bids — Open State & Local Solicitations (`recordstack/texas-government-bids`) Actor

Open bids from the official Texas TxSmartBuy ESBD portal — state agencies plus SmartBuy member cities, counties, school districts and universities. Filter by keyword, NIGP code, agency, or date. Deduped, open-only, with an 'only new since last run' mode. No SAM.gov noise.

- **URL**: https://apify.com/recordstack/texas-government-bids.md
- **Developed by:** [Alex Meacham](https://apify.com/recordstack) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 bid record delivereds

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?

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

## Texas Government Bids — Open State & Local Solicitations

**Every open bid on the official Texas TxSmartBuy portal (ESBD), as clean structured data — without digging through the portal's search UI, and without the federal SAM.gov noise.**

Texas state agencies and Texas SmartBuy member entities — cities, counties, school districts, universities, hospital districts — post solicitations of $25,000 and up on the Electronic State Business Daily (ESBD). This actor reads that same official portal and returns only what's open right now.

### What you get

One record per open solicitation:

- Solicitation ID and title
- Agency / SmartBuy member name and number
- Status (`Posted` or `Addendum Posted` — open only, no awarded/closed/cancelled history)
- Posting date, response due date and time
- NIGP commodity/service codes with descriptions (your trade filter)
- Direct link to the official posting, plus the agency's external bid link when one is provided
- Last-modified timestamp from the portal

### Who it's for

- **Contractors and service companies** (janitorial, HVAC, landscaping, electrical, construction, IT, staffing…) who sell to Texas government and want a daily feed of *their* trade's open bids.
- **Bid consultants and aggregators** building a Texas SLED pipeline without maintaining a portal scraper.
- **Sales teams** watching a specific agency or set of agencies.

### Inputs

| Input | What it does |
|---|---|
| Keyword | Free-text match (e.g. `janitorial`) |
| NIGP code | 5-digit trade code (e.g. `91039` janitorial, `91082` HVAC maintenance) |
| Agency number | Portal agency/member number (e.g. `601` TxDOT) |
| Posted on/after · on/before | Posting-date window |
| Solicitation ID | Look up one exact posting |
| Open only | Default on — open statuses only |
| **Only new since my last run** | Monitor mode: scheduled runs return *only* bids never delivered before. First run delivers the in-scope baseline. |
| Max results | Cap per run (you're only charged for what's delivered) |

### Pricing

**$0.003 per bid record delivered** (pay-per-event). A full sweep of every open Texas solicitation — 502 records at last check — costs about $1.51. A trade-filtered daily monitor run typically costs a few cents.

### Honest notes

- Source is the official portal itself (txsmartbuy.gov), read through the same public JSON service the site's own search page uses. No login is required or used. Data is as current as the portal; posting and due dates are the portal's own.
- "Open" follows the portal's own statuses. An addendum-posted bid is still open — it's included and labelled.
- Texas only. This actor deliberately does not clone the federal SAM.gov feeds — federal opportunities are a different (already well-served) market.
- Records are deduplicated on the portal's internal record ID. If a solicitation is reposted under a new ID, it counts as a new record, because it is one.

### Verified before listing

Local end-to-end test, 2026-10-27: full open sweep returned **502 records (365 Posted + 137 Addendum Posted), 0 duplicates, 0 non-open records**; keyword filter `janitorial` returned exactly the open janitorial postings; "only new" second run returned 0 records with both baseline records correctly skipped as already seen. Sample output: see `sample-output.json` in this repository.

# Actor input Schema

## `agencyNumber` (type: `string`):

Portal agency number as shown on the ESBD site (e.g. '601' for TxDOT, 'M0007' for City of Lubbock). Leave empty for all agencies.

## `keyword` (type: `string`):

Free-text keyword matched by the portal (e.g. 'janitorial', 'roofing', 'landscaping'). Leave empty for all open bids.

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

Cap on records delivered (and charged) in this run.

## `nigpCode` (type: `string`):

5-digit NIGP commodity/service code (e.g. 91039 = janitorial/custodial services, 91082 = HVAC maintenance). Leave empty for all trades.

## `onlyNewSinceLastRun` (type: `boolean`):

Monitor mode for scheduled runs. The actor remembers every record it has delivered (in its key-value state) and only returns records it has never delivered before. On the very first run everything in scope is delivered as the baseline.

## `openOnly` (type: `boolean`):

Recommended. When on (default), only 'Posted' and 'Addendum Posted' records are returned — no awarded, closed, or cancelled history.

## `postedAfter` (type: `string`):

Only solicitations posted on or after this date.

## `postedBefore` (type: `string`):

Only solicitations posted on or before this date.

## `solicitationId` (type: `string`):

Exact solicitation ID to look up a single posting. Leave empty otherwise.

## Actor input object example

```json
{
  "agencyNumber": "601",
  "keyword": "janitorial",
  "maxResults": 100,
  "nigpCode": "91039",
  "onlyNewSinceLastRun": false,
  "openOnly": true,
  "postedAfter": "2026-10-01",
  "postedBefore": "2026-10-27"
}
```

# Actor output Schema

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

URL to the dataset containing the rows from this run.

# 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("recordstack/texas-government-bids").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("recordstack/texas-government-bids").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 recordstack/texas-government-bids --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,recordstack/texas-government-bids"
        }
    }
}
```

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/rcB2SqKtoq09kshBe/builds/hdkjvgL2tAcWBDq4J/openapi.json
