CivicTechTO / CivicTechTO/toronto-bids

TTC procurement (MERX) — the largest single buyer we do not archive

Open
#104 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
7
Forks
2
PR merge metrics
No merged PRs in 30d

Description

Part of #103. **Verified, not assumed** — but do not start until #103 settles the keyspace and the terms-of-use question.

## Why this one first

The TTC is almost certainly the largest procuring body in Toronto outside the City's own divisions, and it publishes more than the City does in one respect: **bid results are posted, not just awards**.

## What exists

All publicly advertised TTC solicitations go to **MERX** — `https://www.merx.com/ttc`. Per the TTC's own page, the sections are:

> **Open Solicitations, Closed Solicitations, Bids Results, Awarded Solicitations**

- **Threshold:** tenders over **$100,000** are publicly advertised; below that they may be. Construction, engineered equipment and vehicles may be advertised at any value.
- **Awarded solicitations** — `https://www.merx.com/ttc/solicitations/awarded-bids`
- **Non-competitive awards over $100,000** are posted separately on ttc.ca, *not* MERX — a second source, and the direct analogue of our `noncompetitive` table.

## The caveat the TTC states itself, which matters for our `bid` table

> "Solicitation results posted on MERX are based on submissions that have **not yet been evaluated**"

and for RFPs, results carry **only the proponent's name and closing date** — no price.

So TTC bid results are **not** the same fact as our `bid` rows, which come from the Bid Award Panel's post-evaluation tables. An unevaluated submission list includes bidders later found non-compliant, with no marker. Storing both under one `bid` table without recording which is which would repeat the `hst_basis` mistake: two incomparable things in one column.

## Steps

1. **Wait for #103** to settle the keyspace and terms of use. Neither is TTC-specific and both block everything.
2. Determine what MERX exposes to a plain HTTP client: is there a JSON endpoint, an RSS/export, or is it an authenticated SPA? Record the answer either way — the Ariba detail API's 401 (#78) was worth knowing precisely.
3. If it is reachable, **write a MERX adapter, not a TTC scraper**: Toronto Police (#105) and the Parking Authority (#106) sit on the same platform under the same URL shape.
4. Model the "unevaluated submissions" distinction explicitly before storing a single bid row.

## First step

Fetch `https://www.merx.com/ttc` and answer exactly one question: **does the public solicitation list render without an account?** That decides whether this is an afternoon or a browser project, and it costs one request.

## Sources

- https://www.ttc.ca/doing-business-with-the-ttc/Procurement-and-Category-Management/solicitations-and-results
- https://www.merx.com/ttc
- https://www.ttc.ca/doing-business-with-the-ttc/Procurement-and-Category-Management/about-ttcs-Procurement-and-Category-Management-department/selling-to-the-ttc

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by fetching https://www.merx.com/ttc with a plain HTTP client and record whether the public solicitation list renders without an account. Then read #103 for the keyspace and terms-of-use decisions; if access is feasible, define a MERX adapter and model unevaluated submissions separately from evaluated bid rows. Done means those access, policy, and data-model questions are settled.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-engineering
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.