{"service":"DiaDNA ReID match API","endpoint":"POST /api/v1/verify-match","auth":"X-Api-Key header (per-client keys; ask the operator)","scope":"single-pair match case: one rough scan set against one claimed polish scan set per call. Accuracy is population-specific and thresholds are calibrated per population","inputs":{"multipart":"fields rough_files / polish_files (.dpt/.csv/.txt/.0/.zip), optional reject_target","json":"{\"rough\": {\"wavenumbers\": [...], \"spectra\": [[...], ...], \"stone_id\": \"optional but recommended\"}, \"polish\": {...}, \"reject_target\": 0.98}"},"reject_targets":[0.99,0.98,0.97,0.96,0.95,0.94,0.93,0.92,0.91,0.9],"default_reject_target":0.98,"expected_results":{"endpoint":"POST /api/v1/expected","purpose":"tell us the GROUND TRUTH of claims we have already answered, keyed by the claim_id returned with each verdict. Deliberate false claims stay blind at submission time; you label them afterwards.","body":"JSON list of {\"claim_id\": \"...\", \"expected\": \"match\"|\"no_match\", \"stone_id\": optional, \"note\": optional}","max_per_call":5000,"advisory":"labels are recorded and reported; they never move a threshold, which changes only by manual approval"},"experimental_reject_targets":[0.94,0.93,0.92,0.91,0.9],"experimental_note":"reject_target below 0.95 is EXPERIMENTAL: added 2026-09-04 for live measurement, not for customer quotation. 0.91 and 0.90 also cannot be population-calibrated — they do not settle at any bank size measured, so they always run on shipped defaults.","notes":"every call is logged for drift and access-pattern review; P(match) assumes a 50:50 claim mix and is not recalibrated per population -- decide on verdict, not probability; send the instrument's unprocessed export, as smoothed input is detected and may be refused (see API.md)"}