Undersigned

The Undersigned API

Every signed review, publisher proof, store rating, rating burst and payment board, as JSON. Read it free within limits; a pass lifts them. The ledger itself is on Solana, so anyone can also read it directly.

Free, no key
1,000

requests a day per address (30 a minute). Lists return the top 20 rows.

Open dataset: every record and score, rebuilt every few minutes.

Pass
100,000

requests over 30 days, 600 a minute, every endpoint. 0.0607 SOL or 369 SKR (332 SKR with a Seeker Genesis Token). Paying again adds another pass.

Or pay per call (for agents): 1.0E-5 SOL or 0.06 SKR a call, from 0.001 SOL or 6.0 SKR, valid a year. POST /v1/checkout with {"calls": N}, pay, redeem.

Publisher plan
0.0607 SOL

a month for one app (369 SKR; 332 with a Genesis Token), up to 12 months a payment. For the app's proven publisher: its report (reviews waiting for an answer, the store rating's trend, bursts, certificate and permission changes, scores by version, its category's benchmark), webhooks and the API. Get it

Data plan
2,000,000

requests over 30 days, 3,000 a minute, and CSV exports of the store's history (changes, found, ratings, apps). 0.607 SOL or 3,690 SKR. Get it

Getting a key
  1. Pay with the button above from a phone wallet, or scan the QR code on a computer. The payment carries the pass reference, so it is found on-chain.
  2. Redeem: POST /v1/keys with the payment's signature and the paying wallet's signature of the message Undersigned API key for <payment signature>. Only the wallet that paid can redeem it. Or start with POST /v1/checkout for a one-time secret instead of a message signature.
  3. Call with Authorization: Bearer <key>. GET /v1/keys/me shows what is left.

Quickstart

No key, no sign-up. Every answer is JSON; add ?pretty=1 to read it.

curl "https://undersigned.provenby.dev/v1/apps?q=wallet&limit=5"
curl "https://undersigned.provenby.dev/v1/apps/com.solflare.mobile"
curl "https://undersigned.provenby.dev/v1/apps/com.solflare.mobile/reviews?sort=newest"
curl -H "Authorization: Bearer YOUR_KEY" "https://undersigned.provenby.dev/v1/watch?days=7"

JavaScript

const r = await fetch("https://undersigned.provenby.dev/v1/apps/com.solflare.mobile");
const app = await r.json();
console.log(app.signed.mean, app.signed.counted_reviews, app.store_rating);

Python

import requests
app = requests.get("https://undersigned.provenby.dev/v1/apps/com.solflare.mobile").json()
print(app["signed"]["mean"], app["signed"]["counted_reviews"])

Answers: 200 data · 402 needs a pass (the body carries the price and Solana Pay links) · 429 over the limit (Retry-After) · 404 unknown. Send a User-Agent header from scripts.

Ask the docs

Ask how to do something with this API or MCP. Answered by AI from the published docs only; check the docs it points to.

Use it from an AI agent (MCP)

This API is also a Model Context Protocol server at https://undersigned.provenby.dev/mcp. Add the URL to your agent; nothing to install. Its tools only read: search apps, get an app's scores, read its reviews, bursts and wallets. No tool writes, signs or submits a review.

Claude Code

claude mcp add --transport http undersigned https://undersigned.provenby.dev/mcp

Cursor and other clients (mcp.json)

{
  "mcpServers": {
    "undersigned": {
      "url": "https://undersigned.provenby.dev/mcp",
      "headers": { "Authorization": "Bearer YOUR_KEY" }
    }
  }
}

Claude (web or desktop): Settings, Connectors, add a custom connector with the URL above. The header line is only needed for the tools marked as needing a pass.

Free

