Endpoints#

Base URL: https://api.hashwatch.us


Public endpoints (no authentication)#

GET /public/hash-of-day#

Returns today’s known-good hashes for all tracked software. Results are cached for up to 1 hour.

curl https://api.hashwatch.us/public/hash-of-day

This public endpoint returns only the current day. Historical snapshots are an authenticated, Teams-tier feature - use GET /api/v1/intel/history with an API key. Passing a ?date= parameter here returns 403.

Response:

{
  "date": "2026-06-05",
  "generated_at": "2026-06-05T02:14:37Z",
  "cache_hit": true,
  "hashes": [
    {
      "id": "...",
      "executable_name": "chrome-win64.msi",
      "version": "124.0.6367.82",
      "vendor": "Google LLC",
      "platform": "windows",
      "arch": "amd64",
      "hash_sha256": "b94d27b9934d3e08a52e52d7da7dabfac484efe04294e576e9e7c3e07ccb1e83",
      "hash_sha1": null,
      "hash_md5": null,
      "source_url": "https://dl.google.com/...",
      "download_verified": true,
      "valid_from": "2026-06-05T02:13:01Z",
      "sig_signer": "Google LLC",
      "sig_issuer": "DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1",
      "sig_serial": "0a...",
      "sig_thumbprint": "1a2b..."
    }
  ]
}

Fields:

FieldDescription
executable_nameFilename as distributed by the vendor
versionRelease version string
vendorPublisher name
platformwindows, linux, darwin, or android
archamd64, arm64, arm, x86, or universal
hash_sha256SHA-256 fingerprint (always present)
hash_sha1SHA-1 fingerprint - null for manifest-only vendors
hash_md5MD5 fingerprint - null for manifest-only vendors
source_urlThe exact file URL the hash was computed from
download_verifiedtrue when HashWatch downloaded the binary itself
sig_signerAuthenticode subject DN - null for non-PE or manifest-only records
sig_issuerAuthenticode issuer DN - null when signer is null
sig_serialSigning certificate serial (hex) - null when signer is null
sig_thumbprintSigning certificate SHA-1 thumbprint - null when signer is null

GET /.well-known/jwks.json#

Returns the RSA public key used to verify HashWatch-issued JWT tokens, in JWKS format. Use this if you validate tokens locally.

curl https://api.hashwatch.us/.well-known/jwks.json

GET /public/status#

Overall system + per-vendor ingestion health (for the status page).

curl https://api.hashwatch.us/public/status

Transparency log#

Signed daily Merkle roots over the public feed. See Transparency Log.

curl https://api.hashwatch.us/public/transparency
curl https://api.hashwatch.us/public/transparency/key
curl https://api.hashwatch.us/public/transparency/2026-06-28
curl "https://api.hashwatch.us/public/transparency/2026-06-28/proof?sha256=<hex>"

Pull feeds#

Verified known-good hashes in JSON / RSS / STIX 2.1, plus a read-only TAXII 2.1 server. See Integrations → Pull feeds.

curl https://api.hashwatch.us/public/feed.json
curl https://api.hashwatch.us/public/feed.rss
curl https://api.hashwatch.us/public/feed/stix
curl https://api.hashwatch.us/taxii2/

Authenticated endpoints#

All endpoints below require an API key (X-API-Key header) or a JWT Bearer token. See Authentication.


POST /api/v1/auth/token#

Exchange your API key for a short-lived JWT (15 minutes). Useful for high-throughput integrations.

Required permission: any valid key
Required tier: any

curl -X POST https://api.hashwatch.us/api/v1/auth/token \
  -H "X-API-Key: <team-id>.<secret>"

Response:

{
  "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 900
}

expires_in is the token lifetime in seconds (900 = 15 minutes). The JWT carries the key’s sub (team), role (primary), roles (the full effective set, including any additional or time-limited grants), and tier claims.


POST /api/v1/auth/refresh#

Refresh a JWT before it expires. Returns a new token with a fresh 15-minute TTL.

Required permission: any valid JWT
Required tier: any

curl -X POST https://api.hashwatch.us/api/v1/auth/refresh \
  -H "Authorization: Bearer <current-token>"

GET /api/v1/intel/stats#

Returns platform-wide counters: total hash records, distinct vendors, and distinct platforms tracked.

Required permission: intel:stats
Required tier: basic

curl https://api.hashwatch.us/api/v1/intel/stats \
  -H "X-API-Key: <team-id>.<secret>"

Response:

