Bonfirehub APIttc.bonfirehub.ca ↗
Retrieve all currently open TTC procurement opportunities from ttc.bonfirehub.ca. Get reference numbers, titles, statuses, and closing dates in one call.
What is the Bonfirehub API?
The TTC Bonfire Procurement API exposes the Toronto Transit Commission's open public procurement opportunities through a single endpoint, list_open_opportunities, returning up to 7 fields per record including reference number, title, status, and closing date in Toronto local ISO 8601 format. The entire open opportunity list is delivered in one response and supports local pagination, making it straightforward to monitor new tenders or track closing deadlines programmatically.
curl -X GET 'https://api.parse.bot/scraper/4f57a7fd-0076-4630-af93-7d678f9e714b/list_open_opportunities?page=2&page_size=5' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace ttc-bonfirehub-ca-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: TTC Procurement Portal — list open opportunities, capped."""
from parse_apis.ttc_bonfirehub_ca_api import TtcProcurement, ParseError
client = TtcProcurement()
# Browse the first 5 open procurement opportunities sorted by closing date.
for opp in client.opportunities.list(page_size=5, limit=5):
print(opp.title, "|", opp.reference_number, "| days left:", opp.days_left)
# Drill into the soonest-closing opportunity for detail.
try:
soonest = client.opportunities.list(page_size=1, limit=1).first()
except ParseError as e:
print("Upstream issue:", e.code)
soonest = None
if soonest is not None:
print("Soonest closing:", soonest.title)
print(" Closes:", soonest.closing_date)
print(" Portal link:", soonest.detail_url)
print(" Department ID:", soonest.department_id)
print("exercised: opportunities.list")
Returns the open public procurement opportunities currently published on the TTC procurement portal, one record per opportunity, sorted by closing date ascending (ties broken by reference number). The portal publishes the whole open list in a single response, so each call makes one round trip and pagination is applied locally: `page` (1-based, defaults to 1) and `page_size` (defaults to 20, values above 100 are clamped to 100) select a slice; `total` is the number of open opportunities on the portal, `total_pages` derives from it, and `has_more` is true while later pages exist. A page past the end returns an empty `opportunities` array with `has_more` false. Closing times are given both in the portal's local Toronto time (`closing_date`, ISO 8601 with offset) and in UTC (`closing_date_utc`); `days_left` is whole days remaining until closing, computed at call time (0 when closing today). `status` is the portal's status label; only opportunities the portal lists as Open appear here. `detail_url` is the public opportunity page on the portal.
| Param | Type | Description |
|---|---|---|
| page | integer | 1-based page number of the locally paginated result list. |
| page_size | integer | Number of opportunities per page; values above 100 are clamped to 100. |
{
"type": "object",
"fields": {
"page": "integer, the page returned",
"total": "integer, total open opportunities on the portal",
"has_more": "boolean, whether a later page exists",
"page_size": "integer, the effective page size after clamping",
"total_pages": "integer, number of pages at this page_size",
"opportunities": "array of opportunity summaries, each with opportunity_id, reference_number, title, status, closing_date (Toronto local ISO 8601), closing_date_utc, days_left (integer), department_id, detail_url"
},
"sample": {
"data": {
"page": 1,
"total": 15,
"has_more": true,
"page_size": 5,
"total_pages": 3,
"opportunities": [
{
"title": "NEW SWITCH MACHINE TRIAL",
"status": "Open",
"days_left": 0,
"detail_url": "https://ttc.bonfirehub.ca/opportunities/110461",
"closing_date": "2026-10-02T14:00:00-04:00",
"department_id": "661",
"opportunity_id": "110461",
"closing_date_utc": "2026-10-02T18:00:00Z",
"reference_number": "P58CF25674"
},
{
"title": "ARC FLASH HAZARD INCIDENT ENERGY ANALYSIS STUDY & REPORT — 5 SUBSTATIONS",
"status": "Open",
"days_left": 4,
"detail_url": "https://ttc.bonfirehub.ca/opportunities/104460",
"closing_date": "2026-10-06T14:00:00-04:00",
"department_id": "661",
"opportunity_id": "104460",
"closing_date_utc": "2026-10-06T18:00:00Z",
"reference_number": "P58PI26175"
}
]
},
"status": "success"
}
}About the Bonfirehub API
What the API Returns
The list_open_opportunities endpoint returns every currently open procurement opportunity published on the TTC's Bonfire portal. Each record in the opportunities array includes opportunity_id, reference_number, title, status, and closing_date expressed in Toronto local ISO 8601 format. Results are sorted by closing_date ascending, with ties broken by reference_number.
Pagination
The response includes page, page_size, total, total_pages, and has_more fields to help you navigate the full list. The page input is 1-based. The page_size parameter controls how many opportunities appear per page, and any value above 100 is automatically clamped to 100. Because the portal publishes the full open list in a single response, all paginated views reflect the same snapshot.
Data Freshness and Scope
The API covers opportunities that are currently in the open state on the TTC Bonfire portal. Closed, awarded, or cancelled opportunities are not included in the response. The closing_date field is particularly useful for building deadline-tracking tools or alert systems, since records are ordered by that field by default.
Official API Availability
The TTC does not publish an official developer API for its Bonfire procurement portal. This Parse API provides structured, paginated access to the open opportunity data that would otherwise require manual review of the portal's web interface.
The Bonfirehub API is a managed, monitored endpoint for ttc.bonfirehub.ca — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when ttc.bonfirehub.ca changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official ttc.bonfirehub.ca API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Monitor upcoming TTC contract deadlines by sorting on
closing_dateto prioritize bid preparation. - Build a daily digest that alerts procurement teams when new opportunities appear with a new
reference_number. - Aggregate TTC open tenders into a unified public-sector procurement dashboard alongside other transit agencies.
- Track the
statusfield over time to detect when a previously open opportunity changes state. - Audit the total volume of open TTC procurements at a point in time using the
totalresponse field. - Feed opportunity
titleandreference_numberdata into an internal CRM for vendor pipeline management.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does the TTC have an official developer API for its procurement portal?+
What does `list_open_opportunities` return, and can I filter by category or type?+
opportunity_id, reference_number, title, status, and closing_date. There is no server-side filter by category or procurement type — the full open list is returned and you apply any filtering client-side after retrieving the data.Does the API include closed, awarded, or cancelled opportunities?+
Can I retrieve the full details of a specific opportunity, such as attached documents or contact information?+
opportunity_id, reference_number, title, status, and closing_date. It does not fetch per-opportunity detail pages, attachments, or contact fields. You can fork it on Parse and revise to add a detail endpoint for individual opportunities.How does pagination work, and what happens if I request more than 100 results per page?+
page parameter. Any page_size value above 100 is clamped to 100, and the response reflects the effective page_size after clamping. Use the has_more and total_pages fields to determine whether additional pages exist.