Developers
SelfAssay connector
A public, read-only view of SelfAssay’s compound evidence for AI assistants and developers, over MCP and REST — no account and no key required, and it serves no member data. Account linking opens to all SelfAssay members thirty days after we notify members by email and in the app (date to be announced). It lets a member connect their own account, read-only — the only way an assistant ever sees anything of theirs.
What this is
SelfAssay aggregates first-hand community reports, PubMed-linked studies, registered clinical trials, and a knowledge graph of compound-outcome relationships into a per-compound dossier. One endpoint serves two tiers with different rules, and the difference is the whole privacy story:
- The public tier exposes the summary level of that corpus — the same material published on selfassay.com — so an assistant can answer a question about a supplement, peptide, or other compound with cited, sized evidence instead of a guess. It is the default, and everything in the tools table below belongs to it.
- The member tieris opt-in, read-only, and off unless a SelfAssay member has explicitly linked their account. It adds tools that read that member’s own stack, checklist and dossiers. See Member tools.
What is true of the public tier
- Read-only. Every public tool is a lookup. Nothing in this tier writes, and nothing here creates an account.
- No account and no member data.Public tools take no user identity and cannot reach a member’s Vault, stack, notebook, or subscription — not as a policy but as a property of the code: the modules behind them have no import path to a user id, and a test asserts it. A live member credential changes nothing about what a public tool answers — a public result is never personalised. The header is not inert, though: an
Authorizationheader that does not resolve to a live member credential refuses the whole request with401 invalid_token, even when that request only calls a public tool. Send a client key inX-API-Keyand leaveAuthorizationunset. - Summary-level. Grades, counts, ranked effect and adverse-event terms, study and trial counts, and a link to the public dossier. Not a bulk export of the corpus, and never dosing guidance.
- Deterministic. Results are reads of precomputed tables. No model runs at request time, so the same arguments return the same answer until the underlying data is rebuilt.
- Not medical advice. Every successful result carries a provenance block with the disclaimer, what the grades mean, and a link back to the dossier. Keep it with the result.
What stays true of both tiers
- No model runs at request time on either tier, so a linked account does not put a member’s data through an inference call on our side.
- Never dosing guidance.We publish none. A member’s own recorded dose comes back from their own stack because it is their record, not a recommendation.
- A failed read is reported as a failure. Neither tier answers a safety or stack question with an empty result when the source could not be read.
Endpoints
MCP
POST https://selfassay.com/api/mcp
Streamable HTTP. The server answers every request with a single application/json object — it never opens an SSE stream, so GET and DELETE on this path return 405. It is stateless: no session is minted, no Mcp-Session-Id is issued or required, and each request is independent. Protocol revisions answered: 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26. Send the revision you speak in the MCP-Protocol-Version header; without it, 2025-03-26 is assumed.
REST
https://selfassay.com/api/public/v1 — the same tools as plain HTTP JSON, for clients that do not speak MCP. The OpenAPI document is authoritative for paths, parameters and response shapes: https://selfassay.com/api/public/v1/openapi.json.
Agent brief
A short, fetchable brief written for the assistant rather than the integrator — transport rules, per-tool guidance, worked recipes, and what not to say: https://selfassay.com/connectors/muse.md.
Public tools
Rendered from the live registry, so this list is what the endpoint serves with no credential at all. Full descriptions and argument schemas come back from tools/list and are in the OpenAPI document. Member tools appear in tools/list too, so an assistant can discover what linking unlocks; they are listed below and refuse without a linked account.
| Name | Title | What it returns | Parameters |
|---|---|---|---|
| search_compounds | Search compounds | Find compounds in SelfAssay's public index by name, brand name, alias or partial name, and get each one's canonical slug. | query (string, required), limit (integer, optional) |
| get_compound_evidence | Get compound evidence | Everything SelfAssay publishes about one compound: what the community reports, what the research says, and how the two compare. | compound (string, required) |
| compare_compounds | Compare two compounds | Put two compounds side by side: the same evidence projection for each, plus the purposes they are both graded for. | a (string, required), b (string, required), goal (string, optional) |
| list_goals | List rankable purposes | Lists the purposes SelfAssay can rank compounds for — the community outcome taxonomy (e.g. Sleep Quality & Insomnia, Focus & Cognition, Weight Management & Appetite). | none |
| find_compounds_for_goal | Find compounds reported for a goal | Returns the compounds with the strongest COMMUNITY-REPORTED outcome grades for one purpose, best grade first and then by report volume. | goal (string, required), limit (integer, optional) |
| check_interactions | Check a combination for documented flags | Screens a list of 2-10 substances — supplements, peptides, nootropics, or prescription medications, by generic or brand name — for DOCUMENTED combination flags. | compounds (array, required) |
| get_research | Published research for a compound | Returns the published-evidence picture SelfAssay holds for one compound: per-purpose research verdicts (what the literature concluded for each use) with the PubMed records that decided them, recent PubMed-linked studies, matched registered clinical trials, and preprints. | compound (string, required), limit (integer, optional) |
| get_research_updates | Recent notable research | Returns recent notable research SelfAssay has tracked — new papers, newly registered or updated clinical trials, and new preprints — either site-wide or for one compound, ranked by a precomputed significance score. | compound (string, optional), limit (integer, optional) |
| get_compound_targets | Compound → biological targets | For one compound, the biological targets (biomarkers, proteins, enzymes, pathways, receptors, hormones, tissues) that PubMed abstracts repeatedly associate with it, each with a direction, an evidence tier and PubMed citations. | compound (string, required), limit (integer, optional) |
| find_compounds_by_target | Biological target → compounds | The reverse lookup: given a biological target (a biomarker, protein, enzyme, pathway or receptor such as "mTOR", "BDNF" or "IL-6"), the compounds in SelfAssay's research index that PubMed abstracts associate with it, each with a direction and an evidence tier. | target (string, required), limit (integer, optional) |
Try it
Open a session (legacy revisions)
curl -sS https://selfassay.com/api/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": { "name": "example-client", "version": "1.0.0" }
}
}'Call a tool
curl -sS https://selfassay.com/api/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'MCP-Protocol-Version: 2025-06-18' \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_compound_evidence",
"arguments": { "compound": "bpc-157" }
}
}'The result carries both a plain-text summary a text-only client can show verbatim and a structured payload, plus the provenance block.
Authentication
Public tools need none. Call them with no headers beyond the transport ones and they answer. There is no account to create and no key to obtain for access — a key only raises a ceiling.
Client keys (rate limits only)
An optional client key exists for one reason: an assistant platform calls from a handful of shared egress addresses, so its users would share one anonymous bucket and throttle each other. A key gives a named client its own bucket and its own ceiling. It grants no data that an anonymous caller cannot already read. Present it as X-API-Key: <key> only. To request one, email hi@selfassay.com with the client name and your expected volume.
Authorization: Bearer is reserved for member credentials and is never read as a client key. Anything presented there is treated as an attempt to act for a member: it either resolves to a live credential or the request is refused with 401 invalid_token. It never quietly degrades to anonymous — a member whose token was revoked must hear so, not be served public results as though nothing had changed. If you hold a client key, send it in X-API-Key and leave Authorization unset.
An absent, unknown, or malformed client key is still treated as anonymous rather than rejected, so a misconfigured key never takes the public tier down for you.
Member tools (account linking)
Limited preview: account linking opens to all SelfAssay members thirty days after we notify members by email and in the app (date to be announced). Until then only accounts enabled for testing and platform review can connect; everyone else is told so at sign-in. Everything else in this section is already live: the member tools are listed by tools/list, and the OAuth and discovery endpoints answer normally.
A SelfAssay member can link their account to an assistant. Once they have, that assistant can call a second set of tools that read their own Vault: the compounds in their stack with the dose and schedule they recorded, what is due today and what they have logged, research news matched to their stack, and fuller dossiers.
The member tier is read-only.Every tool on it is a read of the member’s own record. Nothing an assistant does over this connector adds to, changes or removes anything in a member’s stack, checklist, notebook or account, and no scope a member can grant carries write access — the scope table below is the whole vocabulary, and all of it reads.
Linking is per member, per assistant, explicit, and revocable at any time. Nothing is shared before a member approves a specific list of scopes on a SelfAssay consent screen, and revoking takes effect on the next call — credentials are looked up on every request, so there is no token that outlives its grant.
Two ways to connect
1. OAuth 2.1 with PKCE— for an assistant platform connecting on a member’s behalf. Discovery starts at the protected-resource metadata document:
https://selfassay.com/.well-known/oauth-protected-resource/api/mcp
It is also advertised in the WWW-Authenticate header of the 401 a member tool returns without a credential, so a compliant client discovers it without being told. It names the authorization server, whose metadata is at https://selfassay.com/.well-known/oauth-authorization-server. The resource identifier is https://selfassay.com/api/mcp and must be sent as the resource parameter on both the authorization and token requests (RFC 8707) — a token minted for any other audience is refused here. S256 is the only code-challenge method accepted; plain is rejected. Clients that are not pre-registered can register themselves at https://selfassay.com/oauth/register (RFC 7591). Redirect URIs are matched exactly and must be https or a loopback address.
2. A personal access token — for a member wiring up their own client, a self-hosted agent, or a script. The member creates one in Settings → Connected assistants, choosing its scopes and how long it lives, and sends it as Authorization: Bearer sa_pat_…. It is shown once, at creation, and stored here only as a hash.
A raw Supabase session token is never accepted as a connector credential. Session tokens carry no scopes and cannot be revoked per connection, so handing one to an assistant would grant everything the member’s own browser session can do — the opposite of what the consent screen promises.
Scopes
Rendered from the scope contract, which is the same source the consent screen and the member’s settings page render from, and it is the complete list of what a member can be asked for today. A member grants these individually; a tool called without one of its required scopes is refused, not partially answered.
| Scope | What the member is told it allows | What it never includes |
|---|---|---|
| stack:read | See your stack and today's checklist. The compounds in your stack with the dose and schedule you recorded, which of today's doses are logged, and research news matched to your stack (paid plans). | It never receives your private reasons, notes, symptoms, goals, lab results or notebook. |
| medications:screen | Use your medications for interaction checks — without naming them. When you ask for an interaction check, the medications you recorded are included in the screen. | The assistant is never told which medications you take — a flag says "a medication on file", not its name. |
| dossier:read | Open full dossiers on your account. Fuller evidence dossiers than the public summary. On the free plan each new compound counts against your dossier allowance; paid plans are unlimited. | Dossiers opened this way never include dosing guidance. |
Tools
Rendered from the member registry, so this is exactly what the endpoint serves. Every one of these requires a linked account, refuses without one, and only reads; the ones marked paid plans also require an active paid subscription and answer upgrade_required otherwise.
| Name | What it returns | Parameters | Scopes | Plan |
|---|---|---|---|---|
| get_my_plan | Returns the member's SelfAssay plan (free, pro or practitioner), what this connection is permitted to do, and — on the free plan — how much of the free compound-dossier allowance is left, with the upgrade link. | none | All plans | |
| get_my_stack | Returns the compounds in the member's own SelfAssay stack with the dose, unit, frequency, timing and route they recorded, the date they started, and a link to SelfAssay's public evidence page for that compound when one exists. | none | stack:read | All plans |
| get_my_day | Returns the member's dose checklist for one day: which compounds their schedule expects, and which are already logged as taken. | date (string, optional) | stack:read | All plans |
| check_against_my_stack | Screens ONE substance the member is considering against the compounds in their SelfAssay stack and — when the connection allows it — the medications they recorded, using the same deterministic drug-class guard as check_interactions (MAOIs, serotonergic agents, strong stimulants, CNS depressants). | compound (string, required) | stack:read (+medications:screen when granted) | All plans |
| check_my_stack | Screens every pair within the member's own SelfAssay stack — and, when the connection allows it, their recorded medications — through the same deterministic drug-class guard as check_interactions (MAOIs, serotonergic agents, strong stimulants, CNS depressants). | none | stack:read (+medications:screen when granted) | All plans |
| get_my_research_updates | Returns recent notable research — registered trials, published studies and preprints — matched to the compounds in this member's own SelfAssay stack, newest-significant first, each with a link to the source. | limit (integer, optional) | stack:read | Paid plans |
| get_my_dossier | Opens SelfAssay's fuller dossier on one compound: the written-up sections (Snapshot, Literature evidence, Bioactivity & PK, Safety signal) with the grounded claims behind each one, plus the same graded evidence blocks the public tools return. | compound (string, required) | dossier:read | All plans |
What is never shared
No scope exposes free text a member wrote. Their private reasons for taking something, notes, symptoms, goals, decisions, notebook entries, assistant history, lab results, demographics and practitioner client records never leave SelfAssay over this connector, whatever is granted.
Medication names are never sent to an assistant. With medications:screena member’s recorded medications take part in an interaction screen, and a flag that comes from one says “a medication on file” and nothing more. There is no argument, and no combination of calls, that turns a flag back into a drug name. An assistant that asks a member to name their medications, or guesses at one, is working against the design — say the flag and point at the dossier.
A member can also blocklist a compound from assistant answers. A blocklisted item is withheld from every result — the member is told only how many were withheld — while still taking part in the interaction screening behind the scenes, so hiding something never makes a safety check quieter.
Errors
401withWWW-Authenticate: Bearer— no credential was presented. The challenge carriesresource_metadataand thescopethe call needs. Start the linking flow; do not retry the same call unchanged.401witherror="invalid_token"— a credential was presented and is malformed, unknown, expired, revoked or minted for another audience. Refresh if you hold a refresh token; otherwise ask the member to link again. Never fall back to calling the public tools as though the member were anonymous without telling them the link is broken.403witherror="insufficient_scope"— the credential is valid but lacks a scope. The challenge names every scope the operation needs in one go; re-authorize for the union of what you hold and what it names.upgrade_required(a tool error, not an HTTP status) — the tool is on a paid plan and this member is not on one.data.upgrade_urlis where they can change that. Explain the plan, do not report a failure.quota_exceeded— a free allowance is used up.datacarries what was used, the limit, and the upgrade URL.unavailable— a Vault or corpus read failed. This is not an empty stack and not an all-clear. Say the read failed; do not substitute zeros, an older answer, or your own knowledge.429— over the member ceiling below. HonourRetry-After.
Lifetimes, limits and revocation
- Access tokens live 1 hour.
- Refresh tokens live 60 days and rotate on every use. Presenting a rotated refresh token again is treated as theft and revokes the whole grant, so store only the newest one and do not run two refreshes concurrently.
- Personal access tokens live as long as the member chose, up to 365 days.
- Rate limit: 60 requests per minute per member and 60 per token, counted separately from the public ceilings. This limiter fails closed: if it cannot be checked, the call is refused rather than allowed.
- Revocation: a member can revoke a connection, or any single token, from Settings → Connected assistants, and that page also shows when each connection was last used and what it called. Revoking a refresh token revokes the access tokens issued from it. Deleting a SelfAssay account revokes every connection with it. Revocation stops future access; it cannot recall what was already sent to an assistant.
Every member-tool call is recorded as connection, tool name, time and outcome, so the member can see what their assistant did. Arguments and results are never recorded.What a member’s data is used for once an assistant receives it is governed by that assistant’s own privacy policy, not ours. See our Privacy Policy.
Rate limits
120 requests per minute per IP address for anonymous callers; a keyed client gets its own named bucket and ceiling. A linked member has their own, separate ceiling — see Member tools. Over the limit the endpoint returns 429 with a Retry-After header — wait that many seconds and retry rather than retrying immediately. The two surfaces are counted separately: /api/mcp and /api/public/v1 each apply their own per-minute ceiling to the same caller. Do not treat that as extra headroom — spreading one workload across both protocols to get past a limit is the bulk extraction we ask you not to do.
Data and privacy
Public tier
We receive only the tool arguments an assistant sends us — a compound name, a goal, a target. On a public call we do not receive, and cannot ask for, the identity of the person the assistant is answering: no account is involved, no sign-in is possible on this path, and a public call is never linked to a SelfAssay member. Nothing a public tool serves is member data; it is the summary level of material already published on selfassay.com.
Member tier
When — and only when — a member has linked their account, a call carrying their credential is linked to them by definition: that is what the credential is for, and it is what the member approved on the consent screen. Sending their data to an assistant is a disclosure to a separate company at their direction, not a sub-processor of ours; once it arrives, that company’s privacy policy governs it and we cannot recall it. What can leave is bounded by the scopes they granted, and medication names, free-text notes, reasons, symptoms, goals, labs and notebook entries are outside every scope. See Member tools for the full boundary.
Logging
Requests on both tiers are logged without their arguments — timestamp, tool name, outcome, and the caller identity used for rate limiting — for abuse prevention and capacity planning. A member-tier call additionally records which connection made it, so the member can audit their own assistant in Settings. Tool arguments and tool results are not recorded on either tier. See our Privacy Policy.
Acceptable use
- Answer questions people actually ask. Do not enumerate the corpus, walk the compound list, or use the connector to assemble a copy of the dataset — that is bulk extraction, and it is not permitted.
- Cache responsibly. Results change slowly; re-requesting the same compound on every turn wastes your budget and ours.
- Keep the disclaimer and the dossier link with any result you redistribute, quote, or display. A grade shown without what it means is a misleading grade.
- Present results as evidence, not instruction. Do not turn a result into dosing, a protocol, or a recommendation to start or stop anything, and do not describe the absence of an adverse-event flag as safe or cleared.
- Attribute to SelfAssay, and do not present our summaries as your own clinical assessment.
- With a linked account, act only for the member who linked it. Use what you receive to answer that member, in that conversation. Do not retain it beyond what you need to do so, do not pool it into a dataset, and do not use it to train or fine-tune a model.
- Never ask a member to tell you the medications we declined to name, and never guess at one. A flag that says “a medication on file” is the whole answer.
We may rate-limit, suspend, or block a client whose traffic looks like extraction rather than use. Access is provided as-is and may be changed or withdrawn.
Health disclaimer
SelfAssay is a personal-research and decision-support tool. It is not a medical device, and it does not diagnose, treat, cure, or prevent any disease. Content, grades, summaries, interaction checks, lab interpretations, experiment verdicts, and assistant answers are for informational purposes only and are not medical, pharmacological, or professional advice.
Using the Service does not create a doctor-patient, pharmacist-patient, or other professional relationship. Always seek the advice of a licensed clinician or pharmacist before starting, stopping, or changing any supplement, peptide, medication, or routine, especially if you are pregnant or breastfeeding, have a medical condition, or take prescription drugs. Never disregard professional medical advice or delay seeking it because of something you read on the Service. If you think you may have a medical emergency, call your doctor or emergency services immediately. You are solely responsible for your own decisions and outcomes.
Grades run A (strongest signal) through F (weakest); X means not yet rated. A Benefit grade summarises what first-hand reporters said they experienced and is not a measure of clinical efficacy. The adverse-event signal is a separate observational read of what reporters said happened to them — a low signal is not a finding of safety. Full terms are in our Terms of Service.
Support
Questions, an API key request, a bug in a tool result, or a data-accuracy report: email hi@selfassay.com, or use the form on our Support page. We usually reply within one business day.