{
  "generated_at": "2026-06-09T02:14:37Z",
  "totals": {
    "known_good_hashes": 312,
    "total_vendors": 56,
    "total_platforms": 4
  }
}

POST /api/v1/intel/lookup#

BinTrust known-good lookup. Checks one or more hashes against the HashWatch known-good corpus and returns a classification for each.

Two sources are checked, in priority order:

  1. HashWatch vendor releases - hashes fetched from official vendor channels, HMAC-signed, and actively tracked. Returns vendor name, executable name, version, and platform.
  2. NSRL/catalog corpus - the NIST NSRL RDS loaded from official NIST data. Returns file name and product name.

Every submitted hash appears in the response. Hashes not found in either source are classified as unknown.

Required permission: intel:lookup
Required tier: basic

curl -X POST https://api.hashwatch.us/api/v1/intel/lookup \
  -H "X-API-Key: <team-id>.<secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "hashes": [
      "b94d27b9934d3e08a52e52d7da7dabfac484efe04294e576e9e7c3e07ccb1e83",
      "d41d8cd98f00b204e9800998ecf8427e"
    ]
  }'

Input hashes are normalised to lowercase. Accepted formats:

LengthAlgorithm
32 charactersMD5
40 charactersSHA-1
64 charactersSHA-256

Up to 100 hashes per request. Duplicate hashes are deduplicated automatically.

Response:

{
  "results": {
    "b94d27b9934d3e08a52e52d7da7dabfac484efe04294e576e9e7c3e07ccb1e83": {
      "classification": "known_vendor_release",
      "source": "hashwatch_vendor",
      "vendor": "Google LLC",
      "executable_name": "chrome-win64.msi",
      "version": "124.0.6367.82",
      "platform": "windows"
    },
    "d41d8cd98f00b204e9800998ecf8427e": {
      "classification": "unknown"
    }
  }
}

Classifications:

ValueMeaning
known_vendor_releaseMatches a record HashWatch actively tracks - fetched from an official vendor channel and HMAC-signed.
known_fileFound in the NSRL/catalog corpus. Not a vendor release we verify, but a recognised OS or software file.
unknownNot found in any known-good source. Warrants further investigation.

Fields by classification:

Fieldknown_vendor_releaseknown_file
source✓ (hashwatch_vendor)✓ (nsrl_minimal etc.)
vendor-
executable_name-
version-
platform-
file_name-
product_name-

This endpoint matches against HashWatch’s currently tracked releases plus the NSRL/BinTrust corpus. To also match superseded / older vendor versions, use POST /api/v1/intel/lookup/historical below.

Tip: Use this endpoint as a first-pass triage tool during incident response. A known_vendor_release result immediately clears a suspected binary. A known_file result means the hash is in NIST’s reference corpus - not necessarily safe, but a known quantity. unknown is the signal that warrants deeper investigation.

Learn more about BinTrust


POST /api/v1/intel/lookup/historical#

Known-good lookup including superseded versions. Identical in shape to POST /api/v1/intel/lookup, but the vendor match also covers older / superseded builds - not just the current tracked release. This answers “was this ever a legitimate vendor hash, even for a version that has since been replaced?”

Every vendor match that came from a superseded build carries an extra field, "historical": true, so you can tell a current release from a retired one.

Required permission: intel:history
Required tier: basic

curl -X POST https://api.hashwatch.us/api/v1/intel/lookup/historical \
  -H "X-API-Key: <team-id>.<secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "hashes": [
      "a1b2c3d4e5f6aabbccddeeff00112233445566778899aabbccddeeff00112233"
    ]
  }'

The request body is the same as /intel/lookup: a hashes array of up to 100 MD5 / SHA-1 / SHA-256 values (normalised to lowercase, deduplicated). The response is the same {"results": { "<hash>": { ... } }} map, with "historical": true added to any match against a superseded version.

Response:

{
  "results": {
    "a1b2c3d4e5f6aabbccddeeff00112233445566778899aabbccddeeff00112233": {
      "classification": "known_vendor_release",
      "source": "hashwatch_vendor",
      "vendor": "Google LLC",
      "executable_name": "chrome-win64.msi",
      "version": "124.0.6367.60",
      "platform": "windows",
      "historical": true
    }
  }
}

GET /api/v1/intel/history#

Returns the full historical record of hash values for a specific executable - every version ever seen, with valid_from / valid_until timestamps showing exactly when each version was current.

Required permission: intel:history
Required tier: basic

