Developers

Developer documentation

The security data behind Pavoriz, as plain JSON over HTTPS. What is documented here is read only, needs no key and no account.

On this page

Overview

Pavoriz collects phishing hosts and drainer addresses from public blocklists, raises its own security alerts, tracks published exploits and records which dApps people open through the Pavoriz Shield extension. The endpoints below expose that data so you can use it in your own product.

Base URL: https://pavoriz.com. Every endpoint is a GET that returns JSON.

What you can build

Phishing warnings before a page opens

A wallet, browser extension or link preview can check the host a person is about to visit against the feeds Pavoriz syncs, and warn on a match.

  • /api/shield/lookup
  • /api/shield/threats

Address screening before a transfer

Check a destination address before somebody sends to it: whether a feed names it as a drainer, and whether it has sent tokens to one.

  • /api/exploits/check
  • /api/shield/lookup

Alert and incident feeds

Post the dApps Pavoriz is warning about, or new exploit incidents, to a dashboard, a chat bot or a newsletter.

  • /api/alerts
  • /api/exploits

dApp discovery

Show which dApps people open most through Pavoriz Shield, with a session count for each.

  • /api/dapps/popular

Making requests

  • No API key, token or account is needed for anything on this page.
  • Most responses carry ok. When it is false, error holds a sentence you can show or log. The threat list is the exception: it has no ok field and always answers.
  • Only /api/shield/threats and /api/shield/lookup send Access-Control-Allow-Origin: *, so those two can be called from a browser on another site. Call the others from your server.
  • Those same two set a Cache-Control header (five minutes and one hour). The rest set none, so cache on your side if you poll them.
  • There is no published rate limit and no usage tier. If you expect real volume, tell us first through the access form.
  • A 503 or 500 means the lookup did not run. Treat it as no answer, never as a clean result.

API reference

Example values are illustrative. The field names and types are the ones the endpoints return.

Threat list

GET/api/shield/threats

The list the Pavoriz Shield extension caches to flag phishing hosts and malicious addresses. It is the bundled list that ships with the app, plus the host of every live high risk security alert.

Parameters

No parameters.

Good to know

  • Only high risk alerts join the host list. Medium and low alerts are available from /api/alerts.
  • It still answers when the database is unreachable: the bundled list goes out on its own and source reads bundled instead of bundled+alerts.
  • The bundled list is small. The large public blocklists Pavoriz reads are not served here; ask about a specific host or address with /api/shield/lookup.
  • updatedAt is the time the response was generated.
Request
curl https://pavoriz.com/api/shield/threats
Response 200
{
  "version": 1,
  "updatedAt": "2026-09-30T12:00:00.000Z",
  "addresses": ["0x0000000000000000000000000000000000000000"],
  "hosts": ["uniswop.org", "pancakeswap-finance.com", "opensea-mint.com"],
  "source": "bundled+alerts"
}

Response headers: Access-Control-Allow-Origin: *, Cache-Control: public, max-age=300

Host and address lookup

GET/api/shield/lookup

Checks hosts and wallet addresses against the public threat feeds Pavoriz syncs (MetaMask, ScamSniffer and PhishFort lists).

Parameters

hostquery, optional
A host or URL. Repeat the parameter or separate values with commas. The scheme, path, port and a leading www. are removed; localhost, IP addresses and single labels are dropped.
addressquery, optional
A wallet or contract address: 0x followed by 40 hex characters (compared lowercased), or a base58 address of 32 to 44 characters (compared as written). Anything else is dropped. Repeatable and comma separated, like host.

Good to know

  • At least one valid host or address is required.
  • Each list is capped at 20 values per request; the rest are ignored. checked echoes what was actually looked up.
  • A host is matched exactly as normalized. A parent domain is not looked up for you, so ask for it separately if you need it.
  • verdict is listed when a feed Pavoriz names publicly carries the value, and feeds names those feeds. It is watch when only feeds Pavoriz does not name publicly carry it, and feeds is then empty.
  • An empty matches array means none of the feeds carry the value. It is not a statement that a site or address is safe.
Request
curl "https://pavoriz.com/api/shield/lookup?host=uniswop.org&address=0x0000000000000000000000000000000000000000"
Response 200
{
  "ok": true,
  "checked": {
    "hosts": ["uniswop.org"],
    "addresses": ["0x0000000000000000000000000000000000000000"]
  },
  "matches": [
    {
      "value": "uniswop.org",
      "kind": "host",
      "verdict": "listed",
      "feeds": ["MetaMask eth-phishing-detect"]
    }
  ]
}

Response headers: Access-Control-Allow-Origin: *, Cache-Control: public, max-age=3600

Errors

  • 400No valid host or address survived normalizing.
    { "ok": false, "error": "Nothing to look up." }
  • 503The deployment has no database connection. This is not an empty result.
    { "ok": false, "error": "Not available.", "matches": [] }
  • 500The lookup failed. This is not an empty result.
    { "ok": false, "error": "Not available.", "matches": [] }

