# PeptideAtlas Grey-Market Peptide COA Corpus — Codebook

**Version:** v1 (frozen 2026-08-26)
**File:** `coa-corpus-v1.csv`
**Rows:** 1,476 published analytical reports
**Vendors:** 223 distinct vendor names (218 distinct normalised slugs)
**Coverage:** 2020-02-03 to 2026-05-06, plus 22 undated reports
**Licence:** CC BY 4.0 — reuse freely with attribution.
**Suggested citation:** PeptideAtlas, *Grey-Market Peptide COA Corpus v1*, August 2026.
https://peptideatlas.co/research/grey-market-peptide-coa-dataset

---

## What this dataset is

Every row is one analytical report attributed to Janoshik Analytical that a
vendor, reseller or customer **made publicly visible** — on a product page, in a
storefront's COA library, or through Janoshik's public verification portal.

It is a census of *published* certificates. It is **not** a random sample of what
is sold, and it is not a sample of what was tested. Both distinctions are
load-bearing and are discussed under *Selection* below.

## Columns

| Column | Type | Description |
|---|---|---|
| `test_id` | string | Janoshik task number. Primary key; unique within the file. Combined with `verify_key` it resolves against Janoshik's public verification portal. |
| `substance_label` | string | The substance string **as the vendor labelled it**, lightly normalised for casing and whitespace only. Not a controlled vocabulary — see *Substance labels*. |
| `vendor_name` | string | Display name of the vendor, reseller or customer the report is attributed to. The 223-vendor headline count is over this column. |
| `vendor_slug` | string | Normalised identifier used to join against PeptideAtlas vendor records. Collapses casing and punctuation, so it yields 218 groups where `vendor_name` yields 223. |
| `test_date` | date (`YYYY-MM-DD`) | Date on the report. Empty for 22 rows where no date was legible. |
| `purity_percent` | float or empty | Reported numeric purity. **Empty means no readable purity figure was present — it does not mean zero.** 690 of 1,476 rows are empty here. |
| `has_coa_image` | 0/1 | Whether a certificate image was captured with the record. 1,470 of 1,476 rows have one. |
| `verify_key` | string | Janoshik verification key, where published. Use with `test_id` to check a report against the issuing laboratory. |

## The two facts most likely to be misread

**1. `purity_percent` empty ≠ failure, and ≠ zero.**
690 rows (46.7%) carry no readable numeric purity value. These are largely real
analytical artefacts — identity confirmations, mass-spectrometry reports without
quantitation, cropped or low-resolution images, and reports whose visible content
never included a purity figure. Coercing empty to `0` would invent 690 failures
and destroy the single most important finding in the dataset. Filter, do not fill.

**2. The 99.4% pass rate is a measurement of publication behaviour.**
Among the 786 rows with a readable value, 99.4% are at or above 95%. That is a
fact about which certificates became public, not about the purity of grey-market
vials in general. A vendor can test ten batches, publish the best one, and
truthfully call itself third-party tested. Failed assays that were never posted,
batches retested until one passed, and batches never tested at all are all
invisible to this file by construction.

## Selection

Three filters sit between the market and this file, and they compound:

1. **Tested at all.** Only a subset of batches are ever sent for analysis.
2. **Published.** Only a subset of results are made publicly visible. This is the
   dominant filter and its direction is known: publication is a marketing act.
3. **Discoverable and captured.** Only published reports PeptideAtlas could find
   and parse are here.

For any question about *product quality*, treat these numbers as an upper bound
of unknown tightness. For questions about *the market's evidence ecosystem* —
what vendors publish, how often, with what completeness — the selection is the
subject rather than a confounder.

## Substance labels

`substance_label` is the vendor's own string. 1,476 reports carry 939 distinct
labels because "Tirzepatide", "Tirzepatide 30mg" and "Tirz 60mg" are three labels
for one compound. Any per-compound analysis needs a normalisation pass of your
own; we deliberately did not impose one, so that the raw labelling variance
stays inspectable.

## Vendor attribution

Attribution is imperfect and should be treated as such. Some reports name a
manufacturer, a reseller or the customer who commissioned the test rather than
the retail brand a consumer would recognise. Reports PeptideAtlas could not
attribute to a named vendor are **excluded** from this file.

## Single laboratory

Every record is attributed to one laboratory. That is what makes the set
internally comparable across vendors — one set of methods, conventions and
analytical uncertainties — and it is also the main external-validity limit. Do
not read it as a market-wide measurement across laboratories.

## Reproducing the published figures

```
node node_modules/tsx/dist/cli.mjs scripts/research/coa-corpus-stats.ts
```

Reads this CSV and writes `src/data/investigations/coa-corpus-stats.json`, which
is the file every number in *The COA Mirage* renders from. No figure in the
article is hand-typed.

SHA-256 of `coa-corpus-v1.csv`:
`c7957abfd9eb73ea95011eaae43750e9075bb723ea209af1e1437329b6875c03`

## Versioning policy

**v1 is frozen and will not change.** The live corpus behind peptideatlas.co is
rebuilt continuously and it does not only grow — it has lost rows to pipeline
failures before. A citable dataset whose row count drops after someone quotes it
is worse than no dataset, so additions become v2, published alongside v1 rather
than replacing it. Every version keeps its own URL, hash and update log.

## Update log

| Date | Version | Change |
|---|---|---|
| 2026-08-26 | v1 | Initial public release. 1,476 reports, 223 vendors, frozen. |

## Contact

Corrections, questions and data requests: **contact@brainymedia.co**

If you find an error in this file we want to know, and we will log the correction
in the table above rather than silently amending it.
