API · MCP · read-only
The paper trail, as an API.
Stored receipts, live on-chain checks and the library for any Solana token, over HTTP or as tools for Claude, Cursor and other MCP clients. JSON only. Nothing here signs or sends a transaction.
Get a key
Keys are free. Reads work without one at a lower rate; live checks and MCP need one. Sign in on /tiers first and the key follows your wallet's tier.
Shown once. Copy it now; we only keep a hash and can't show it again.
Quick start
Send the key as Authorization: Bearer <key> or X-API-Key: <key>.
Stored receipt (no key needed)
curl https://papertrailsol.xyz/api/v1/receipt/DFMt2FyLpB6ekPNAzVErLXgpSnJ9CRf1VnxBAkTLpump
Start a live check
curl -X POST https://papertrailsol.xyz/api/v1/check \ -H "Authorization: Bearer pt_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"mint":"DFMt2FyLpB6ekPNAzVErLXgpSnJ9CRf1VnxBAkTLpump"}'Poll the check
curl https://papertrailsol.xyz/api/v1/check/chk_… -H "Authorization: Bearer pt_YOUR_KEY"
Search the library
curl "https://papertrailsol.xyz/api/v1/library?q=pump&verdict=RED&limit=20" -H "X-API-Key: pt_YOUR_KEY"
Revoke a key
curl -X DELETE https://papertrailsol.xyz/api/v1/keys/<prefix> -H "Authorization: Bearer pt_YOUR_KEY"
Endpoints
Base URL https://papertrailsol.xyz. GET endpoints send Access-Control-Allow-Origin: *; POST and DELETE don't, so call them from a server.
| Method | Path | Key | What it does |
|---|---|---|---|
| GET | /api/v1/receipt/<mint> | optional | Stored result for a token. 404 when it hasn't been checked. Never runs a check. |
| POST | /api/v1/check | required | Body {"mint"}. Starts a live check, or joins the one already running. A check from the last few hours comes back done (no quota used). 202 {id, status, url} while running. |
| GET | /api/v1/check/<id> | optional | {id, status: running | done | failed, url, result when done}. |
| GET | /api/v1/library | optional | ?q= (name, ticker or mint) &verdict= RED | CAUTION | CLEAN | UNCHECKED &limit= (max 50) &cursor= (from nextCursor). |
| POST | /api/v1/keys | none | New key, shown once. Made from this page; linked to your wallet if you're signed in on /tiers. |
| GET | /api/v1/keys | required | Your key (and others linked to the same wallet): prefix, label, dates. Never the secret. |
| DELETE | /api/v1/keys/<prefix> | that key | Revokes the key. Only the key itself can do this. |
The result
verdict: the on-chain stamp, RED, CAUTION, CLEAN (no flags found, not a safety rating) or UNCHECKED.score: 100 minus 30 per red flag and 10 per caution flag, floored at 0. A tally, not advice.bundlePct: % of supply the launch bundle took.devSells: % of supply the dev wallets sold, through the trading history read.freshWalletHandoff: launch tokens passed through fresh relay wallets.washPct: % of swap volume that looks washed.tech: the verdict on what the project claims (REAL, PARTIAL, LARP, or a specific reason such as NO PRODUCT or NEEDS LOGIN) with evidence lines.checkedAt: when the chain was read. Every number is as of then.
Example (illustrative values)
{ "mint": "DFMt2FyLpB6ekPNAzVErLXgpSnJ9CRf1VnxBAkTLpump", "symbol": "OPTIMUS", "name": "Optimus", "verdict": "RED", "score": 40, "flags": [ { "code": "insider_dump", "level": "red", "section": "trading", "text": "Insiders sold 24% of supply within 15 minutes." } ], "bundlePct": 31.2, "devSells": 4.1, "freshWalletHandoff": true, "washPct": 12.5, "tech": { "verdict": "NO PRODUCT", "evidence": [ "No working product was found to test." ] }, "checkedAt": "2026-10-24T12:00:00.000Z", "url": "https://papertrailsol.xyz/c/DFMt2FyLpB6ekPNAzVErLXgpSnJ9CRf1VnxBAkTLpump"}MCP
Remote MCP server over Streamable HTTP at https://papertrailsol.xyz/mcp, same key. Tools: check_token {mint} (waits up to about 25 s, then returns the result or a status URL), get_receipt {mint}, search_library {q?, verdict?, limit?}.
Claude Desktop (claude_desktop_config.json, via mcp-remote)
{ "mcpServers": { "papertrail": { "command": "npx", "args": [ "-y", "mcp-remote", "https://papertrailsol.xyz/mcp", "--header", "Authorization:${PAPERTRAIL_AUTH}" ], "env": { "PAPERTRAIL_AUTH": "Bearer pt_YOUR_KEY" } } }}Cursor (~/.cursor/mcp.json)
{ "mcpServers": { "papertrail": { "url": "https://papertrailsol.xyz/mcp", "headers": { "Authorization": "Bearer pt_YOUR_KEY" } } }}Claude Code
claude mcp add --transport http papertrail https://papertrailsol.xyz/mcp \ --header "Authorization: Bearer pt_YOUR_KEY"
Limits
| What | Limit |
|---|---|
| Live checks, Free | 5 a day per key |
| Live checks, Holder | 10 a day per wallet |
| Live checks, Whale | 50 a day per wallet |
| Reads with a key | 60 a minute per key |
| Reads without a key | 20 a minute per connection |
| New keys | 3 a day per connection |
| Library page size | up to 50 |
Daily limits reset at 00:00 UTC. A 429 carries Retry-After (seconds) and resetAt (ISO time). A recent stored check is returned without using a live check.
Errors
Every error is JSON: {"error": "…", "code": "…"}, plus resetAt on 429.
| HTTP | code | Meaning |
|---|---|---|
| 400 | bad_request | The body isn't JSON. |
| 400 | bad_mint | That isn't a Solana token address. |
| 401 | invalid_key | The key is malformed, unknown or revoked. |
| 401 | key_required | This endpoint needs a key (live checks, key list, revoke, MCP). |
| 403 | forbidden | A key can only revoke itself. |
| 404 | not_found | No stored check, unknown check id, or no such endpoint. |
| 405 | method_not_allowed | Wrong HTTP method for this endpoint. |
| 413 | too_large | Request body too large. |
| 415 | bad_content_type | POST bodies must be Content-Type: application/json. |
| 429 | rate_limited | Too many requests this minute. Wait for Retry-After. |
| 429 | quota_exceeded | Today's live checks for this key's tier are used up. resetAt is the next UTC midnight. |
| 429 | site_budget | Live checks are paused site-wide for today. Stored receipts still work. |
| 429 | key_limit | Too many new keys from this connection today. |
| 500 | internal | Something went wrong on our side. Try again in a minute. |