{
  "openapi": "3.1.0",
  "info": {
    "title": "Passage Data — cited environmental limits",
    "version": "1.13.0",
    "summary": "Numeric environmental limits and guidelines read from the regulations themselves, every row cited to its source; a species' status under each species register held, cited; a species file's columns mapped to Darwin Core, and the file built into a Darwin Core archive; and a US NPDES permit's monthly report checked against its limits, or computed from the plant's own rows; and a published Darwin Core archive's defects, audited.",
    "description": "Discharge limits and water, groundwater and air quality guidelines from US federal effluent guidelines, the rules of 31 US states and DC, Canadian federal and provincial rules, and German, French, Italian and EU instruments; and the status a species holds under the species registers we hold (US ESA, SARA, COSEWIC, provincial acts, IUCN, CITES, CMS, EU and UK schedules). Every row carries a `cite` block: instrument, edition, section or page, the quoted text, source URL and sha256. An answer with nothing to give is a `refused` block naming what was searched; it is a statement about our sources, not about the law of a place. Also served as an MCP server at https://passage-data.com/mcp, which also lists an account's own sites (list_sites, create_site, add_document, ask_site): a connector signs in by OAuth 2.1 (metadata at /.well-known/oauth-protected-resource/mcp), or a client sends the account's key as `Authorization: Bearer pdk_…`; those tools have no HTTP route here. Free while in preview; calls may be rate-limited."
  },
  "servers": [{"url": "https://passage-data.com/api/v1"}],
  "paths": {
    "/limits": {
      "get": {
        "operationId": "find_limits",
        "summary": "Find cited limits for one substance or measure",
        "parameters": [
          {"name": "parameter", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The substance or measure as a regulation names it (ammonia, copper, TSS, pH, BOD5) or its CAS number (7440-50-8)."},
          {"name": "place", "in": "query", "schema": {"type": "string"}, "description": "ISO 3166 code: US, US-OH, CA, CA-QC, DE, FR, IT, EU. A place also searches every place above it (US-OH searches US-OH and US)."},
          {"name": "medium", "in": "query", "schema": {"type": "string", "enum": ["water_discharge", "surface_water", "groundwater", "drinking_water", "soil", "ambient_air", "air_emission", "sediment", "leachate"]}},
          {"name": "statistic", "in": "query", "schema": {"type": "string"}, "description": "daily_max, monthly_avg, four_day_avg, annual_avg, hourly_avg, instant, ..."},
          {"name": "kind", "in": "query", "schema": {"type": "string", "enum": ["limit", "guideline", "benchmark", "threshold", "objective", "acceptance", "printed_reference"]}},
          {"name": "max_rows", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50}},
          {"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
        ],
        "responses": {
          "200": {"description": "Rows, or a `refused` block (rows.none_held, parameter.unknown, parameter.ambiguous, place.not_held)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Limits"}}}},
          "400": {"description": "parameter.missing", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/check": {
      "get": {
        "operationId": "check_value",
        "summary": "Check a measured value against every cited limit held for it",
        "description": "Every row find_limits would return, each with a verdict: over (above a ceiling or a band's top), under (below a floor or a band's bottom), within, or not_comparable with a `why` (parameter.named_differently, parameter.member_of_sum for a limit on a sum the asked substance is one member of, printed_reference, condition.dependent for a number that holds only at a stated hardness, pH or temperature, value.not_a_number, value.range_of_levels, direction.not_printed, unit.family_mismatch, unit.not_convertible, unit.unrecognised, unit.refused, unit.not_printed). Units convert exactly, in decimal, within a family (µg/L to mg/L) by the engine's registry; no limit is summed or inferred. Rows come over first, then under, within, not_comparable; `counts` and `not_comparable_by` cover every row, not only the page.",
        "parameters": [
          {"name": "parameter", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The substance or measure as a regulation names it (copper, ammonia, pH) or its CAS number (7440-50-8). A row held under a longer name holding these words is not compared: ask by that name."},
          {"name": "value", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The measured value, one decimal number: 0.15, 0,15, 1.5e-3. A result below detection (<0.005), a comma that reads two ways (1,500), an amount below zero and a number past 1e±30 are refused."},
          {"name": "unit", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The value's unit: mg/L, µg/L (or ug/L), ng/L, mg/kg, µg/m³, pH ..."},
          {"name": "place", "in": "query", "schema": {"type": "string"}, "description": "ISO 3166 code: US, US-OH, CA, CA-QC, DE, FR, IT, EU. A place also searches every place above it."},
          {"name": "medium", "in": "query", "schema": {"type": "string", "enum": ["water_discharge", "surface_water", "groundwater", "ambient_air", "air_emission", "sediment", "leachate"]}},
          {"name": "statistic", "in": "query", "schema": {"type": "string"}, "description": "daily_max, monthly_avg, instant, composite, ..."},
          {"name": "max_rows", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50}},
          {"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
        ],
        "responses": {
          "200": {"description": "Rows with verdicts, or a `refused` block (rows.none_held, parameter.unknown, parameter.ambiguous, place.not_held, unit.refused, unit.unrecognised)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Check"}}}},
          "400": {"description": "parameter.missing, value.missing, value.malformed, value.ambiguous, value.negative, value.out_of_range, unit.missing", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      },
      "post": {
        "operationId": "check_values",
        "summary": "Check a table of measured values against the cited limits held for one place, in one call",
        "description": "A lab table of up to 200 rows (parameter, value, unit), each answered by check_value itself: its verdicts (over, under, within, not_comparable with a `why`), `counts` and `says`, or its own coded refusal (an unknown parameter, a value below detection such as <0.005, an ambiguous unit). Each held limit is sent once, in `limits`, and each verdict names it by index (`limit`): joined, they are check_value's row with its `cite`; `compared` keeps the value in the row's unit and whether that conversion is exact. `searched.parameters` says how each parameter was matched. `summary` counts the rows over a limit, under a floor (and over none), within every limit compared, with limits none of which compares, and refused by code. `max_rows` pages each row's verdicts (over first); check_value with `offset` gives the rest. Use it instead of one call a row: the door allows 30 calls in 10 seconds.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["place", "rows"], "additionalProperties": false, "properties": {
          "place": {"type": "string", "description": "ISO 3166 code: US, US-OH, CA, CA-QC, DE, FR, IT, EU. One place for the whole table; it also searches every place above it."},
          "medium": {"type": "string", "enum": ["water_discharge", "surface_water", "groundwater", "drinking_water", "soil", "ambient_air", "air_emission", "sediment", "leachate"]},
          "statistic": {"type": "string", "description": "daily_max, monthly_avg, instant, composite, ..."},
          "max_rows": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50, "description": "Verdicts returned for each row; its counts cover all."},
          "rows": {"type": "array", "minItems": 1, "maxItems": 200, "description": "The table's rows, in order; the answer keeps the order.", "items": {"type": "object", "required": ["parameter", "value", "unit"], "additionalProperties": false, "properties": {
            "parameter": {"type": "string", "description": "The substance or measure as a regulation names it (copper, ammonia, pH) or its CAS number."},
            "value": {"type": ["number", "string"], "description": "The measured value as the table prints it (0.15, \"0,15\"). A result below detection (\"<0.005\") is refused for that row, never compared."},
            "unit": {"type": "string", "description": "mg/L, µg/L (or ug/L), ng/L, mg/kg, µg/m³, pH ..."}}}}}},
          "example": {"place": "CA-QC", "medium": "water_discharge", "rows": [{"parameter": "copper", "value": 0.15, "unit": "mg/L"}, {"parameter": "zinc", "value": "0,4", "unit": "mg/L"}, {"parameter": "lead", "value": 120, "unit": "µg/L"}]}}}},
        "responses": {
          "200": {"description": "One result a row, in the rows' order, beside the limits they name and a summary; or the call refused once (place.not_held)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CheckValues"}}}},
          "400": {"description": "place.missing, rows.missing, rows.malformed, rows.too_many (over 200), body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "413": {"description": "body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/verify": {
      "get": {
        "operationId": "verify_claim",
        "summary": "Verify a claimed limit against the cited rows held",
        "description": "A limit someone stated (in an AI's answer, a report) set beside every row find_limits keeps for it. confirmed: a row prints the same number, in the claim's unit or one that converts exactly (in decimal, by the engine's registry), under the claim's statistic when one is given; quote its cite. contradicted: rows are held and none prints it; held_otherwise gives the number each prints, with its own conditions. not_held: a `refused` block (place.not_held, parameter.unknown, rows.none_held, statistic.none_held) naming every instrument searched and its edition, a statement about our sources and never about whether the claim is true. not_comparable: rows held, none comparable with one number, each with its `why`. Equal is equal as exact decimals: a rounded number is another number. A row worked for water of a stated chemistry confirms the same number and never contradicts another.",
        "parameters": [
          {"name": "parameter", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The substance or measure the claim names (copper, ammonia, pH) or its CAS number."},
          {"name": "value", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The number the claim states, one decimal number: 0.10, 0,10, 1e-4."},
          {"name": "unit", "in": "query", "required": true, "schema": {"type": "string"}, "description": "The claim's unit: mg/L, µg/L (or ug/L), ng/L, mg/kg, µg/m³, pH ..."},
          {"name": "place", "in": "query", "schema": {"type": "string"}, "description": "ISO 3166 code: US, US-OH, CA, CA-QC, DE, FR, IT, EU. A place also searches every place above it."},
          {"name": "medium", "in": "query", "schema": {"type": "string", "enum": ["water_discharge", "surface_water", "groundwater", "drinking_water", "soil", "ambient_air", "air_emission", "sediment", "leachate"]}},
          {"name": "statistic", "in": "query", "schema": {"type": "string"}, "description": "A row code: monthly_avg, daily_max, daily_avg, weekly_avg, annual_avg, hourly_avg, four_day_avg, instant, composite, qualified_grab, ... An unknown code is refused with the list."},
          {"name": "sentence", "in": "query", "schema": {"type": "string", "maxLength": 2000}, "description": "Optional: the sentence the claim came from (better sent by POST). Read for the claim's number and unit, never kept."}
        ],
        "responses": {
          "200": {"description": "A verdict, or a `refused` block (not_held: place.not_held, parameter.unknown, rows.none_held, statistic.none_held; parameter.ambiguous, statistic.unrecognised, unit.refused, unit.unrecognised)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Claim"}}}},
          "400": {"description": "parameter.missing, value.missing, value.malformed, value.ambiguous, value.negative, value.out_of_range, unit.missing", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      },
      "post": {
        "operationId": "verify_claim_post",
        "summary": "Verify a claimed limit, with the sentence it came from",
        "description": "The GET's arguments as a JSON object, with the optional `sentence`: the answer says whether the sentence prints the claim's number with its unit beside it, and names the parameter. The sentence is never kept.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["parameter", "value", "unit"], "additionalProperties": false, "properties": {
          "parameter": {"type": "string"}, "value": {"type": ["number", "string"]}, "unit": {"type": "string"}, "place": {"type": "string"},
          "medium": {"type": "string", "enum": ["water_discharge", "surface_water", "groundwater", "drinking_water", "soil", "ambient_air", "air_emission", "sediment", "leachate"]},
          "statistic": {"type": "string"}, "sentence": {"type": "string", "maxLength": 2000}}}}}},
        "responses": {
          "200": {"description": "As the GET", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Claim"}}}},
          "400": {"description": "body.malformed and the GET's 400s", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/sources": {
      "get": {
        "operationId": "list_sources",
        "summary": "List the instruments held for a place",
        "parameters": [
          {"name": "place", "in": "query", "schema": {"type": "string"}},
          {"name": "medium", "in": "query", "schema": {"type": "string"}}
        ],
        "responses": {"200": {"description": "Instruments with edition, rows read and source", "content": {"application/json": {"schema": {"type": "object"}}}}}
      }
    },
    "/certificate": {"post": {"operationId": "read_certificate", "summary": "Read a laboratory certificate into its rows, each with its page, and check each row against a place's limits", "description": "A PDF certificate, or the laboratory's own export as XLSX, XLS or CSV / TSV, read by rules (no AI writes a row): each row the certificate prints with the sample, the parameter, the value as printed, its unit, a qualifier (<, >, ND), the detection limit and the page (or sheet) it was read from; a sample's date, matrix, lab ID and certificate in `samples`. With a `place` (best with a `medium`), every row with a value is checked by check_values itself; `exceedances` lists every row over a limit or under a floor, each limit once in `limits` with its `cite`. A result below detection is not compared (`value.below_detection`). `checked_as` is the printed name without the lab's decoration (`Cuivre (Cu) a 2` -> `Cuivre`) when check_value holds that name. Rows page by `max_rows` / `offset` (the file is read again). Anything but a PDF, XLSX, XLS or CSV is refused `format.not_handled` before it is read. The file is read and discarded: it is not kept, and nothing is learned from it.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {"content_base64": {"type": "string", "description": "The file's bytes, base64-encoded (at most 10 MB). Give this or file_url."}, "file_url": {"type": "string", "description": "An https address the file can be fetched from (not loopback or a private network). Give this or content_base64."}, "filename": {"type": "string"}, "place": {"type": "string", "description": "ISO 3166 code: US, US-OH, CA, CA-QC, DE, FR, IT, EU. Omit to read the rows without checking them."}, "medium": {"type": "string", "enum": ["water_discharge", "surface_water", "groundwater", "drinking_water", "soil", "ambient_air", "air_emission", "sediment", "leachate"]}, "statistic": {"type": "string"}, "max_rows": {"type": "integer", "minimum": 1, "maximum": 500, "default": 100, "description": "Certificate rows on this page; the summary and exceedances cover every row."}, "offset": {"type": "integer", "minimum": 0, "default": 0}, "call_id": {"type": "string", "description": "Only after read.pending: collect the reading without sending the file again."}}}, "example": {"file_url": "https://example.org/certificate.pdf", "place": "CA-QC", "medium": "surface_water"}}, "multipart/form-data": {"schema": {"type": "object", "required": ["file"], "properties": {"file": {"type": "string", "format": "binary"}, "place": {"type": "string"}, "medium": {"type": "string"}, "statistic": {"type": "string"}, "max_rows": {"type": "integer"}, "offset": {"type": "integer"}}}}}}, "responses": {"200": {"description": "The rows read, the summary and, with a place, the exceedances and the limits they name; or a refusal about the file (certificate.no_rows, certificate.not_results, page.missing)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Certificate"}}}}, "202": {"description": "read.pending: a long file is still being read; call again with its call_id", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}, "400": {"description": "file.missing, file.ambiguous, file.malformed, file.url_refused, call_id.unknown, body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}, "413": {"description": "file.too_large (over 10 MB), body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}, "415": {"description": "format.not_handled: not a PDF, XLSX, XLS or CSV; nothing read", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}, "422": {"description": "file.unreachable: the file_url could not be fetched", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}, "429": {"description": "engine.busy: the reading service's hourly limit", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}, "503": {"description": "engine.unreachable, engine.timeout: nothing was read; try again", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}}}},
    "/dwc/map": {
      "post": {
        "operationId": "map_to_darwin_core",
        "summary": "Map a species file's columns to Darwin Core terms",
        "description": "For each column of an occurrence or checklist file: the Darwin Core term, the rule that decided it (header_exact, header_token, header_packed, header_grid) and the alias that matched, or a coded `refused` block saying why it is unmapped. Also names the terms GBIF requires of an occurrence or checklist dataset that no column carries. The header rules of our file-to-archive converter; values are not checked here, and each mapped column names the check its values must still pass.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["columns"], "additionalProperties": false, "properties": {
          "columns": {"type": "array", "items": {"type": "string"}, "minItems": 1, "maxItems": 500, "description": "The file's header names, in order, exactly as written."},
          "sample_rows": {"type": "array", "maxItems": 400, "items": {"type": ["array", "object"]}, "description": "Optional data rows, each an array aligned with columns or an object keyed by header. A column blank in every row is skipped as the converter skips it; a column of distinct codes is named an identifier."}}},
          "example": {"columns": ["nom_latin", "nom_vernac", "effectif", "date", "x", "y", "code_postal"]}}}},
        "responses": {
          "200": {"description": "One entry per column, the GBIF-required terms held and missing, and any ties to settle", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DwcMap"}}}},
          "400": {"description": "columns.missing, columns.malformed, columns.too_many, sample_rows.malformed, sample_rows.too_large, body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "413": {"description": "body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/dwc/archive": {
      "post": {
        "operationId": "build_dwc_archive",
        "summary": "Build a Darwin Core archive from a species file or a list of names",
        "description": "A species occurrence or checklist file (CSV, TSV, Excel, a zipped shapefile, ...) given as `file_url` (a public https address the door fetches) or `content_base64`, or a list of scientific names (`species`, a checklist), becomes a Darwin Core archive for GBIF: occurrence.txt or taxon.txt, meta.xml and eml.xml, built by the converter behind map_to_darwin_core, which maps every column and checks every value. The zip comes back whole in `archive.base64`, with each thing the converter would not guess coded in `could_not_read` (the same lines ship inside the archive as passage-data-exceptions.csv and .json). GBIF indexes an archive only with a title, an abstract, a licence and a creator and a contact (given name, surname, organisation, email): give them in `metadata`; nothing is filled in. `chapman_category` (1-4, the data holder's own Chapman 2020 category) coarsens the coordinates of species a conservation register lists. Nothing of the file is kept: the converter is sent no_learn. A large file takes up to a minute.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "properties": {
          "file_url": {"type": "string", "description": "A public https address of the file (at most 10 MB). Not with content_base64 or species."},
          "content_base64": {"type": "string", "description": "The file's bytes as base64 (at most 10 MB decoded). Not with file_url or species."},
          "filename": {"type": "string", "maxLength": 200, "description": "The file's name with its extension (survey.xlsx, sites.zip); taken from file_url when omitted."},
          "species": {"type": "array", "minItems": 1, "maxItems": 5000, "items": {"type": "string"}, "description": "Instead of a file: scientific names, one an entry, for a checklist archive."},
          "core": {"type": "string", "enum": ["occurrence", "checklist"], "description": "occurrence (the default for a file) or checklist (the default for species)."},
          "metadata": {"type": "object", "additionalProperties": false, "properties": {
            "title": {"type": "string"}, "abstract": {"type": "string"}, "license": {"type": "string", "enum": ["CC0-1.0", "CC-BY-4.0", "CC-BY-NC-4.0"]},
            "creator": {"$ref": "#/components/schemas/Party"}, "contact": {"$ref": "#/components/schemas/Party"}}},
          "chapman_category": {"type": "integer", "minimum": 1, "maximum": 4, "description": "Your sensitivity category under Chapman 2020: listed species' coordinates generalised to its grid, said in dataGeneralizations."}}},
          "example": {"file_url": "https://static.data.gouv.fr/resources/inventaire-faune-flaure/20160718-175427/Inventaire_Faune_Flore.csv", "metadata": {"title": "Inventaire de la faune et de la flore le long du fuseau du Grand Paris Express", "abstract": "...", "license": "CC-BY-4.0", "creator": {"given": "...", "sur": "...", "organization": "...", "email": "..."}, "contact": {"given": "...", "sur": "...", "organization": "...", "email": "..."}}}}}},
        "responses": {
          "200": {"description": "The archive (base64) and its receipt, what could not be read, notices", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DwcArchive"}}}},
          "400": {"description": "source.missing, source.ambiguous, file.ambiguous, file.malformed, file.url_refused, filename.malformed, species.malformed, species.too_many, species.not_occurrences, core.malformed, chapman_category.malformed, metadata.malformed, license.unrecognised, body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "402": {"description": "archive.priced: past the free conversion allowance (about 50,000 records)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "413": {"description": "file.too_large, body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "422": {"description": "archive.not_built: the converter's own reason (no species name reached the archive, ...); file.unreachable: the file_url did not answer with the file", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "429": {"description": "engine.busy: the converter's per-caller budget", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "503": {"description": "engine.unreachable, engine.timeout: the converter did not answer", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/permits/{permit}": {
      "get": {
        "operationId": "get_permit",
        "summary": "One US NPDES permit from EPA's national file",
        "parameters": [{"name": "permit", "in": "path", "required": true, "schema": {"type": "string", "pattern": "^[A-Za-z]{2}[A-Za-z0-9]{7}$"}, "description": "e.g. PA0228061"}],
        "responses": {
          "200": {"description": "Limits by outfall, renewal due date, the last 12 months' values over a limit", "content": {"application/json": {"schema": {"type": "object"}}}},
          "400": {"description": "permit.malformed"},
          "404": {"description": "permit.not_held"}
        }
      }
    },
    "/dmr/check": {
      "post": {
        "operationId": "check_dmr",
        "summary": "Check a period's DMR values against the permit's own limits",
        "description": "A US NPDES permit's Discharge Monitoring Report for one period, checked before it is filed: each value you send (outfall, parameter, statistic, value, unit) is set beside the permit's own limit for that period, from EPA's national limits file (ICIS-NPDES), with EPA's violation rule's verdict: flagged (EPA records a violation), ok, undecidable (a less-than result against a lower limit: EPA does not flag it, nor does it show compliance), no_data (a NODI code), not_graded (an alert or stayed limit), unreadable. A row we cannot place on one value due is refused by its code (outfall.not_in_permit, parameter.not_limited, statistic.not_limited, unit.not_on_form, period.not_due, row.ambiguous with the candidates), never put on the nearest limit. Every value due this period is in `limits` once with its limit_value_id (the cite into EPA's file); `not_sent` lists those you did not send, which EPA records as missing (D90) when filed blank. `headline` and `tally` are the forms as filed with exactly the values placed. `netdmr: true` adds the NetDMR \"Import DMRs\" file as text (not yet validated by NetDMR's own import check). The values reach our server to be checked and are not kept: only how many were sent, flagged and refused is counted.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["permit", "period_end", "values"], "additionalProperties": false, "properties": {"permit": {"type": "string", "description": "The NPDES permit number, e.g. PA0228061."}, "period_end": {"type": "string", "description": "The reporting period: its month (2026-09) or its last day (2026-09-30). A quarterly form is due on the period ending its quarter."}, "values": {"type": "array", "minItems": 1, "maxItems": 500, "description": "The period's values, one a row, as the DMR prints them.", "items": {"type": "object", "additionalProperties": false, "properties": {"outfall": {"type": "string", "description": "The outfall (permitted feature): 001, 1, 002A ..."}, "parameter": {"type": "string", "description": "EPA's parameter code (get_permit's parameter_code: 00530, WEP6L) or its name (Solids, total suspended; TSS; ammonia)."}, "statistic": {"type": "string", "description": "EPA's statistical base code (MK, DD, WA, IA ...) or get_permit's words (monthly average, daily maximum, weekly average)."}, "value": {"type": ["number", "string"], "description": "The number as filed: 12, 0.5, or a censored result as a string: \"<0.10\"."}, "qualifier": {"type": "string", "enum": ["<", "<=", ">", ">=", "="], "description": "Optional: the value's qualifier, when the value is a bare number."}, "unit": {"type": "string", "description": "The value's unit, which must be the form's: mg/L, ug/L, lb/d, MGD, SU, #/100mL ... It separates a concentration from a loading."}, "location": {"type": "string", "description": "Optional: the monitoring location, EPA's code (1 effluent gross, G raw sewage influent, K percent removal) or its name."}, "form": {"type": "string", "description": "Optional: the DMR form (limit set) when two forms carry the parameter: its designator (A, Q) or name (001 Monthly)."}, "season": {"type": "string", "description": "Optional: the limit's season number when seasonal limits overlap (1, 2)."}, "nodi": {"type": "string", "description": "A no-data code in place of a value: C no discharge, B below detection, 9 conditional monitoring ..."}, "limit_value_id": {"type": "string", "description": "Optional: the limit's id from an earlier check_dmr or fill_dmr answer, in place of outfall, parameter, statistic and unit."}}}}, "netdmr": {"type": "boolean", "default": false, "description": "Also return the NetDMR \"Import DMRs\" file (CSV text) for the values placed."}}}, "example": {"permit": "PA0228061", "period_end": "2026-09", "values": [{"outfall": "001", "parameter": "00530", "statistic": "MK", "value": 12, "unit": "mg/L"}, {"outfall": "001", "parameter": "pH", "statistic": "instantaneous maximum", "value": 7.4, "unit": "SU"}]}}}},
        "responses": {
          "200": {"description": "Each value beside its limit with EPA's rule's verdict, every value due, the forms' headline and tally", "content": {"application/json": {"schema": {"type": "object"}}}},
          "400": {"description": "permit.missing, permit.malformed, period.missing, period.malformed, values.missing, values.malformed, values.too_many, body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "404": {"description": "permit.not_held", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "413": {"description": "body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/dmr/fill": {
      "post": {
        "operationId": "fill_dmr",
        "summary": "Compute a period's DMR values from the plant's own monitoring rows",
        "description": "The numbers a US NPDES permit's Discharge Monitoring Report asks for in one period, computed from the plant's own raw results (daily samples, flows): for each value due on the period's forms (EPA's national limits file) its statistic as EPA defines it (monthly average, daily maximum, weekly average over EPA's Sunday-to-Saturday weeks, geometric mean, loadings in lb/d from concentration x flow x 8.34, percent removal), the rows it was computed from, and EPA's violation rule's verdict against the limit. A value the rows cannot give is refused with its code (fill.no_column, fill.unit, fill.ambiguous, dmr.nd_rule_missing ...): a number the rows do not hold is never supplied. Send `rows` as JSON (date, parameter, value, unit, point) or `table` as the file's text (a laboratory's long export, or a sheet of days with one column per parameter); include the previous month's last days when a weekly average is due. A result below detection enters an average by `nd_rule` (zero, half, dl, dl_lt), else by the state's written rule. `netdmr: true` adds the NetDMR \"Import DMRs\" file as text (not yet validated by NetDMR's own import check). The rows reach our server to be computed and are not kept: only how many rows were sent and values filled is counted.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["permit", "period_end"], "additionalProperties": false, "properties": {"permit": {"type": "string", "description": "The NPDES permit number, e.g. PA0228061."}, "period_end": {"type": "string", "description": "The reporting period: its month (2026-09) or its last day (2026-09-30)."}, "rows": {"type": "array", "maxItems": 20000, "description": "The plant's results, one a row (send rows or table).", "items": {"type": "object", "required": ["date", "parameter", "value"], "additionalProperties": false, "properties": {"date": {"type": "string", "description": "The sample's day: 2026-09-01 or 9/1/2026."}, "parameter": {"type": "string", "description": "As the plant's log names it: TSS, CBOD5, Ammonia-N, Flow, pH, E. coli, Copper ..."}, "value": {"type": ["number", "string"], "description": "The result: 12, or \"<0.5\" below detection, or \"ND\" with a detection_limit."}, "unit": {"type": "string", "description": "mg/L, ug/L, MGD, SU, #/100mL ..."}, "point": {"type": "string", "description": "Where it was sampled, as the plant names it: Influent, Effluent, Outfall 002 ..."}, "outfall": {"type": "string", "description": "Optional: the outfall the sample belongs to, read with the point."}, "qualifier": {"type": "string", "description": "Optional: <, >, or ND."}, "detection_limit": {"type": ["number", "string"], "description": "Optional: the detection or reporting limit of an ND result."}}}}, "table": {"type": ["string", "array"], "items": {"type": "array"}, "description": "The plant's file as text (CSV, TSV or semicolons; at most 2000000 characters) or as lines of cells (send rows or table)."}, "nd_rule": {"type": "string", "enum": ["zero", "half", "dl", "dl_lt"], "description": "How a result below detection enters an average: as zero, half the limit, the limit (dl), or the limit reported as less-than (dl_lt). Default: the state's written rule, else none (such a statistic is refused)."}, "netdmr": {"type": "boolean", "default": false, "description": "Also return the NetDMR \"Import DMRs\" file (CSV text) for the values filled."}}}, "example": {"permit": "PA0228061", "period_end": "2026-09", "nd_rule": "half", "rows": [{"date": "2026-09-01", "parameter": "TSS", "value": 12, "unit": "mg/L", "point": "Effluent"}, {"date": "2026-09-01", "parameter": "Flow", "value": 0.61, "unit": "MGD", "point": "Effluent"}]}}}},
        "responses": {
          "200": {"description": "Each value due, computed with the rows it came from and its verdict, or refused with its code", "content": {"application/json": {"schema": {"type": "object"}}}},
          "400": {"description": "permit.missing, permit.malformed, period.missing, period.malformed, rows.missing, rows.malformed, rows.too_many, table.malformed, table.too_many, nd_rule.malformed, body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "404": {"description": "permit.not_held", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "413": {"description": "table.too_large, body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/designations": {
      "get": {
        "operationId": "find_designations",
        "summary": "What the species registers we hold say about one species, each status cited",
        "description": "US Endangered Species Act lists, Canada's Species at Risk Act and COSEWIC, provincial acts, the IUCN Red List, CITES, CMS, the EU Habitats and Birds Directives' annexes and UK schedules. Each row: the status as printed, an outcome (listed, listed_qualified = only under a population or subspecies to confirm, watch_listed, assessed_not_listed, scope_undetermined), and a cite block (instrument, edition, the line the register prints, source URL and sha256). Registers searched that do not name the species are in `silent`, with what each one's silence means.",
        "parameters": [
          {"name": "species", "in": "query", "required": true, "schema": {"type": "string"}, "description": "A scientific name (Myotis lucifugus, Rana draytonii; authorship allowed) or a common name exactly as a register prints it (little brown myotis)."},
          {"name": "place", "in": "query", "schema": {"type": "string"}, "description": "ISO 3166 code of where the species is: US, CA, GB, FR, US-CA, CA-ON, GB-SCT. Only the registers that reach it are searched, with the global ones (IUCN, CITES, and CMS where the country is a Party)."}
        ],
        "responses": {
          "200": {"description": "Rows, or a `refused` block (designations.none_held with registers_searched, species.unreadable, species.ambiguous with candidates)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Designations"}}}},
          "400": {"description": "species.missing, place.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      },
      "post": {
        "operationId": "screen_species",
        "summary": "Screen a species list against the species registers held, in one call",
        "description": "Up to 500 names, each answered by find_designations itself: its designations with their cites and the registers searched that are `silent` on it with what each one's silence means, or its own coded refusal (designations.none_held = no register searched names it, a statement about these registers and never that the species is unprotected; species.ambiguous with candidates; species.unreadable). A register's instrument, title, edition, place, note for the place, source URL and sha256 are sent once, in `registers`: a designation, its cite or a silent entry leaves out a field only where its value is the register's. A designation without `outcome_says` says `outcomes[outcome]`; a reconciled name without `source` is read from `backbone`. `summary` counts the names listed, listed only under a population or subspecies, watch-listed, named but listed by none, named by no register, ambiguous and refused, and how many names each register lists. Use it instead of one call a name: the door allows 30 calls in 10 seconds.",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["species"], "additionalProperties": false, "properties": {
          "species": {"type": "array", "minItems": 1, "maxItems": 500, "items": {"type": "string"}, "description": "The names as the list prints them: scientific names (authorship allowed) or common names exactly as a register prints them."},
          "place": {"type": "string", "description": "ISO 3166 code of where the species are: US, CA, GB, FR, US-CA, CA-ON, GB-SCT. Omit to search every register."}}},
          "example": {"place": "CA-ON", "species": ["Myotis lucifugus", "Emydoidea blandingii", "Bombus affinis", "little brown myotis"]}}}},
        "responses": {
          "200": {"description": "One result a name, in the list's order, beside the registers they name and a summary; or the call refused once (place.malformed)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ScreenSpecies"}}}},
          "400": {"description": "species.missing, species.malformed, species.too_many (over 500), place.malformed, body.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "413": {"description": "body.too_large", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/search": {
      "get": {
        "operationId": "search",
        "summary": "Search the cited limits, species registers and permits by free text",
        "description": "A query is read by exact matches against what is held: an NPDES permit number, a CAS number, a place's ISO code or name, a parameter name as a regulation prints it, a scientific name or a common name a species register prints, words of an instrument's title. Each result is an id for /fetch, a title saying what it holds, and the url of the page with the same rows. `searched` says how the query was read and names what was read but is not held. Nothing found is a `refused` block (search.none_held) saying what was searched.",
        "parameters": [
          {"name": "query", "in": "query", "required": true, "schema": {"type": "string"}, "description": "Free text: copper effluent Quebec, ammonia Ohio, 7440-50-8 Germany, Myotis lucifugus Ontario, little brown myotis, Metal and Diamond Mining Effluent Regulations, PA0228061."}
        ],
        "responses": {
          "200": {"description": "Results, or a `refused` block (search.none_held) with `searched`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SearchResults"}}}},
          "400": {"description": "query.missing", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    },
    "/cite": {
      "get": {
        "operationId": "cite_document",
        "summary": "Cite numbers or phrases from a public document by page",
        "description": "A public document sent here is kept in our library, to be indexed and read into cited rows; a link on a file-sharing host or carrying a signature or token is read and never kept (`kept` says which, and why). Each `find` is located on the document's own page text, exactly as typed (a number as printed: 0.10 is not 0.1, a decimal comma reads as a point; spaces optional; any case; µg read as ug), and answered with every page it is printed on (`n_hits`, the first 5 with their `quote` and `cite`: page, address, the document's sha256, the day read). A find not printed on the pages read is in `not_found`. `held_as` names the instruments this server reads rows from when the document is one of them. PDFs, web pages and plain text up to 40 MiB; a scan with no text layer is refused (read.no_text).",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The document's public http(s) address."
          },
          {
            "name": "find",
            "in": "query",
            "required": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "maxItems": 10
            },
            "style": "form",
            "explode": true,
            "description": "What to cite, as the document prints it; repeat for each (at most 10)."
          }
        ],
        "responses": {
          "200": {
            "description": "Each find with its pages and quotes; or a `refused` block from reading the document (read.http_<status>, read.unreachable, read.private_host, read.kind_unread, read.no_text, read.damaged, read.failed, engine.timeout, engine.unreachable)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "final_url": {
                      "type": "string"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "bytes": {
                      "type": "integer"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "pdf",
                        "html",
                        "text"
                      ]
                    },
                    "n_pages": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "fetched_at": {
                      "type": "string"
                    },
                    "found": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "find": {
                            "type": "string"
                          },
                          "n_hits": {
                            "type": "integer"
                          },
                          "hits": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "page": {
                                  "type": "integer"
                                },
                                "printed": {
                                  "type": "string"
                                },
                                "quote": {
                                  "type": "string"
                                },
                                "cite": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "not_found": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "find": {
                            "type": "string"
                          },
                          "says": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "says": {
                      "type": "string"
                    },
                    "kept": {
                      "type": "object",
                      "properties": {
                        "kept": {
                          "type": "boolean"
                        },
                        "why": {
                          "type": "string"
                        }
                      }
                    },
                    "held_as": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "next": {
                      "type": "string"
                    },
                    "refused": {
                      "$ref": "#/components/schemas/Refused"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "url.missing, url.malformed, find.missing, find.too_many, read.bad_address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "413": {
            "description": "read.too_large (over 40 MiB)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "429": {
            "description": "cite.daily_cap: the door's reads for the UTC day are spent; nothing was opened",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "503": {
            "description": "cite.not_configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "cite_document_post",
        "summary": "Cite numbers or phrases from a public document by page",
        "description": "A public document sent here is kept in our library, to be indexed and read into cited rows; a link on a file-sharing host or carrying a signature or token is read and never kept (`kept` says which, and why). Each `find` is located on the document's own page text, exactly as typed (a number as printed: 0.10 is not 0.1, a decimal comma reads as a point; spaces optional; any case; µg read as ug), and answered with every page it is printed on (`n_hits`, the first 5 with their `quote` and `cite`: page, address, the document's sha256, the day read). A find not printed on the pages read is in `not_found`. `held_as` names the instruments this server reads rows from when the document is one of them. PDFs, web pages and plain text up to 40 MiB; a scan with no text layer is refused (read.no_text).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "find"
                ],
                "additionalProperties": false,
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "find": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 120
                    },
                    "minItems": 1,
                    "maxItems": 10
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Each find with its pages and quotes; or a `refused` block from reading the document (read.http_<status>, read.unreachable, read.private_host, read.kind_unread, read.no_text, read.damaged, read.failed, engine.timeout, engine.unreachable)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "final_url": {
                      "type": "string"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "bytes": {
                      "type": "integer"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "pdf",
                        "html",
                        "text"
                      ]
                    },
                    "n_pages": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "fetched_at": {
                      "type": "string"
                    },
                    "found": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "find": {
                            "type": "string"
                          },
                          "n_hits": {
                            "type": "integer"
                          },
                          "hits": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "page": {
                                  "type": "integer"
                                },
                                "printed": {
                                  "type": "string"
                                },
                                "quote": {
                                  "type": "string"
                                },
                                "cite": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "not_found": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "find": {
                            "type": "string"
                          },
                          "says": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "says": {
                      "type": "string"
                    },
                    "kept": {
                      "type": "object",
                      "properties": {
                        "kept": {
                          "type": "boolean"
                        },
                        "why": {
                          "type": "string"
                        }
                      }
                    },
                    "held_as": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "next": {
                      "type": "string"
                    },
                    "refused": {
                      "$ref": "#/components/schemas/Refused"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "url.missing, url.malformed, find.missing, find.too_many, read.bad_address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "413": {
            "description": "read.too_large (over 40 MiB)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "429": {
            "description": "cite.daily_cap: the door's reads for the UTC day are spent; nothing was opened",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "503": {
            "description": "cite.not_configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          }
        }
      }
    },
    "/audit": {
      "get": {
        "operationId": "audit_archive",
        "summary": "Audit a published Darwin Core archive",
        "description": "The defects the website's own audit finds in a published Darwin Core archive, given by its GBIF dataset key or its address: each coded, with the check that found it, the file and lines it stands on and its count over the rows read; and every TDWG BDQ TG2 test, ran with its counts or not run under a code (a test not run is not a test passed). With call_id instead: a pending audit, collected.",
        "parameters": [
          {
            "name": "gbif_dataset",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A GBIF dataset key; the archive is fetched from the endpoint GBIF's registry lists."
          },
          {
            "name": "url",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "The http(s) address of a Darwin Core archive (up to 200 MB)."
          },
          {
            "name": "annex",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Also return the audit as a markdown document."
          },
          {
            "name": "call_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "A pending audit's call_id: collect it (202 while it runs)."
          }
        ],
        "responses": {
          "200": {
            "description": "The audit: defects by check with file, lines and count; every BDQ TG2 test ran or not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArchiveAudit"
                }
              }
            }
          },
          "202": {
            "description": "pending: the audit is still running; collect it with GET /audit?call_id=",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pending"
                }
              }
            }
          },
          "400": {
            "description": "source.missing, source.several, dataset.malformed, url.malformed, url.refused, call_id.malformed, call_id.unknown, file.malformed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "404": {
            "description": "dataset.not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "413": {
            "description": "archive.too_large, body.too_large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "422": {
            "description": "archive.not_dwca, archive.unreadable, dataset.no_archive",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "502": {
            "description": "archive.unreachable, registry.unreachable, audit.failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "503": {
            "description": "engine.unreachable, engine.timeout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "audit_archive_post",
        "summary": "Audit a Darwin Core archive named in JSON or sent as a file",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "gbif_dataset": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "content_base64": {
                    "type": "string",
                    "description": "The zip itself, base64 (up to 10 MB of zip)."
                  },
                  "filename": {
                    "type": "string"
                  },
                  "annex": {
                    "type": "boolean",
                    "default": false
                  },
                  "call_id": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "gbif_dataset": "ffd67559-7ebe-41cc-9280-74fc40000f01"
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The zip (up to 10 MB)."
                  },
                  "annex": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The audit: defects by check with file, lines and count; every BDQ TG2 test ran or not run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArchiveAudit"
                }
              }
            }
          },
          "202": {
            "description": "pending: the audit is still running; collect it with GET /audit?call_id=",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pending"
                }
              }
            }
          },
          "400": {
            "description": "source.missing, source.several, dataset.malformed, url.malformed, url.refused, call_id.malformed, call_id.unknown, file.malformed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "404": {
            "description": "dataset.not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "413": {
            "description": "archive.too_large, body.too_large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "422": {
            "description": "archive.not_dwca, archive.unreadable, dataset.no_archive",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "502": {
            "description": "archive.unreachable, registry.unreachable, audit.failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          },
          "503": {
            "description": "engine.unreachable, engine.timeout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refused"
                }
              }
            }
          }
        }
      }
    },
    "/fetch": {
      "get": {
        "operationId": "fetch",
        "summary": "One document search returned, as text with the url to cite",
        "description": "limits/<place>/<parameter>: every cited row for that parameter there (at most 60 in the text; `metadata.total` and the JSON pages the text names carry every one). species/<name>[/<place>]: what each species register says, and each register searched that is silent. place/<place>: instruments and parameters held. source/<instrument>: one instrument's edition and source. permit/<NPDES number>: one US NPDES permit's limits by outfall.",
        "parameters": [
          {"name": "id", "in": "query", "required": true, "schema": {"type": "string"}, "description": "An id from /search: limits/CA-QC/copper, species/Myotis lucifugus/CA-ON, place/US-OH, source/ca_mdmer, permit/PA0228061."}
        ],
        "responses": {
          "200": {"description": "The document; when no row is held, a document of what was searched with a `refused` block (rows.none_held, designations.none_held)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Document"}}}},
          "400": {"description": "id.missing, id.malformed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}},
          "404": {"description": "document.not_held, permit.not_held", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Refused"}}}}
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Pending": {
        "type": "object",
        "required": [
          "pending",
          "call_id"
        ],
        "properties": {
          "pending": {
            "type": "boolean"
          },
          "call_id": {
            "type": "string"
          },
          "retry_after_s": {
            "type": "integer"
          },
          "says": {
            "type": "string"
          }
        }
      },
      "ArchiveAudit": {
        "type": "object",
        "properties": {
          "archive": {
            "type": "object",
            "description": "source (gbif, url, upload), dataset (GBIF's registry entry), url, bytes, sha256, core, extensions, read"
          },
          "scope": {
            "type": "object",
            "description": "rows_read, rows_in_file, complete, columns_read, columns_unmapped, reads"
          },
          "summary": {
            "type": "object",
            "properties": {
              "checks": {
                "type": "integer"
              },
              "checks_fired": {
                "type": "integer"
              },
              "defects": {
                "type": "integer"
              },
              "defects_shown": {
                "type": "integer"
              },
              "cells": {
                "type": "integer"
              },
              "bdq_ran": {
                "type": "integer"
              },
              "bdq_not_compliant": {
                "type": "integer"
              },
              "bdq_not_run": {
                "type": "integer"
              }
            }
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "severity": {
                  "type": "string"
                },
                "proposes_a_fix": {
                  "type": "boolean"
                },
                "findings": {
                  "type": "integer"
                },
                "what": {
                  "type": "string"
                },
                "do": {
                  "type": "string"
                }
              }
            }
          },
          "findings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "check": {
                  "type": "integer",
                  "description": "index into checks"
                },
                "code": {
                  "type": "string"
                },
                "field": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "of_rows": {
                  "type": "integer"
                },
                "examples": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "file": {
                  "type": "string"
                },
                "lines": {
                  "type": "array",
                  "items": {
                    "type": "integer"
                  }
                },
                "lines_matched": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "by": {
                  "type": "string",
                  "enum": [
                    "value",
                    "row_position",
                    "blank_cell",
                    "bdq_test",
                    "declaration"
                  ]
                },
                "not_located": {
                  "type": "string"
                },
                "proposal": {
                  "type": "object"
                },
                "asks": {
                  "type": "string"
                }
              }
            }
          },
          "bdq": {
            "type": "object",
            "description": "standard, unit, file, records, summary, ran (test, terms, compliant, not_compliant, prerequisites_not_met, file, lines, values), not_run by code"
          },
          "kept": {
            "type": "object"
          },
          "annex": {
            "type": "object",
            "properties": {
              "format": {
                "type": "string"
              },
              "chars": {
                "type": "integer"
              },
              "text": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "says": {
            "type": "string"
          }
        }
      },
      "Cite": {"type": "object", "properties": {
        "instrument": {"type": "string"}, "title": {"type": "string"}, "issuer": {"type": ["string", "null"]}, "edition": {"type": ["string", "null"]},
        "section": {"type": ["string", "null"]}, "page": {"type": ["integer", "string", "null"]}, "quote": {"type": ["string", "null"]},
        "source_url": {"type": ["string", "null"]}, "source_sha256": {"type": ["string", "null"]},
        "note": {"type": "string", "description": "What the register prints beside the value (e.g. a later or earlier value and its date)."},
        "table": {"type": "string"}, "column": {"type": "string", "description": "The register column the value sits in (e.g. mcl, mclg)."}}},
      "Row": {"type": "object", "properties": {
        "parameter": {"type": "string"}, "parameter_key": {"type": "string"}, "value": {"type": "string"}, "value_num": {"type": ["number", "null"]},
        "range": {"type": ["array", "null"]}, "unit": {"type": ["string", "null"]}, "statistic": {"type": ["string", "null"]}, "direction": {"type": ["string", "null"]},
        "kind": {"type": "string"}, "medium": {"type": "string"}, "place": {"type": "array", "items": {"type": "string"}},
        "conditions": {"type": "array", "items": {"type": "string"}}, "cite": {"$ref": "#/components/schemas/Cite"}}},
      "Refused": {"type": "object", "properties": {"refused": {"type": "object", "properties": {"code": {"type": "string"}, "says": {"type": "string"}}}}},
      "DwcColumn": {"type": "object", "properties": {
        "header": {"type": "string"}, "status": {"type": "string", "enum": ["mapped", "refused", "empty", "unmapped"]},
        "term": {"type": ["string", "null"]}, "terms": {"type": "array", "items": {"type": "string"}},
        "rule": {"type": "string", "enum": ["header_exact", "header_token", "header_packed", "header_grid"]},
        "evidence": {"type": "object", "properties": {"alias": {"type": "string"}, "alias_rank": {"type": ["integer", "null"]},
          "alias_origin": {"type": ["string", "null"], "enum": ["standard", "ours", "learned", "wikidata", null]}, "table": {"type": "string"},
          "also_nominated": {"type": "array", "items": {"type": "string"}}}},
        "values_check": {"type": "object", "properties": {"check": {"type": "string"}, "run_here": {"type": "boolean"}, "says": {"type": "string"}}},
        "named": {"type": "string"},
        "refused": {"type": "object", "properties": {"code": {"type": "string"}, "says": {"type": "string"}}}}},
      "DwcMap": {"type": "object", "properties": {
        "rules": {"type": "object"}, "scope": {"type": "string"},
        "columns": {"type": "array", "items": {"$ref": "#/components/schemas/DwcColumn"}},
        "summary": {"type": "object"}, "questions": {"type": "array", "items": {"type": "object"}},
        "required": {"type": "object", "properties": {"occurrence": {"type": "object"}, "checklist": {"type": "object"}}},
        "refused": {"type": "object"}}},
      "Party": {"type": "object", "additionalProperties": false, "description": "GBIF needs given, sur, organization and email.", "properties": {
        "given": {"type": "string"}, "sur": {"type": "string"}, "organization": {"type": "string"}, "email": {"type": "string"},
        "position": {"type": "string"}, "country": {"type": "string"}, "url": {"type": "string"}}},
      "DwcArchive": {"type": "object", "properties": {
        "archive": {"type": "object", "properties": {
          "filename": {"type": "string"}, "bytes": {"type": "integer"}, "sha256": {"type": "string"}, "core": {"type": "string"},
          "records": {"type": "integer"}, "rows_in": {"type": "integer"}, "rows_lost": {"type": "integer"}, "rows_refused": {"type": "integer"},
          "terms": {"type": "array", "items": {"type": "string"}}, "extensions": {"type": "array", "items": {"type": "string"}},
          "members": {"type": "array", "items": {"type": "object", "properties": {"name": {"type": "string"}, "bytes": {"type": "integer"}}}},
          "publishable": {"type": "object", "properties": {"ok": {"type": "boolean"}, "missing": {"type": "array", "items": {"type": "string"}}, "says": {"type": "string"}}},
          "generalised": {"type": ["object", "null"]}, "inline": {"type": "boolean"}, "base64": {"type": "string"}}},
        "could_not_read": {"type": "object", "properties": {"n": {"type": ["integer", "null"]}, "vocabulary": {"type": "string"},
          "items": {"type": "array", "items": {"type": "object", "properties": {"code": {"type": "string"}, "scope": {"type": "string"},
            "about": {"type": "string"}, "n_rows": {"type": ["integer", "string", "null"]}, "status": {"type": "string"},
            "what_it_means": {"type": "string"}, "what_we_saw": {"type": "string"}}}}}},
        "notices": {"type": "array", "items": {"type": "string"}}, "says": {"type": "string"}, "kept": {"type": "string"},
        "engine": {"type": "object", "properties": {"upload_id": {"type": "string"}, "seconds": {"type": "number"}}},
        "refused": {"type": "object"}}},
      "Limits": {"type": "object", "properties": {
        "query": {"type": "object"}, "searched": {"type": "object"}, "total": {"type": "integer"}, "offset": {"type": "integer"},
        "returned": {"type": "integer"}, "next_offset": {"type": ["integer", "null"]},
        "rows": {"type": "array", "items": {"$ref": "#/components/schemas/Row"}},
        "refused": {"type": "object"}}},
      "Designation": {"type": "object", "properties": {
        "register": {"type": "string"}, "name": {"type": "string"}, "status": {"type": "string"}, "outcome": {"type": "string"},
        "outcome_says": {"type": "string"}, "matched_at": {"type": "string"}, "place": {"type": "array", "items": {"type": "string"}},
        "legal_instrument": {"type": "boolean"}, "kind": {"type": "string"}, "population": {"type": ["string", "null"]},
        "asks": {"type": ["string", "null"]}, "note": {"type": ["string", "null"]}, "cite": {"$ref": "#/components/schemas/Cite"}}},
      "Designations": {"type": "object", "properties": {
        "query": {"type": "object"}, "name": {"type": "object"}, "searched": {"type": "object"}, "total": {"type": "integer"},
        "designations": {"type": "array", "items": {"$ref": "#/components/schemas/Designation"}},
        "silent": {"type": "array", "items": {"type": "object"}}, "refused": {"type": "object"}}},
      "Verdict": {"allOf": [{"$ref": "#/components/schemas/Row"}, {"type": "object", "properties": {
        "verdict": {"type": "string", "enum": ["over", "under", "within", "not_comparable"]},
        "why": {"type": "object", "properties": {"code": {"type": "string"}, "says": {"type": "string"}}},
        "compared": {"type": "object", "properties": {"value": {"type": "string"}, "unit": {"type": "string"}, "value_in_row_unit": {"type": "string"},
          "exact": {"type": "boolean"}, "limit": {"type": "string"}, "limit_unit": {"type": ["string", "null"]}, "direction": {"type": "string"}}}}}]},
      "Check": {"type": "object", "properties": {
        "query": {"type": "object"}, "searched": {"type": "object"},
        "value": {"type": "object", "properties": {"value": {"type": "string"}, "unit": {"type": "string"}, "unit_key": {"type": "string"}, "family": {"type": ["string", "null"]}}},
        "counts": {"type": "object", "properties": {"over": {"type": "integer"}, "under": {"type": "integer"}, "within": {"type": "integer"}, "not_comparable": {"type": "integer"}}},
        "not_comparable_by": {"type": "object", "additionalProperties": {"type": "integer"}}, "says": {"type": "string"}, "reads_as": {"type": "string"},
        "total": {"type": "integer"}, "offset": {"type": "integer"}, "returned": {"type": "integer"}, "next_offset": {"type": ["integer", "null"]},
        "rows": {"type": "array", "items": {"$ref": "#/components/schemas/Verdict"}},
        "refused": {"type": "object"}}},
      "ClaimRow": {"allOf": [{"$ref": "#/components/schemas/Row"}, {"type": "object", "properties": {
        "verdict": {"type": "string", "enum": ["same", "differs", "not_comparable"]},
        "why": {"type": "object", "properties": {"code": {"type": "string"}, "says": {"type": "string"}}},
        "compared": {"type": "object", "properties": {"value": {"type": "string"}, "unit": {"type": "string"}, "value_in_row_unit": {"type": "string"},
          "exact": {"type": "boolean"}, "held": {"type": "string"}, "held_unit": {"type": ["string", "null"]}}}}}]},
      "Claim": {"type": "object", "properties": {
        "query": {"type": "object"}, "searched": {"type": "object"},
        "claim": {"type": "object", "properties": {"parameter": {"type": "string"}, "place": {"type": ["string", "null"]}, "medium": {"type": ["string", "null"]},
          "statistic": {"type": ["string", "null"]}, "value": {"type": "string"}, "unit": {"type": "string"}}},
        "verdict": {"type": "string", "enum": ["confirmed", "contradicted", "not_held", "not_comparable"]}, "says": {"type": "string"}, "reads_as": {"type": "string"},
        "counts": {"type": "object", "properties": {"same": {"type": "integer"}, "differs": {"type": "integer"}, "not_comparable": {"type": "integer"}}},
        "not_comparable_by": {"type": "object", "additionalProperties": {"type": "integer"}}, "other_statistics": {"type": "object", "additionalProperties": {"type": "integer"}},
        "confirmed_by": {"type": "array", "items": {"$ref": "#/components/schemas/ClaimRow"}},
        "held_otherwise": {"type": "array", "items": {"$ref": "#/components/schemas/ClaimRow"}},
        "not_comparable": {"type": "array", "items": {"$ref": "#/components/schemas/ClaimRow"}},
        "listed": {"type": "object"},
        "sentence": {"type": "object", "properties": {"value_printed": {"type": "boolean"}, "unit_beside": {"type": "boolean"}, "parameter_named": {"type": "boolean"}, "says": {"type": "string"}}},
        "refused": {"type": "object"}}},
      "SearchResults": {"type": "object", "required": ["results"], "properties": {
        "results": {"type": "array", "items": {"type": "object", "required": ["id", "title", "url"], "properties": {"id": {"type": "string"}, "title": {"type": "string"}, "url": {"type": "string"}}}},
        "searched": {"type": "object", "description": "how the query was read (places, medium, parameters, species names tried, permits, instruments matched), `not_held`, and `more` when a parameter is held in more places than shown"},
        "refused": {"type": "object"}}},
      "Document": {"type": "object", "required": ["id", "title", "text", "url"], "properties": {
        "id": {"type": "string"}, "title": {"type": "string"}, "text": {"type": "string"}, "url": {"type": "string"},
        "metadata": {"type": "object", "description": "type, place, parameter or species, total rows, and `json`: the same rows as JSON"},
        "refused": {"type": "object"}}},
      "CheckValues": {"type": "object", "properties": {
        "query": {"type": "object"}, "searched": {"type": "object", "properties": {"places": {"type": "array", "items": {"type": "string"}}, "parameters": {"type": "object", "description": "Each parameter as typed: how it was matched (parameter_keys, names_matched, match)."}}},
        "summary": {"type": "object", "properties": {"rows": {"type": "integer"}, "over": {"type": "integer"}, "under": {"type": "integer"}, "within": {"type": "integer"}, "not_comparable": {"type": "integer"}, "refused": {"type": "integer"}, "refused_by": {"type": "object", "additionalProperties": {"type": "integer"}}, "says": {"type": "string"}}},
        "reads_as": {"type": "string"}, "packed_as": {"type": "string"},
        "sources_searched": {"type": "array", "items": {"type": "object"}, "description": "When a row is rows.none_held: the instruments searched for this place and medium, once."},
        "limits": {"type": "array", "items": {"$ref": "#/components/schemas/Row"}},
        "results": {"type": "array", "items": {"type": "object", "properties": {
          "index": {"type": "integer"}, "outcome": {"type": "string", "enum": ["over", "under", "within", "not_comparable", "refused"]},
          "query": {"type": "object"}, "value": {"type": "object"}, "counts": {"type": "object"}, "not_comparable_by": {"type": "object"}, "says": {"type": "string"},
          "total": {"type": "integer"}, "returned": {"type": "integer"}, "next_offset": {"type": ["integer", "null"]},
          "verdicts": {"type": "array", "items": {"type": "object", "properties": {"limit": {"type": "integer"}, "verdict": {"type": "string", "enum": ["over", "under", "within", "not_comparable"]}, "why": {"type": "object"}, "compared": {"type": "object", "properties": {"value_in_row_unit": {"type": "string"}, "exact": {"type": "boolean"}}}}}},
          "refused": {"type": "object"}}}},
        "refused": {"type": "object"}}},
      "Certificate": {"type": "object", "properties": {"query": {"type": "object"}, "file": {"type": "object", "properties": {"name": {"type": ["string", "null"]}, "bytes": {"type": "integer"}, "format": {"type": "string", "enum": ["pdf", "xlsx", "xls", "csv"]}, "sha256": {"type": "string"}, "from": {"type": "string"}}}, "read": {"type": "object", "description": "lab, certificates, samples, parameters, rows, and the pages (or sheets) rows were read from"}, "checked": {"type": "object", "description": "places searched, or the place's own `refused` (the rows are still returned)"}, "summary": {"type": "object", "properties": {"samples": {"type": "integer"}, "rows": {"type": "integer"}, "over": {"type": "integer"}, "under": {"type": "integer"}, "within": {"type": "integer"}, "not_comparable": {"type": "integer"}, "below_detection": {"type": "integer"}, "refused": {"type": "integer"}, "refused_by": {"type": "object", "additionalProperties": {"type": "integer"}}, "says": {"type": "string"}}}, "notes": {"type": "array", "items": {"type": "object", "properties": {"code": {"type": "string"}, "says": {"type": "string"}}}}, "packed_as": {"type": "string"}, "exceedances": {"type": "array", "items": {"type": "object", "properties": {"i": {"type": "integer"}, "s": {"type": "integer"}, "parameter": {"type": "string"}, "value": {"type": "string"}, "unit": {"type": "string"}, "page": {"type": "integer"}, "tab": {"type": "string"}, "over": {"type": "array", "items": {"type": "integer"}}, "under": {"type": "array", "items": {"type": "integer"}}}}}, "limits": {"type": "array", "items": {"$ref": "#/components/schemas/Row"}}, "refusals": {"type": "object", "additionalProperties": {"type": "string"}, "description": "Each refusal code's sentence, once"}, "sources_searched": {"type": "array", "items": {"type": "object"}}, "samples": {"type": "array", "items": {"type": "object", "properties": {"sample": {"type": "string"}, "date": {"type": "string"}, "matrix": {"type": "string"}, "lab_id": {"type": "string"}, "certificate": {"type": "string"}}}}, "total": {"type": "integer"}, "offset": {"type": "integer"}, "returned": {"type": "integer"}, "next_offset": {"type": ["integer", "null"]}, "rows": {"type": "array", "items": {"type": "object", "properties": {"i": {"type": "integer"}, "s": {"type": "integer", "description": "index into samples"}, "parameter": {"type": "string", "description": "as printed"}, "value": {"type": "string", "description": "as printed"}, "unit": {"type": "string"}, "qualifier": {"type": "string", "description": "<, > or ND"}, "detection_limit": {"type": "string"}, "rdl": {"type": "string"}, "mdl": {"type": "string"}, "loq": {"type": "string"}, "flag": {"type": "string"}, "lab_flag": {"type": "string"}, "page": {"type": "integer"}, "tab": {"type": "string"}, "checked_as": {"type": "string"}, "outcome": {"type": "string", "enum": ["over", "under", "within", "not_comparable"]}, "counts": {"type": "object"}, "over": {"type": "array", "items": {"type": "integer"}}, "under": {"type": "array", "items": {"type": "integer"}}, "refused": {"type": "object", "properties": {"code": {"type": "string"}, "says": {"type": "string"}}}}}}, "refused": {"type": "object"}}},
      "ScreenSpecies": {"type": "object", "properties": {
        "query": {"type": "object"}, "searched": {"type": "object"},
        "summary": {"type": "object", "properties": {"names": {"type": "integer"}, "listed": {"type": "integer"}, "listed_qualified": {"type": "integer"}, "watch_listed": {"type": "integer"}, "named_not_listed": {"type": "integer"}, "none_held": {"type": "integer"}, "ambiguous": {"type": "integer"}, "refused": {"type": "integer"}, "refused_by": {"type": "object"}, "listed_by": {"type": "object", "additionalProperties": {"type": "integer"}}, "says": {"type": "string"}}},
        "packed_as": {"type": "string"}, "registers": {"type": "object", "additionalProperties": {"type": "object"}}, "outcomes": {"type": "object"}, "backbone": {"type": "object"},
        "results": {"type": "array", "items": {"type": "object", "properties": {
          "index": {"type": "integer"}, "outcome": {"type": "string", "enum": ["listed", "listed_qualified", "watch_listed", "named_not_listed", "none_held", "ambiguous", "refused"]},
          "query": {"type": "object"}, "name": {"type": "object"}, "total": {"type": "integer"},
          "designations": {"type": "array", "items": {"$ref": "#/components/schemas/Designation"}}, "silent": {"type": "array", "items": {"type": "object"}}, "refused": {"type": "object"}}}},
        "refused": {"type": "object"}}}
    }
  }
}
