- the six read endpoints:
check-malicious,query-latest,threat-feed,false-positive,threat-data,query-by-username - the two write endpoints:
submit-threat-report,modify-threat-report
A
CORS OPTIONS preflight request returns 204 or 200 — this is expected browser behavior, not an error.Quick reference
Shared errors — read endpoints
These are returned by every read endpoint (check-malicious, query-latest, threat-feed, false-positive, threat-data, query-by-username). Wording and status are identical unless noted per endpoint below.
405 — Method not allowed
query-by-username variant: "Method not allowed. Use GET."429 — IP rate limit (500 req / 15 min per IP)
429 — Token rate limit (per-minute, tier-scoped)
429 — Daily quota exceeded
threat-feed and query-by-username omit the trailing "Upgrade to Pro for higher limits." sentence but keep the same fields.500 — Internal server error
check-malicious
401 — Missing API token
401 — Invalid or inactive token
400 — Invalid or missing report_type
400 — Missing resource_identifier
400 — Invalid repository format
500 — Database query failed
query-latest
401 — Missing API token
401 — Invalid token
401 — Inactive token
400 — Missing ecosystem
500 — Query failed
threat-feed
401 — Missing API token
401 — Invalid token
401 — Inactive token
403 — Endpoint requires Core/Pro/Enterprise
403 — unverified=true requires Pro/Enterprise
400 — Invalid hours
400 — Missing ecosystem
500 — Query failed
threat-data
401 — Missing API token
401 — Invalid or inactive token
403 — Requires Pro/Editor/Admin
400 — Missing threat_id
400 — Invalid UUID
404 — Not found or not verified/modified
false-positive
400 — Missing ecosystem parameter
400 — Invalid hours parameter
400 — Invalid source parameter
401 — Missing API token
401 — Invalid or inactive token
403 — Insufficient role (e.g. standard tier)
405 — Wrong HTTP method (only GET is allowed)
429 — IP rate limit (500 requests per 15 minutes per IP)
429 — Token rate limit (per minute; varies by tier)
429 — Daily quota exceeded
tier/used/limit reflect the caller’s actual tier — trial counts as free (2,000/day), pro/core 25,000, enterprise 50,000, admin/editor unlimited.
500 — Threats query failed
500 — OSV withdrawals query failed
500 — Unexpected error (catch-all)
query-by-username
401 — Missing API token
401 — Invalid token
401 — Inactive token
403 — Requires Pro/Enterprise
400 — Missing params
500 — Failed to verify permissions
500 — Database query failed
Write endpoints
submit-threat-report and modify-threat-report rate limits are per-hour (submission/modification counts) rather than per-minute.
submit-threat-report
401 — No Authorization header
401 — Invalid API token (osm_...)
429 — IP rate limit
429 — Submission rate limit (per hour)
10/hour for Free users. Limit may be increased by an admin.
403 — New-user unverified cap
405 — Method not allowed
400 — Missing required fields
409 — Duplicate package in registry
Returned only for package reports, when a report with the samepackage_name and registry already exists in any status, including pending, rejected, and false positive. Matching is exact and case-sensitive. Other report types aren’t checked for duplicates. To update the existing report, pass existingThreatId to modify-threat-report as threat_id.
500 — Existing-package lookup failed
500 — Threat insert failed
Also returned when a field has a value the database doesn’t accept, such as an unsupportedreport_type or severity_level.
500 — Threat details insert failed (threat was rolled back)
500 — Catch-all
modify-threat-report
401 — No Authorization header
401 — Invalid API token
429 — IP rate limit (whitelisted IPs bypass)
429 — Modification rate limit (per hour)
30/hour for standard users. This limit may be increased by an admin.
405 — Method not allowed
400 — No target identifier supplied
404 — Lookup by package_name returned nothing
404 — Lookup by resource_identifier returned nothing
404 — threat_id not found
500 — Lookup by package_name failed
Also returned when more than one report matches thepackage_name, for example the same name in two registries with no registry value sent. Use threat_id instead.
500 — Lookup by resource_identifier failed
Also returned when more than one report matches theresource_identifier. Use threat_id instead.
500 — Fetch existing threat failed
500 — Version-creation prefetch failed (pro-user edit path)
500 — Save proposed changes failed (pro-user edit path)
500 — Admin/editor threat update failed
Also returned when a field has a value the database doesn’t accept, such as an unsupportedseverity_level.