GET /v1/apps/{pkg}
One dApp: signed score, store details and rating, publisher, payments
GET /v1/apps/{pkg}/bursts
Review and store-rating bursts with sparklines
GET /v1/apps/{pkg}/summary
Suggested summary, by AI, of an app's counted reviews: the points most mentioned, each with its count and review ids
POST /v1/ask
Docs helper: ask how to use this API or MCP; answered by AI from the published docs only
GET /v1/changelog
What changed in the API and MCP, newest first
POST /v1/checkout
Start a purchase: a secret, and Solana Pay URLs whose memo commits to it. Body {"calls": N} for pay-per-call credits instead of a pass
GET /v1/dataset.json
The open dataset: every record, every app's signed score, every signer's public facts (rebuilt every few minutes)
GET /v1/health
Indexer status: last syncs, last error, skipped transactions, hook failures
POST /v1/help
In-app help: a question about how reviews are collected, checked, weighted and shown, answered by AI from the integrity policy only. Body {question, lang}
POST /v1/keys
Redeem a pass payment for an API key
GET /v1/keys/me
Your pass: requests left and end date
GET /v1/openapi.json
This API's description
POST /v1/pay/review
Solana Pay transaction request: body {account}; query package, rating, tags (comma-separated), text
GET /v1/pay/review
Solana Pay transaction request: label and icon
GET /v1/payments/app/{pkg}/series
One dApp's payments per day|week|month across its confirmed and found wallets
GET /v1/payments/chart/app/{pkg}.svg
Chart: one dApp's payments over time, as SVG
GET /v1/payments/chart/store.svg
Chart: payments into dApp wallets over a window, confirmed and found stacked, as SVG
GET /v1/payments/chart/top.svg
Chart: the top dApps by USD received in a window (n, include), as SVG
GET /v1/payments/series
Payments into every dApp wallet per day|week|month over a window, confirmed and found apart
GET /v1/pricing
Pass price and how to pay
POST /v1/publisher/plan
Redeem a publisher-plan payment: {signature, package, secret or message_signature}. Only a proven publisher of the package, paying from that wallet
GET /v1/publisher/{pkg}/plan
Whether an app has a live publisher plan, until when, and the price
GET /v1/records/{id}
One record by id (signature or signature:n)
GET /v1/relay/info
Quick reviews: the fee payer, a recent blockhash and the limits
POST /v1/relay/review
Quick reviews: submit a transaction signed by the phone's app key; the relayer adds the fee payer's signature. Body {tx: base64}
GET /v1/reviews/chart/apps.svg
Chart: the dApps with the most reviews for a source and window (n, category), mean stars and change, as SVG
GET /v1/reviews/chart/categories.svg
Chart: store categories by reviews for a source and window, mean stars and change, as SVG
GET /v1/reviews/chart/series.svg
Chart: reviews per day|week|month and their mean stars over a window for a source (category, package), as SVG
GET /v1/reviews/chart/stars.svg
Chart: the star distribution of a source over a window (category, package), as SVG
POST /v1/rpc
JSON-RPC read proxy for the app (one call a request, read and send methods only): the keyed provider's key stays on the server; 120 a minute and 20,000 a day per network
GET /v1/stats
Ledger totals
GET /v1/tags
Review tag vocabulary with counts
POST /v1/tx/record
Build an unsigned helpful vote, reply or flag: {account, kind: up|reply|flag, target, text?, reason?}
POST /v1/tx/review
Build an unsigned review transaction for a browser wallet: {account, package, rating, tags[1-3], text?}

Free within the limits above