Security alerts

GET/api/alerts

The dApps Pavoriz is currently warning about: the same live alerts shown on the home page card. Silenced alerts are not returned.

Parameters

No parameters.

Good to know

  • Sorted worst risk first (high, medium, low), then most recently raised.
  • host is the flagged site. link is the real project's site when the flagged host impersonates one, and can be an empty string.
  • icon is a URL or null. source is one of reports, feed, manual or scan.
  • reportCount counts incident reports linked to the alert. live is always true in this response.
Request
curl https://pavoriz.com/api/alerts
Response 200
{
  "ok": true,
  "alerts": [
    {
      "id": "6f1c2b1e-0c4d-4d57-9a53-2c1f7f0e5a10",
      "dappName": "uniswop.org",
      "host": "uniswop.org",
      "link": "https://app.uniswap.org",
      "icon": null,
      "risk": "high",
      "reason": "Clone of the Uniswap interface that asks for unlimited approvals.",
      "source": "manual",
      "reportCount": 0,
      "live": true,
      "raisedAt": "2026-09-01T10:00:00.000Z",
      "updatedAt": "2026-09-01T10:00:00.000Z"
    }
  ]
}

Errors

  • 503The deployment has no database connection.
    { "ok": false, "error": "The database is not configured on this deployment." }
  • 500The read failed. The detail is logged on the server, not returned.
    { "ok": false, "error": "Something went wrong on our side." }

Exploits

GET/api/exploits

Published exploit incidents, newest first. Most come from DefiLlama's public hacks index; the rest are entered by Pavoriz.

Parameters

limitquery, optional
How many to return. Default 60, clamped to 1 to 500.

Good to know

  • occurredOn is a date (YYYY-MM-DD). source is defillama or manual.
  • amountUsd and returnedUsd are null when no figure was published. Null is not zero.
  • chains uses the publisher's own chain names. link is often an empty string, because the index carries no source link.
  • attackers counts attacker addresses Pavoriz has attached to the incident, and affected counts distinct addresses seen sending tokens to them. scannedAt is null when that walk has never run, in which case both counts say nothing yet.
Request
curl "https://pavoriz.com/api/exploits?limit=1"
Response 200
{
  "ok": true,
  "exploits": [
    {
      "id": "b7a0d7c2-5f7e-4c1a-8d0e-1e9f3c2a4b61",
      "source": "defillama",
      "sourceKey": "Example Protocol|1789171200|12000000|Ethereum",
      "name": "Example Protocol",
      "occurredOn": "2026-09-12",
      "classification": "Protocol Logic",
      "technique": "Price oracle manipulation",
      "amountUsd": 12000000,
      "returnedUsd": null,
      "chains": ["Ethereum"],
      "targetType": "DeFi Protocol",
      "bridgeHack": false,
      "link": "",
      "description": "Example Protocol is listed in DefiLlama's hacks index as a defi protocol incident on Ethereum. The technique was recorded as price oracle manipulation.",
      "published": true,
      "attackers": 0,
      "affected": 0,
      "scannedAt": null
    }
  ]
}

Errors

  • 503The deployment has no database connection.
    { "ok": false, "error": "Not available.", "exploits": [] }
  • 500The read failed.
    { "ok": false, "error": "Not available.", "exploits": [] }

Wallet check

GET/api/exploits/check

Checks one wallet address: whether a threat feed names it, and whether it has sent tokens to an address a feed names.

Parameters

addressquery, required
One address: 0x followed by 40 hex characters, or a base58 address of 32 to 44 characters.

Good to know

  • verdict is one of listed (a feed names this address), affected (it sent tokens to a listed address), exposed (it holds a live approval to one), clear or unknown.
  • clear means the feeds Pavoriz reads do not name the address and nothing Pavoriz has scanned links it to one. It is not a promise that the address is safe.
  • unknown means a lookup did not complete, so there is no result.
  • sentTo lists up to 25 transfers, with the transaction hash when one was recorded. It is what was observed on chain, not proof of a theft.
  • The approvals lookup only runs for a signed in Pavoriz account, so for API callers riskyApprovals is always empty and scannedApprovals is false. exposed therefore does not occur.
Request
curl "https://pavoriz.com/api/exploits/check?address=0x0000000000000000000000000000000000000000"
Response 200
{
  "ok": true,
  "check": {
    "address": "0x0000000000000000000000000000000000000000",
    "listedBy": ["ScamSniffer scam-database (addresses)"],
    "sentTo": [
      {
        "attacker": "0x...",
        "chain": "ethereum",
        "transfers": 2,
        "txHash": "0x..."
      }
    ],
    "riskyApprovals": [],
    "complete": true
  },
  "verdict": "listed",
  "scannedApprovals": false
}

