# markedet package check

> Pay-per-call API for coding agents: before `pip install` or `npm install`, check whether each package exists, its age, downloads, known vulnerabilities (OSV) and typosquat/slopsquat signals. Verdict ok, caution or block with reasons. PyPI and npm.

Price: $0.002 per unique package in USDC on Base mainnet (eip155:8453) via x402 v2 (scheme exact). 1 to 500 packages per call. No account or API key. Invalid input is a free 422.

Free trial: First 50 packages per payer wallet are free: sign the payment as usual; the server verifies the signature (that identifies the wallet) and does not settle while the wallet is within the free 50. A call is free only if it fits in what is left (use limit to fit). About 50: the counter is in memory and resets when the server restarts. The wallet must hold enough USDC for the signature to verify; nothing moves.

Lockfile input: send `{"lockfile": "<raw file>"}` (requirements.txt, poetry.lock, uv.lock, Pipfile.lock, package-lock.json, pnpm-lock.yaml, yarn.lock; auto-detected; optional `lockfile_format`, `include_dev`, `limit`). One verdict per unique package in `results`, plus a compact `verdicts` list with line numbers where the format has them. `POST /parse` is free and returns the unique packages and the exact quote.

Latency: Measured, not promised. GET /demo checks a fixed 79-package package-lock.json and reports check_wall_s on this host right now; /stats has median and p95 of real /check calls since the last restart. Lookups are cached for about 10 minutes, so a warm run is much faster than a cold one (first call after a restart or after idle).

## Endpoints

- [POST /check](https://package-check-qy40.onrender.com/check): paid. Body `{"packages": [{"ecosystem": "pypi", "name": "reqeusts"}, {"ecosystem": "npm", "name": "lodash", "version": "4.17.15"}]}` or `{"lockfile": "requests==2.32.3\nreqeusts\nflask>=3\n", "lockfile_format": "requirements.txt"}`
- [POST /parse](https://package-check-qy40.onrender.com/parse): free, parses a lockfile and quotes the price
- [GET /demo](https://package-check-qy40.onrender.com/demo): free, checks a fixed bundled package-lock.json (79 packages) and shows the measured latency
- [GET /openapi.json](https://package-check-qy40.onrender.com/openapi.json): OpenAPI 3.1 with x-payment-info
- [GET /selftest](https://package-check-qy40.onrender.com/selftest): free known-answer self-test
- [GET /stats](https://package-check-qy40.onrender.com/stats): calls and latency since last restart
- [GET /.well-known/x402](https://package-check-qy40.onrender.com/.well-known/x402): x402 discovery
- [MCP https://package-check-qy40.onrender.com/mcp](https://package-check-qy40.onrender.com/mcp): remote MCP (streamable HTTP), paid tool `check_packages` (x402 MCP transport), free tool `selftest`
- [Guide](https://package-check-qy40.onrender.com/guide): before pip install, catching hallucinated and typosquatted packages (signals, limits, known-answer set)
- [A2A agent card](https://package-check-qy40.onrender.com/.well-known/agent-card.json): `POST https://package-check-qy40.onrender.com/a2a` message/send answers with price and how to pay

## Paid call

1. `curl -si -X POST https://package-check-qy40.onrender.com/check -H 'content-type: application/json' -d '{"packages": [{"ecosystem": "pypi", "name": "reqeusts"}, {"ecosystem": "npm", "name": "lodash", "version": "4.17.15"}]}'` returns 402 with the quote (PAYMENT-REQUIRED header).
2. Sign it with an x402 client (Python `x402`, TypeScript `@x402/fetch`) and resend with header `PAYMENT-SIGNATURE`.
3. The 200 response carries results and a PAYMENT-RESPONSE header with the settlement transaction.

## Limits

- PyPI and npm only. A lockfile is parsed for names and exact versions; nothing is resolved or installed. In requirements.txt a range (requests>=2) is checked against the latest release; git, URL, path and workspace entries are skipped and listed.
- Price is per unique package after parsing; at most 500 unique packages per call (POST /parse is free and shows the count).
- Free trial: about 50 packages per payer wallet; the counter lives in memory and resets when the server restarts.
- Latency is measured, not promised: see LATENCY in the guide and live numbers at /stats. Cold lookups of hundreds of packages take seconds.
- Typosquat detection by name compares against the top 2000 packages per ecosystem.
- A clean ok is not a guarantee: a new malicious package with no advisory yet can pass.
- Live registry data; verdicts can change over time.
- Runs on Render Free: after ~15 minutes idle the first call takes ~30-60 s (cold start).

Source (MIT): https://bitbucket.org/markedet/package-check