POST /mcp
Model Context Protocol (Streamable HTTP, JSON-RPC): read-only tools for AI agents. Add this URL to Claude, Cursor or any MCP client
GET /v1/apps
Catalogue search: q, category, sort (name|signed|updated); or packages=a,b,c for several apps at once
GET /v1/apps/{pkg}/reviews
Signed reviews with every signal; limit, offset, sort (newest|helpful|skr|sol: stake as read when each review appeared; never changes a score)
GET /v1/digest
This week's digest: store-wide rating bursts and app updates in plain words, by AI from the facts seen (Pro wallet via ?wallet=, or a pass / credits key)
GET /v1/leaderboard
Rankings: metric (signed_score|signed_reviews|store_rating|store_reviews|revenue|payers|growth), category
GET /v1/payments
Payments board: confirmed treasuries by USD received
GET /v1/payments/categories
Store categories ranked by USD received in a window, each with its change against the window before and its three leaders
GET /v1/payments/found
Treasuries found in app code, not confirmed by the publisher: a separate list, by app name, never ranked with the board
GET /v1/payments/found/trends
Store-wide monthly payments into wallets found in app code (not confirmed)
GET /v1/payments/found/{pkg}
One app's wallets found in app code, with full-history analytics: dates, monthly series, new and returning payers, concentration
GET /v1/payments/leaderboard
dApps ranked by USD received in a window (7d|30d|90d|1y|all) across confirmed treasuries and found wallets (include=confirmed|found|all; rail=sol|skr|usdc to count one rail only), with rails, payers, new payers and a weekly series each
GET /v1/payments/patterns
Rails, repeat payers, concentration, payment sizes, and payments by hour and weekday in a window
GET /v1/payments/summary
The analytics dashboard in one answer: leaderboard, categories, trending, patterns, treasuries, series
GET /v1/payments/treasuries
Wallets ranked by USD received in a window, each with the dApps it was listed for or found in
GET /v1/payments/trending
dApps rising, falling and new by USD received, this window against the one before
GET /v1/records
Every decoded record, newest first; filter by type, package, signer, since, until; page with before
GET /v1/records/{id}/translation
Suggested translation of a review's or reply's text into lang (Pro wallet via ?wallet=, or a pass / credits key)
GET /v1/reviews/analytics
Review analytics for one source (source=store|all|organic|pro|promoted|quick|other|ours): reviews, mean, stars, replied and short shares, categories, top apps and a series per day|week|month over a window (7d|30d|90d|1y|all), optionally for one category or package
GET /v1/reviews/analytics.csv
The same review analytics as CSV (categories, apps, series)
GET /v1/reviews/store.csv
Raw rows of the dApp Store reviews read so far, one a line: package, name, category, stars, created, words, from_skr_name, publisher_replied. No text and no wallet: the words stay the store's and the reviewer's.
POST /v1/translate
Suggested translation, by AI, of a store review's text (up to 1,000 characters) into lang. Body {text, lang, wallet}. Pro or a key
POST /v1/translate/reply
Your reply draft, put by AI into the language of the review it answers. Body {reply, review_id or review_text, wallet}. Pro or a key; you check it and sign it as your own words
GET /v1/wallets/{address}
A wallet: attested device, stake weight, standing, reviews; full=1 with a pass lists its records

With a pass

GET /v1/apps/{pkg}/payments
Payments received, with a monthly series
GET /v1/apps/{pkg}/similar
Copy-paste findings among its reviews
GET /v1/apps/{pkg}/store-ratings
Daily store star-count snapshots
GET /v1/apps/{pkg}/versions
Signed score per version
GET /v1/changes
Changes seen across the store: new releases (any listing's updated date moved), version codes and signing certificates; since=epoch seconds
GET /v1/export/{dataset}
Data plan: CSV export of a dataset (ratings | changes | apps | found)
POST /v1/hooks
Create a webhook: {url, packages[], events[] (review|reply|store_note|flag|claim|fixed|follow_up|burst|version|release|certificate|digest)}; returns its signing secret once
GET /v1/hooks
Your webhooks
DELETE /v1/hooks/{id}
Delete one of your webhooks
GET /v1/hooks/{id}/deliveries
The last 100 delivery attempts to one of your webhooks, with the receiver's status
POST /v1/hooks/{id}/test
Send a signed test ping to one of your webhooks now; returns the receiver's status
GET /v1/publisher/{pkg}/report
Publisher plan: the app's report (waiting reviews, rating trend, bursts, changes, versions, category benchmark). A publisher key for that app
GET /v1/watch
Store-wide rating bursts in the last N days (days=3)

Full description: OpenAPI · Raw price and pay links: /v1/pricing · Store data shown here belongs to the Solana dApp Store.