curl "https://api.hashwatch.us/api/v1/intel/history?executable=chrome-win64.msi" \
  -H "X-API-Key: <team-id>.<secret>"

Query parameters:

ParameterTypeDescription
executablestringExecutable name to look up (required)
platformstringFilter by platform (windows, linux, darwin, universal)
archstringFilter by arch (amd64, arm64, x86, universal)
limitintegerMax results (default 50, max 200)
offsetintegerPagination offset

Response:

{
  "results": [
    {
      "executable_name": "chrome-win64.msi",
      "version": "124.0.6367.82",
      "hash_sha256": "b94d27b9934d3e08a52e52d7da7dabfac484efe04294e576e9e7c3e07ccb1e83",
      "valid_from": "2026-06-05T02:13:01Z",
      "valid_until": null,
      "status": "current"
    },
    {
      "executable_name": "chrome-win64.msi",
      "version": "124.0.6367.60",
      "hash_sha256": "a1b2c3d4...",
      "valid_from": "2026-05-29T02:11:43Z",
      "valid_until": "2026-06-05T02:13:01Z",
      "status": "superseded"
    }
  ],
  "total": 42,
  "limit": 50,
  "offset": 0
}

POST /api/v1/intel/sbom#

SBOM scan. Submit a CycloneDX or SPDX JSON software bill of materials and get an integrity + risk report for every component in one pass. For each component HashWatch (a) matches any embedded hash (SHA-256 / SHA-1 / MD5) against the known-good corpus - the same engine as /intel/lookup; (b) runs name-only typosquat analysis; and (c) attaches known CVE advisories for tracked packages. The SBOM is parsed in memory and discarded - never stored.

Required permission: intel:packages
Required tier: teams

The request body is the raw SBOM JSON (up to 16 MB); the format (CycloneDX / SPDX) is auto-detected.

curl -X POST https://api.hashwatch.us/api/v1/intel/sbom \
  -H "X-API-Key: <team-id>.<secret>" \
  -H "Content-Type: application/json" \
  --data-binary @sbom.cdx.json

Response:

{
  "format": "CycloneDX",
  "summary": {
    "components": 214,
    "hash_known": 180,
    "hash_unknown": 6,
    "no_hash": 28,
    "typosquat": 1,
    "dependency_confusion": 0,
    "with_advisories": 3
  },
  "components": [
    {
      "name": "left-pad",
      "version": "1.3.0",
      "ecosystem": "npm",
      "hash": { "classification": "known_vendor_release", "source": "hashwatch_vendor" },
      "name_risk": { "risk": "clear", "nearest_known": null },
      "advisories": []
    }
  ]
}

The hash object mirrors an /intel/lookup result (classification one of known_vendor_release / known_file / unknown); name_risk mirrors a /intel/typosquat result; advisories lists known CVEs for tracked packages.


POST /api/v1/intel/typosquat#

Typosquat & dependency-confusion analysis. Name-only - no package is fetched. Submit up to 200 package names and each is classified as known (exact match to a popular / tracked package), typosquat (within edit distance of / a look-alike of a popular name - returns nearest_known + distance), dependency_confusion (a name listed in internal_names that also exists publicly), or clear.

Required permission: intel:packages
Required tier: teams

curl -X POST https://api.hashwatch.us/api/v1/intel/typosquat \
  -H "X-API-Key: <team-id>.<secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "packages": [{ "ecosystem": "npm", "name": "expresss" }],
    "internal_names": ["mycorp-utils"]
  }'

Response:

{
  "results": [
    {
      "ecosystem": "npm",
      "name": "expresss",
      "risk": "typosquat",
      "nearest_known": "express",
      "distance": 1,
      "reason": "within edit distance of a popular package"
    }
  ],
  "summary": { "typosquat": 1 }
}

Both this endpoint and /intel/sbom are also available in the admin console under Supply Chain (/admin/supply-chain).


GET /api/v1/intel/revocations - RevokeRadar feed#

RevokeRadar is HashWatch’s certificate-revocation feed. It returns every signing certificate that RevokeRadar has detected as revoked (via CRL). Each entry includes which vendors used the cert and whether any currently-active binary (still “current” on the dashboard) was signed with it.

currently_active: true is the high-priority signal - it means a binary visible on the public dashboard today was signed with a certificate the CA has since revoked.

Required permission: intel:revocations
Required tier: teams

curl https://api.hashwatch.us/api/v1/intel/revocations \
  -H "X-API-Key: <team-id>.<secret>"

Response:

