Tutorial

Check for new notices on your schedule

Run your own script and keep a local list of seen notice IDs.

← All tutorials

Before you start

You need active GovBiz API access and a key with the search permission. Create your key first.

Use Python 3.12 or later. The example uses the standard library. Save your key in GOVBIZ_API_KEY.

Each request uses your shared workspace allowance. The examples do not send email or update another service.

Run the example

Save the code in query.py. Run it with python3 query.py.

import json, os, pathlib, time, urllib.error, urllib.request

state = pathlib.Path("seen-notices.json")
seen = set(json.loads(state.read_text())) if state.exists() else set()
url = "https://www.govbiz.ai/api/v2/opportunities/search?naics_code=541512&posted_within_days=7&limit=100"
request = urllib.request.Request(url, headers={
    "Authorization": "Bearer " + os.environ["GOVBIZ_API_KEY"]
})
for attempt in range(3):
    try:
        with urllib.request.urlopen(request, timeout=30) as response:
            result = json.load(response)
        break
    except urllib.error.HTTPError as error:
        if error.code not in (429, 502, 503, 504) or attempt == 2:
            raise
        delay = int(error.headers.get("Retry-After", "5"))
        time.sleep(min(max(delay, 5) * (attempt + 1), 60))
rows = result["data"]["results"]
for row in rows:
    if row["notice_id"] not in seen:
        print(row["notice_id"], row["title"])
        seen.add(row["notice_id"])
temporary = state.with_suffix(".tmp")
temporary.write_text(json.dumps(sorted(seen)))
temporary.replace(state)
if result["data"]["total_count"] > 100:
    print("More records match. Add pagination before using this for complete coverage.")

Check the result

The script prints notice IDs it has not seen. It then saves those IDs in seen-notices.json.

Live results change. Compare the response shape with our captured sample and check the original notices.

Use your own scheduler to run this script. Allow one run at a time and keep the state file between runs.

This example checks one page and tracks new IDs only. It does not detect changed deadlines or guarantee complete coverage.

Add pagination and field comparisons if you need them. Confirm your scheduler’s availability and fees before relying on it.

Limits and care

Keep credentials out of shared code, browser bundles, and workbooks you distribute. Excel parameters may be visible to people who can open the workbook.

Check HTTP errors before using results. Retry temporary errors with a delay. Avoid repeated retries for authentication failures.

These examples use explicit filters. They do not make bid decisions or produce proposals.