Papertrail

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.

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.

MethodPathKeyWhat it does
GET/api/v1/receipt/<mint>optionalStored result for a token. 404 when it hasn't been checked. Never runs a check.
POST/api/v1/checkrequiredBody {"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/libraryoptional?q= (name, ticker or mint) &verdict= RED | CAUTION | CLEAN | UNCHECKED &limit= (max 50) &cursor= (from nextCursor).
POST/api/v1/keysnoneNew key, shown once. Made from this page; linked to your wallet if you're signed in on /tiers.
GET/api/v1/keysrequiredYour key (and others linked to the same wallet): prefix, label, dates. Never the secret.
DELETE/api/v1/keys/<prefix>that keyRevokes the key. Only the key itself can do this.

The result

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

WhatLimit
Live checks, Free5 a day per key
Live checks, Holder10 a day per wallet
Live checks, Whale50 a day per wallet
Reads with a key60 a minute per key
Reads without a key20 a minute per connection
New keys3 a day per connection
Library page sizeup 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.

HTTPcodeMeaning
400bad_requestThe body isn't JSON.
400bad_mintThat isn't a Solana token address.
401invalid_keyThe key is malformed, unknown or revoked.
401key_requiredThis endpoint needs a key (live checks, key list, revoke, MCP).
403forbiddenA key can only revoke itself.
404not_foundNo stored check, unknown check id, or no such endpoint.
405method_not_allowedWrong HTTP method for this endpoint.
413too_largeRequest body too large.
415bad_content_typePOST bodies must be Content-Type: application/json.
429rate_limitedToo many requests this minute. Wait for Retry-After.
429quota_exceededToday's live checks for this key's tier are used up. resetAt is the next UTC midnight.
429site_budgetLive checks are paused site-wide for today. Stored receipts still work.
429key_limitToo many new keys from this connection today.
500internalSomething went wrong on our side. Try again in a minute.