Skip to content

About

Who wins Swiss public contracts? Local copy of simap.ch linked to the commercial register (Zefix).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TenderWatch

Who wins Swiss public contracts? TenderWatch keeps a local copy of the publications of simap.ch — the joint procurement platform of the Swiss Confederation, cantons and municipalities — and links every award winner to the Swiss commercial register (Zefix) through its UID (CHE-123.456.789).

What it does today:

  • collects every simap publication (tenders, awards, direct awards, abandonments…) through simap's public API, project by project and lot by lot, and keeps the raw answers — an edited publication never overwrites the previous version;
  • links each winner to its commercial-register record (legal name, status, seat, legal form, official gazette notices);
  • ranks the companies that win the most contracts, by number of awards, published amount or number of contracting authorities;
  • computes two risk indicators, preliminary: contracting authorities that receive single bids (docs/indicators/single-bid.md), or award contracts directly, without competition (docs/indicators/direct-award.md), more often than on similar contracts — with the legal ground each direct award cites, read from its free-text justification.

What it is heading for: risk indicators on procedures — single bids, direct awards and the exemption invoked, short tender periods, concentration of one winner at one contracting authority… See docs/methodology.md.

The most reusable piece is probably docs/simap-api.md: field-level notes on simap's public API — which endpoints answer without a token, pagination, lots, and the traps found while building this.

Status: early, working version. Data from 1 July 2024 onwards (the new simap platform); the 2007–2024 archive is not collected yet.

A word on vocabulary

TenderWatch computes risk indicators, never verdicts. A single signal says little: in August 2026, 13 % of awards received a single bid (150 sampled), and each signal has legitimate explanations — a remote valley with one supplier, an intellectual-property right, a short deadline announced long in advance. Indicators are always compared with similar contracts, and the method is published with the result.

Install

Requires Python ≥ 3.11 and PostgreSQL (≥ 13).

python3 -m venv venv
venv/bin/pip install -e '.[test]'
createdb tenderwatch
venv/bin/tenderwatch init-db

The database is reached through a libpq connection string in TENDERWATCH_DSN (default dbname=tenderwatch, local unix socket).

Zefix credentials

Linking winners to the commercial register needs access to the Zefix PublicREST API, run by the Federal Registry of Commerce (FRC). Access is free but personal: request a username and password by email to zefix@bj.admin.ch, stating your intended use. The API is documented on its Swagger page.

Credentials are read from the environment only, never from the command line (argv is visible to every local user through ps):

export ZEFIX_USERNAME=…  ZEFIX_PASSWORD=…
# or keep them in a file readable by you only, then:
set -a && . ~/.config/tenderwatch/zefix.env && set +a

Zefix asks users to avoid repeated bulk queries: TenderWatch queries each UID once and keeps the answer.

Collection from simap needs no credentials.

Usage

# 1. Collect — every step is resumable, whatever is stored is skipped
venv/bin/tenderwatch collect all --from 2026-01-01 --to 2026-09-30
#    = search (projects, month by month) → history (past publications)
#      → details (raw detail) → vendors (profiles, UID) → offices (authorities)

#    Keeping up to date, e.g. from cron or a systemd timer:
venv/bin/tenderwatch collect daily      # rolling 60-day window + the other steps (~5 min)
venv/bin/tenderwatch collect refresh    # weekly: re-read details of the last 30 days
#    daily exits with 1 if more than 5 % of the window vanished from the search:
#    a broken search, not withdrawals, so nothing is flagged

# 2. Link winners to the commercial register
venv/bin/tenderwatch zefix

# 3. Rank
venv/bin/tenderwatch ranking                                 # current year, top 50 by number of awards
venv/bin/tenderwatch ranking --order amount --top 100 --csv ranking.csv
venv/bin/tenderwatch ranking --canton GE                     # authorities of Geneva (CH = federal)
venv/bin/tenderwatch ranking --by-canton                     # one row per canton

# 4. Risk indicators
venv/bin/tenderwatch single-bid                              # authorities with more single bids than similar contracts
venv/bin/tenderwatch single-bid --authority <proc_office_id> # their lots, one by one
venv/bin/tenderwatch direct-award                            # authorities with more direct awards than similar contracts

Pace: about 3 calls per second (--interval 0.35). A full year is roughly 16,000 projects and 40,000 calls, i.e. 4 to 5 hours. No rate-limit header was observed; the pace is a courtesy, not a measured constraint.

Data model

See tenderwatch/schema.sql. Raw API answers are stored as jsonb; everything else is derived by views, so changing an analysis never requires downloading again.

Table / view Content
projects one project per row, with the search answer; missing_since when the daily search stopped returning it
publications one publication per row (one lot = one publication), raw detail
publication_history replaced versions: an edited publication is never overwritten
vendors public profiles of winners, including the normalised UID
zefix_companies Zefix record per UID
proc_offices contracting authorities listed by simap, with their type (federal, cantonal, communal…)
v_awards one row per (award, winner), with jurisdiction: CH or the authority's canton
v_awards_current same, without earlier versions of a corrected award

Limits — read before publishing a figure

Summarised here, detailed in docs/methodology.md:

  • members of a bidding consortium are only named in free text: only the lead vendor is counted;
  • the price is the published price — VAT included or not, sometimes a framework-agreement ceiling: totals are orders of magnitude; an amount repeated across the winners or lots of a project is reported apart, once;
  • corporate groups are not consolidated;
  • losing bidders and their prices are never published, so bid-rigging detection is out of reach;
  • below the publication thresholds, nothing appears at all.

Roadmap

  • Collect the new simap platform (from 2026), link winners to Zefix, rank them
  • Go back to 1 July 2024, the start of the new platform
  • Daily incremental collection
  • Export to the Open Contracting Data Standard (OCDS). Mapping simap publications to OCDS releases would make Swiss data comparable with other countries' and let existing tools run on it unchanged — first of all Cardinal, which computes red flags from the OCP guide
  • Risk indicators, each mapped to the red flag of the OCP guide it implements, calibrated on documented cases before publication — single bid and direct award, preliminary (testing protocol)
  • Members of bidding consortia, extracted from the free-text notes
  • The 2007–2024 archive (archiv.simap.ch), matched to the register by name and address for lack of a UID
  • Cross-check with the federal list of contracts of CHF 50,000 and more

Related work

  • Red Flags in Public Procurement (Open Contracting Partnership, 2024): the reference guide for data-driven risk indicators — 73 red flags across the procurement cycle, with definitions and formulas mapped to the Open Contracting Data Standard (OCDS). TenderWatch's indicators will start from this list.
  • Cardinal (Open Contracting Partnership): open-source library that computes some of these red flags on OCDS data.
  • Government Transparency Institute and opentender.eu: academic work led by Mihály Fazekas on procurement corruption-risk indicators, and their application to European procurement data.
  • IntelliProcure (Bern University of Applied Sciences): simap since 2009 including tender documents, full-text search; free accounts for journalists.
  • Digilac/simap-mcp: an MCP server to query simap from an AI assistant.

License

GNU Affero General Public License v3.0 or later. If you run a modified version as a network service, you must offer its source to its users.

About

Who wins Swiss public contracts? Local copy of simap.ch linked to the commercial register (Zefix).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages