# Passage Data > Cited environmental limits for programs and agents. Numeric discharge limits, water, groundwater and air quality guidelines, drinking-water standards and soil and groundwater screening values, read from the regulations themselves: US federal effluent guidelines (40 CFR 133, 405-471), the rules of 31 US states and DC (water quality standards above all), Canadian federal rules and every province's and territory's, German, French, Italian and EU instruments; drinking water from 40 CFR 141 and 143, the EU Directive 2020/2184, Quebec's regulation and the PFAS rules of Germany, France, Italy and Canada; soil and groundwater from EPA's Regional Screening Levels, California's ESLs, Ontario, Quebec, British Columbia, CCME and Italy. Every row cites its instrument, edition, section or page, the quoted text, and the source file's URL and sha256. When nothing is held, the answer is a coded refusal naming every instrument searched, never an empty list. The data is read from public law and public agency files. A refusal is a statement about our sources, not about the law of a place or the protection of a species. Check the cited source before relying on a value. Free while in preview; calls may be rate-limited. We keep what is asked (tool, place, parameter or species name, outcome), the name and version the calling program gives, the network it calls from (operator and country, as Cloudflare reports them) and how many distinct callers a day; never an IP address, an account or a person. ## MCP server - [MCP endpoint](https://passage-data.com/mcp): Streamable HTTP, no key. Tools: `find_limits`, `check_value`, `list_sources`, `get_permit`, `map_to_darwin_core`, `find_designations`. Add it with `claude mcp add --transport http passage-data https://passage-data.com/mcp`, or as a remote connector URL in any MCP client. ## HTTP API (GET, JSON, no key) - [Service card](https://passage-data.com/api/v1/): what is held (instruments, rows, parameters, places) and every endpoint - [find_limits](https://passage-data.com/api/v1/limits?parameter=ammonia&place=US-OH&medium=surface_water): `parameter` (a name or CAS number) and optionally `place` (ISO 3166: US, US-OH, CA-QC, DE, EU; a place also searches the places above it), `medium` (water_discharge, surface_water, groundwater, drinking_water, soil, ambient_air, air_emission, sediment, leachate), `statistic` (daily_max, monthly_avg, four_day_avg, ...), `kind` (limit, guideline, ...), `max_rows` (1-200, default 50), `offset` - [check_value](https://passage-data.com/api/v1/check?parameter=copper&value=0.15&unit=mg/L&place=CA-QC&medium=water_discharge): `parameter`, `value` (one number), `unit` (mg/L, µg/L, ng/L, mg/kg, µg/m³, pH ...) and the same `place`, `medium`, `statistic`, `max_rows`, `offset`: every row find_limits would return, each with a verdict — over, under, within, or not_comparable with the reason. Units convert exactly within a family; no limit is summed or inferred - [list_sources](https://passage-data.com/api/v1/sources?place=CA-QC): every instrument held for a place, with edition, rows read and source URL - [get_permit](https://passage-data.com/api/v1/permits/PA0228061): one US NPDES permit from EPA's national file: limits by outfall, renewal due date, the last 12 months' values over a limit - map_to_darwin_core: `POST https://passage-data.com/api/v1/dwc/map` with JSON `{"columns": ["nom_latin", "date", "x", "y"], "sample_rows": [[...], ...]}` (columns: the header row, up to 500; sample_rows optional, up to 400): for each column of a species occurrence or checklist file, the Darwin Core term, the rule that decided it and the alias that matched, or a coded refusal saying why it is unmapped; and the terms GBIF requires of an occurrence or checklist dataset that no column carries - [find_designations](https://passage-data.com/api/v1/designations?species=Myotis%20lucifugus&place=CA-ON): `species` (a scientific name, or a common name exactly as a register prints it) and optionally `place` (ISO 3166: US, US-CA, CA-ON, GB-SCT, FR; only the registers that reach it are searched, with IUCN, CITES and, where the country is a Party, CMS). Registers: US Endangered Species Act lists (50 CFR 17.11, 17.12), Canada's Species at Risk Act Schedule 1 and COSEWIC, the provinces' and territories' acts, the IUCN Red List, CITES, CMS, the EU Habitats (Annexes II, IV, V) and Birds (Annex I) Directives, UK Wildlife and Countryside Act and Habitats Regulations schedules - [OpenAPI 3.1 description](https://passage-data.com/openapi.json) ## Answer shape - Each row of `find_limits`: `parameter` (as the instrument prints it), `parameter_key` (cas:… or name:…), `value` (as printed), `value_num`, `range`, `unit`, `statistic`, `direction` (max, min, range), `kind`, `medium`, `place`, `conditions` (as printed), and `cite`: `instrument`, `title`, `issuer`, `edition`, `section`, `page`, `quote`, `source_url`, `source_sha256`; a row read from a register table also gives its `table`, `column` (e.g. `mcl`, `mclg`) and the `note` the register prints beside it. A limit on a SUM (Summe PFAS-4, Sum of PFAS, the 25 PFAS of Health Canada's objective) carries `sum_of`: the `members` its instrument lists, as printed; asking for one member (PFOA, its CAS number, a synonym) finds the sum and the row says it is one. - Each row of `check_value` is a `find_limits` row plus `verdict` (over, under, within, not_comparable), `compared` (your value in the row's unit, `exact`, the limit, its direction) and, when not comparable, `why`: `parameter.named_differently` (a longer name: ask by it), `parameter.member_of_sum` (the row limits a sum the asked substance is one member of: ask by the sum's name with the summed value), `printed_reference`, `condition.dependent` (the number holds only at a stated hardness, pH or temperature), `value.not_a_number` (an equation or narrative), `value.range_of_levels`, `direction.not_printed`, `unit.family_mismatch`, `unit.not_convertible`, `unit.unrecognised`, `unit.refused`, `unit.not_printed`. `counts` and `not_comparable_by` cover every row; rows come over first. A verdict compares numbers: whether your value is the row's statistic and its conditions are yours is for you to say. - `searched` says which places and parameter names were matched. `total`, `returned` and `next_offset` page the rows; nothing is cut silently. - Each column of `map_to_darwin_core`: `header`, `status` (mapped, refused, empty, unmapped), `term` and `terms` (Darwin Core names), `rule` (header_exact, header_token, header_packed, header_grid), `evidence` (`alias`, `alias_rank`, `alias_origin`: standard, ours, learned or wikidata; `table`; `also_nominated`), `values_check` (the check the column's values must still pass: not run here), or `refused` (`silence.no_dwc_term_matched`, `silence.unrecognised`, `silence.identifier`, `term.ambiguous_header`, `term.held_by_other_column`, `value.column_empty`, `value.uncorroborated_count`, `value.insufficient`). `required.occurrence` and `required.checklist` list the GBIF-required terms `held` and `missing` (`filled_if_absent` when the converter writes it itself); `questions` names the ties to settle. - `refused.code`: `parameter.missing`, `parameter.unknown`, `parameter.ambiguous`, `place.not_held`, `rows.none_held` (with `sources_searched` and `held_elsewhere`), `permit.malformed`, `permit.not_held`; for check_value also `value.missing`, `value.malformed`, `value.ambiguous` (1,500: a comma that reads two ways), `value.negative` (an amount below zero), `value.out_of_range`, `unit.missing`, `unit.refused` (an ambiguous unit such as ppt or gal), `unit.unrecognised`. - Each row of `find_designations`: `register`, `name` (as the register prints it), `status` (as printed), `outcome` (`listed`; `listed_qualified` = listed only under a population or subspecies, with `asks` saying which to confirm; `watch_listed`; `assessed_not_listed`, e.g. IUCN Least Concern), `outcome_says`, `matched_at` (the name as typed, a synonym, a broader taxon, the backbone's lineage), `place`, `legal_instrument`, and `cite` (`instrument`, `title`, `edition`, `quote` = the line the register prints, `source_url`, `source_sha256`). `silent` lists each register searched that does not name the species and what its silence means (`assessed_not_listed`, `out_of_scope`, `scope_undetermined`, `not_assessed`). Refusals: `species.missing`, `species.unreadable`, `species.ambiguous` (with `candidates`), `place.malformed`, `designations.none_held` (with `registers_searched` and their editions). ## For people - [Cited limits by place](https://passage-data.com/limits/): the same rows as pages, one per place and parameter, e.g. [copper in Québec](https://passage-data.com/limits/CA-QC/copper) or [ammonia in Ohio](https://passage-data.com/limits/US-OH/ammonia); each page links its JSON. [Sitemap](https://passage-data.com/sitemap-limits.xml) - [NPDES permits by state](https://passage-data.com/dmr/p/): every active individual US discharge permit, its limits and EPA's 12-month record - [Passage Data](https://passage-data.com/): drop a site's documents; get what each says, cited to the page