{
  "revoked_certs": [
    {
      "thumbprint": "a1b2c3d4e5f6...",
      "signer": "Acme Corp",
      "issuer": "DigiCert EV Code Signing CA",
      "revoked_at": "2026-04-15T00:00:00Z",
      "revocation_reason": "keyCompromise",
      "check_method": "crl",
      "affected_vendors": ["AcmeTool", "AcmeSetup"],
      "currently_active": true
    }
  ],
  "total": 1
}

Revocation reasons follow RFC 5280 §5.3.1: unspecified, keyCompromise, cACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold.

Public dashboard - The cert_revoked_at field also appears directly on each hash record in the /public/hash-of-day response and in the dashboard’s RevokeRadar panel ("⚠ RevokeRadar - Revoked Signing Certificates"), so no API key is required to see whether a binary’s signing cert is revoked.


GET /api/v1/intel/revocations/history - RevokeRadar timeline#

The queryable revocation history: the same enriched revoked-cert records as the feed above, but ordered by revocation time (newest first) and filterable by date - so you can answer “what code-signing certs were revoked, and when”.

Required permission: intel:revocations
Required tier: teams

# Everything revoked in Q2 2026, signer containing "Acme"
curl "https://api.hashwatch.us/api/v1/intel/revocations/history?since=2026-04-01&until=2026-07-01&signer=Acme&limit=50" \
  -H "X-API-Key: <team-id>.<secret>"

Query parameters (all optional):

ParameterTypeDescription
sincestringOnly revocations at/after this time (RFC3339 2026-04-01T00:00:00Z or 2026-04-01)
untilstringOnly revocations at/before this time
signerstringCase-insensitive substring match on the certificate subject
limitintegerMax results (default 50, max 200)
offsetintegerPagination offset

The response shape is { total, limit, offset, revoked_certs: [...] }, each entry identical to the feed entries above (including revoked_at, revocation_reason, affected_vendors, currently_active).


GET /api/v1/intel/revocations/{thumbprint} - per-cert detail#

Returns a single revoked certificate’s detail by its 40-character lowercase hex SHA-1 thumbprint - when it was revoked, the reason, the check method, and the affected vendors. Returns 404 if the thumbprint is not a known revoked cert.

Required permission: intel:revocations
Required tier: teams

curl https://api.hashwatch.us/api/v1/intel/revocations/0123456789abcdef0123456789abcdef01234567 \
  -H "X-API-Key: <team-id>.<secret>"

Response: { "revoked_cert": { ...same shape as a feed entry... } }.


GET /api/v1/intel/downloads#

Returns the immutable download audit trail - every time HashWatch streamed a vendor binary to compute its hash. Each record includes the URL, timestamp, file size, and confirmation that nothing was written to disk.

Required permission: intel:downloads
Required tier: teams

curl https://api.hashwatch.us/api/v1/intel/downloads \
  -H "X-API-Key: <team-id>.<secret>"

Query parameters:

ParameterTypeDescription
vendorstringFilter by vendor name
fromISO 8601Start of time range
untilISO 8601End of time range
limitintegerMax results (default 50, max 200)
offsetintegerPagination offset

Response:

{
  "results": [
    {
      "downloaded_at": "2026-06-05T02:13:01Z",
      "deleted_at": "2026-06-05T02:13:01Z",
      "storage_method": "stream",
      "url": "https://dl.google.com/...",
      "size_bytes": 98345678,
      "hash_record_id": "..."
    }
  ],
  "total": 1240
}

storage_method: "stream" and deleted_at == downloaded_at confirm the binary was hashed in memory and never written to disk.


GET /api/v1/intel/export#

Bulk historical export as CSV or JSON. Same Basic-tier gate as /intel/history (intel:history); bounded to ≤366 days / ≤100,000 rows.

curl "https://api.hashwatch.us/api/v1/intel/export?format=csv&from=2026-06-01&to=2026-06-28" \
  -H "X-API-Key: <your-key>" -o hashwatch-export.csv

Query params: format=csv|json, executable (optional), platform, arch, from/to (YYYY-MM-DD).


GET /api/v1/admin/usage#

Your account’s API usage analytics — this-month total, per-endpoint breakdown, a 30-day series, and your tier’s monthly quota. Available to any authenticated account for its own usage.

curl https://api.hashwatch.us/api/v1/admin/usage -H "X-API-Key: <your-key>"

Each tier carries a monthly request quota (Basic 50,000 · Teams 500,000 · Enterprise unlimited); exceeding it returns 429 QUOTA_EXCEEDED.