Enterprise Data

Data Provenance & Security Whitepaper

Version 1.0 · 16 October 2026 · Assay Systems, Ottawa, Ontario, Canada

This paper is written for the engineers, security and legal reviewers of a company that takes the Assay Systems register under an Enterprise Data contract. It sets out where every record comes from, under which licence, how it is cleaned and de-duplicated, how it is protected and delivered, and the exact shape of the data.

  1. Sources and licences
  2. The data pipeline
  3. De-duplication and entity resolution
  4. Personal data
  5. Security
  6. Enterprise delivery and service levels
  7. Response structure and JSON schemas

1. Sources and licences

Every record in the register is taken from a public procurement record that a government, or the public body it designates, publishes openly for reuse. Nothing is taken from behind a login, a paywall or a terms-of-use wall. Every row carries the URL of its source dataset, the licence it is published under and the publisher's own record reference, so any figure can be traced back to the government record it came from.

Publishers and licences
Country or regionPublisherLicence
Canada – contractsGovernment of Canada, proactive disclosure of contracts (open.canada.ca)Open Government Licence – Canada 2.0
Canada – grants and contributionsGovernment of Canada (open.canada.ca)Open Government Licence – Canada 2.0
United StatesUSAspending.govU.S. Government work, public domain (17 U.S.C. 105)
European Union and EEA countriesTenders Electronic Daily (TED), Publications Office of the EUReuse under Commission Decision 2011/833/EU
Countries publishing in the Open Contracting Data StandardNational procurement authorities (OCDS publications)The publisher's licence, named in each row: CC BY 4.0, CC BY-SA 4.0, ODbL 1.0, ODC PDDL 1.0 or a national open-data licence
Australia, United Kingdom, New Zealand, NorwayAusTender, Contracts Finder, GETS, DoffinThe publisher's open government licence, named in each row

Sources published under a non-commercial licence (for example CC BY-NC-SA 4.0) stay open on the public site as summaries and are excluded from every paid service, Enterprise Data included. Share-alike sources are delivered under the same licence, as that licence requires.

2. The data pipeline

The register is built by an automated pipeline with six stages. Each build writes a manifest that records what went in, what was removed and what failed a check.

3. De-duplication and entity resolution

Raw government contract data cannot be summed as published. The register corrects two structural problems before any figure is counted.

Amendments: one contract, one value

The Government of Canada publishes each amendment to a contract as a separate row, and the value on that row is the full value of the contract after the amendment, not the increment. Adding the rows counts the same contract several times.

Example from the published record: one contract signed on 5 October 2011 appears in four rows. Their sum is $1,088,662,391; the real value of the contract is $348,625,938, the last published figure. Across the federal register, summing raw rows overstates the value of contracts by 43 percent.

The register keys a contract by supplier, date signed, original value and buying department, and keeps the last published record in each key, which carries the final value. Grants and contributions are keyed by the agreement number, so a grant amended or republished under a new reference is still counted once.

Supplier names: one company, one record

The same supplier is written many ways in government records: case, punctuation, legal suffixes, truncation, misspellings. The register merges spellings only inside one financial key: the original value to the cent, the start date and the buying department must all match. Name similarity is used as a limit on a merge, never as proof of one.

Merges are graded exact or probable. In the Canadian register 6,420 families of spellings were merged this way, 5,934 exact and 486 probable. For example, five spellings of one detection-equipment supplier under one Canada Border Services Agency contract resolve to a single supplier record.

4. Personal data

5. Security

6. Enterprise delivery and service levels

7. Response structure and JSON schemas

Every API answer is JSON in UTF-8. A machine-readable list of the endpoints is at GET https://assay-systems.com/api/v1.

Envelope of every record answer
{
  "api": "assay-systems/v1",
  "key_tier": "none | open | commercial",
  "retrieved": "YYYY-MM-DDThh:mm:ssZ",
  "source": "Assay Systems register, https://assay-systems.com/register/",
  "data": { ...record... }
}

A record (/api/v1/supplier/{country}/{id}, /line/, /contract/, /grants/) holds id, type, country, name, url, register, line, summary, figures, sections and cite_as.

Contract row (paid layer and bulk files)
FieldTypeMeaning
idstringStable row identifier in the register
countrystringISO 3166-1 alpha-2 code, lower case
buyerstringBuying department or agency
buyer_idstring or nullRegister identifier of the buyer
officestring or nullBuying office
office_emailstring or nullProcurement mailbox, as published by the department
office_phonestring or nullOffice telephone, as published
supplierstringSupplier, after entity resolution
supplier_idstring or nullRegister identifier of the supplier
linestring or nullLine of business in the register
codestring or nullCommodity or service code of the source
descriptionstring or nullDescription, as published
valuenumberFinal contract value, after amendments
currencystringISO 4217 code, as published
signeddate or nullDate signed, YYYY-MM-DD
endsdate or nullEnd date, YYYY-MM-DD
procedurestring or nullProcurement procedure (open, limited, sole source)
biddersinteger or nullNumber of bids received
record_refstring or nullThe publisher's own record reference
source_urlstringSource dataset
licencestringLicence of the source
updateddateDate the row was last updated in the register

Paged answers wrap rows as {"source", "key_tier", "licence", "register", "built", "data": {...rows, page...}}. Bulk files carry the same rows, one JSON object per line, gzip-compressed, with a manifest.json per country.

Endpoints
  • GET /api/v1/countries · GET /api/v1/search?q=&country=&limit=
  • GET /api/v1/supplier/{country}/{id} · /line/{country}/{id} · /contract/{country}/{id} · /grants/{country}/{id}
  • GET /api/v1/uncontested · /uncontested/{country}[/{page}] · /page/{path under /register/}
  • Paid: GET /api/v1/line/{country}/{id}/contracts?page=&ends_before=&buyer= · /supplier/{country}/{id}/contracts?page= · /ending?country=&line=&before= · /solo · /solo/{country}?kind=pairs|locks|buyers