API reference

Start scans and read results as JSON. There's also an OpenAPI spec.

Authentication

Create a key on your account page and send it as a bearer token. Keys are shown once, so store yours somewhere safe. Revoking one takes effect immediately.

Authorization: Bearer gp_...

The base URL is https://ghostprint.tools/api/v1.

Quick start

export GHOSTPRINT_KEY="gp_..."
export BASE="https://ghostprint.tools/api/v1"
export MINT="AcfayFzfssZuuedUcoRP2NT8tJa98WKojPdjtjFKpump"

# Start a scan
curl -X POST "$BASE/scans" \
  -H "Authorization: Bearer $GHOSTPRINT_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"mint\":\"$MINT\"}"

# Poll until status is "done"
curl "$BASE/scans/$MINT" -H "Authorization: Bearer $GHOSTPRINT_KEY"

POST /scans

Starts a scan, or joins one already running. A token that already has a result returns straight away and uses none of your limit.

{ "mint": "AcfayFzfssZuuedUcoRP2NT8tJa98WKojPdjtjFKpump" }
StatusMeaning
200A result exists. status is done
202Queued or running. Poll GET /scans/{mint}
400invalid_mint
429scan_limit_reached or too_many_requests. See Retry-After
503queue_full or free_capacity_reached. See Retry-After
{
  "mint": "AcfayFzfssZuuedUcoRP2NT8tJa98WKojPdjtjFKpump",
  "status": "queued",
  "used_scan_credit": false,
  "scans_remaining_this_hour": 9
}

GET /scans/{mint}

Returns progress, then the full report. Polling every few seconds is plenty.

{
  "mint": "AcfayFzfssZuuedUcoRP2NT8tJa98WKojPdjtjFKpump",
  "status": "running",
  "progress": { "step": "Scoring links", "done": 0, "total": 0 }
}

When status is done, the response has a report. If it's failed, it has an error message, and any credit used has been returned. A 404 with not_scanned means no scan exists yet.

Report fieldContents
tokenName, symbol, image, decimals and supply
buyersThe first wallets, in order, with their buy transaction and supply share
linksEach finding, with its type, wallets, confidence, reasons and transactions
flagsWallets funded within 5 minutes of each other
clustersGroups joined by medium or high confidence links
fundersSenders that paid two or more early wallets
excludedFundersProgram-owned senders left out of links
coverageWhat the scan read, and where it stopped
summaryPlain-English headline and points, each citing its links

GET /me

Your tier, how much of your hourly limit is used, and your credit balance.

{
  "wallet": "...",
  "tier": "account",
  "scans_per_hour": 10,
  "scans_used_this_hour": 2,
  "scan_credits": 0
}

Errors and limits

Errors share one shape. code is stable, so branch on that and not on the message.

{ "error": { "code": "scan_limit_reached", "message": "..." } }

Each key can make 120 requests a minute. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining. See Limits and credits for scan limits.