Errors

  • 400The address parameter is missing or empty.
    { "ok": false, "error": "No address was given." }
  • 400The value is not an EVM or base58 address.
    { "ok": false, "error": "That is not an address." }
  • 503The deployment has no database connection.
    { "ok": false, "error": "The database is not configured on this deployment." }
  • 500The read failed. The detail is logged on the server, not returned.
    { "ok": false, "error": "Something went wrong on our side." }
GET/api/dapps/popular

The dApps opened most often through Pavoriz Shield, with a session count each, and one summed row for everything else.

Parameters

limitquery, optional
How many dApps to list. Default 5, clamped to 1 to 20. Send a whole number.

Good to know

  • Counts are all time sessions that the Shield recorded and a Pavoriz page mirrored to the server. They are not the dApp's own user numbers.
  • icon is a path on pavoriz.com for dApps Pavoriz ships art for, and null otherwise. name falls back to the host.
  • others sums every dApp that did not make the list.
Request
curl "https://pavoriz.com/api/dapps/popular?limit=2"
Response 200
{
  "ok": true,
  "top": [
    {
      "host": "app.uniswap.org",
      "name": "Uniswap",
      "icon": "/images/activity-icons/uniswap-white.svg",
      "url": "https://app.uniswap.org",
      "sessions": 42
    },
    {
      "host": "example-dapp.xyz",
      "name": "example-dapp.xyz",
      "icon": null,
      "url": "https://example-dapp.xyz",
      "sessions": 17
    }
  ],
  "others": { "dapps": 12, "sessions": 31 }
}

Errors

  • 503The deployment has no database connection.
    { "ok": false, "error": "The database is not configured on this deployment." }
  • 500The read failed. The detail is logged on the server, not returned.
    { "ok": false, "error": "Something went wrong on our side." }

Shield and the launcher

Pavoriz Shield is a browser extension. The Pavoriz site talks to it with window.postMessage, and a content script in the extension relays those messages to its background worker.

That content script only runs on Pavoriz's own origins (pavoriz.com and its subdomains, plus local and preview hosts used in development). A page on any other site cannot reach the extension this way, so the protocol below is documented for reference and is not an integration point for third party sites.

Message shape

Page to extension
window.postMessage(
  { __pavoriz: true, dir: "to-ext", type: "LAUNCH_DAPP", url: "https://app.uniswap.org" },
  "*"
);
Extension to page
{ __pavoriz: true, dir: "to-page", type: "LAUNCH_ACK", url: "https://app.uniswap.org", ok: true }

Page to extension

  • PING

    Asks the extension to announce itself again.

  • LAUNCH_DAPPurl

    Opens the dApp in a monitored tab and enrols its host in always-on protection. Answered with LAUNCH_ACK.

  • GET_HISTORY

    Asks for the stored activity history. Answered with HISTORY.

  • GET_SESSIONS

    Asks which dApp tabs are under the Shield. Answered with SESSIONS.

  • GET_THREATS

    Asks for the extension's cached threat list. Answered with THREATS.

  • GET_PROTECTED

    Asks for the always-on protection state. Answered with PROTECTED.

  • SET_AUTO_PROTECTenabled

    Turns always-on protection on or off.

  • FORGET_HOSThost

    Stops guarding one dApp on direct visits.

  • CLEAR_PROTECTED

    Drops every enrolled dApp.

  • FOCUS_TABtabId

    Brings a monitored tab to the front.

  • END_SESSIONtabId

    Closes a monitored tab.

Extension to page

  • SHIELD_READY version
  • LAUNCH_ACK url, ok
  • EVENT event
  • HISTORY events
  • SESSIONS sessions
  • THREATS threats (addresses, hosts)
  • PROTECTED autoProtect, sites

The typed client for all of this is lib/pavorizShield.ts in the Pavoriz web app.

The /embed/launcher route

When somebody clicks the Shield badge on a protected dApp, the extension overlays an iframe of /embed/launcher from the Pavoriz origin it has on record. The page renders the same dApp launcher as /dapp on a transparent background and reports the choice to its parent window:

Launcher to parent window
{ __pavorizLaunch: true, type: "LAUNCH", url: "https://app.uniswap.org" }
{ __pavorizLaunch: true, type: "CLOSE" }

The extension ignores these messages unless they come from that recorded Pavoriz origin. The route is built for this overlay and is not offered as an embed for other sites.

Not part of the public API

Everything else under /apiserves the Pavoriz app itself and can change without notice. That includes routes tied to a browser's Pavoriz account (revoke, scans, auto revoke, trust checks, votes, activity mirroring), routes that write (incident reports, spotlight applications), the administrator routes and scheduled jobs. Please do not build on them.

Request API access

The endpoints above are open today. If you plan to call them at volume, or need data they do not cover, tell us what you are building.

0 / 2000