← Back to Search

API Documentation

Integrate priorwork.fyi into your tools and workflows

⚡ Quick Start

Use the key below to get started immediately — no sign-up required.

Your API Key
pw_live_65d65b6a1f42920fda777e306f0005c0b9141bba4327dff203be010c1f34be72
Daily limit
500 requests / day
Available endpoints
Retrieval & Summaries

The limit resets at midnight UTC. If you need higher volume or synthesis analysis, get in touch.

Set it as an environment variable, then try a text search:

# Set once
export API_KEY="pw_live_65d65b6a1f42920fda777e306f0005c0b9141bba4327dff203be010c1f34be72"

# Text search — returns the 10 most relevant papers
curl -X POST https://priorwork.fyi/api/query \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "contrastive learning for vision transformers",
    "max_results": 10
  }'
The base URL is https://priorwork.fyi. Pass your key in the X-API-Key header on every request.

🧠 The analysis Parameter

ValueDescriptionExtra latency
"none" Search results only, no LLM processing —
"summaries" Per-paper structured notes: problem, method, key results, evidence strength. Uses cached extractions when available. +5–15 s

📦 Response Structure — Paper Search

For the topics endpoints, see the response tables in the Topics API section above.

Search-only (analysis: "none")

{
  "query": "diffusion models for image generation",
  "total_results": 10,
  "uncited_count": 8,
  "cited_count": 2,
  "results": [
    {
      "paper_id":    "DDPM_2020",
      "title":      "Denoising Diffusion Probabilistic Models",
      "authors":    "Ho, Jain, Abbeel",
      "year":       "2020",
      "conference": "NeurIPS",
      "abstract":   "We present ...",
      "similarity": 0.91,
      "is_cited":   false,
      "download_url": "https://..."
    }
  ],
  "llm_analysis": null,
  "llm_error":    null
}

With summaries (analysis: "summaries")

The results array is unchanged. An llm_analysis.extractions list is added:

{
  "results": [ /* same as above */ ],
  "llm_analysis": {
    "extractions": [
      {
        "paper_id":               "DDPM_2020",
        "problem":                "The core problem addressed",
        "core_insight":           "The key observation that justifies the approach",
        "method_summary":         "How the paper solves it",
        "key_results":            ["Result 1", "Result 2"],
        "baselines_beaten":       ["Baseline A"],
        "limitations":            ["Main limitation", "Secondary limitation"],
        "applicability_conditions":"Assumptions and constraints on when this applies",
        "positioning":            "Gap in prior work the authors claim to fill",
        "evidence_strength":      "4/5 — Strong empirical evidence with ablations"
      }
    ],
    "error": null
  }
}
is_cited is only meaningful when check_citations: true is passed. similarity values above 0.83 indicate a strong match; above 0.97 likely means the paper is already in your references.

🧭 Topics API

A different corpus and a different question. Paper search returns papers from a 128,730-paper index; these two work on the research topics our problem discovery pipeline publishes — ranking them against an interest, or judging whether a project you describe has already been done.

The two are not alike on auth. Both need a key; search accepts any valid one, including the public free key, while validate requires a key with analysis rights.

GET /api/research-suggestions — The topics themselves

Every published topic, in one document. No key, no parameters, no ranking — this is the corpus, and it is useful on its own if you want to browse rather than search. It is also what you join /api/topics/search results against, since that endpoint returns keys rather than text.

curl https://priorwork.fyi/api/research-suggestions

// → {"artifact": "162e7c8fb8cd", "generated": "2026-09-08", "topics": [ … ]}

artifact is the id of this exact topic set. It changes whenever the published set changes — a new topic, a withdrawn one, or the same topics with rewritten text. /api/topics/search returns the same id, so a client that caches this document can compare the two and refetch only when it moves:

hits = requests.post(f"{BASE}/api/topics/search", json={"q": q}).json()
if hits["artifact"] != cached_artifact_id:
    blob = requests.get(f"{BASE}/api/research-suggestions").json()
    cached_topics, cached_artifact_id = blob["topics"], blob["artifact"]

Do not infer this from a key that fails to resolve. A key derives from a topic's supporting papers, so a run that rewrites every title leaves every key untouched — a cache waiting on a resolution failure would serve that stale indefinitely.

About 4.6 MB for ~180 topics, because each one carries its full reasoning. Fetch it once and keep it rather than calling it per search — the topics change only when the pipeline runs, and generated tells you when that was.

FieldTypeWhat it is
keystring Stable id, derived from the papers behind the topic. This is what /api/topics/search returns
titlestring The project, phrased as a paper title
whystring The limitation several papers independently hit
impactstringWhat changes if it works
riskstringThe reason it might not
approachesstring Concrete ways in, numbered
regionstring The research area it was mined from
papersint How many papers the evidence rests on
statementsarray The verbatim limitations those papers stated
sources, neighboursarray The papers themselves, with ids you can look up
verification.verdictstring OPEN if a prior-art check found nothing that closes it
childrenarray Sub-problems, on the ~20% of topics that split
hydestring The synthetic abstract the ranker matches your query against

title, why, impact, risk and approaches are the ones worth reading. The rest is provenance, kept so any claim can be traced back to the papers behind it.

These are generated, not curated. verification.verdict records a prior-art check, but that check finds only about a third of work that already exists — an OPEN verdict is not evidence the problem is unsolved. Treat a topic as a lead to investigate.

Phrasing the query

Each topic is stored as a synthetic abstract of the paper that would close it, so the match is intent against intent. Write what you want to work on the way you would write it in an abstract. Measured against the live index:

StyleQueryResultsTop score
keywordsefficient transformers edge devices 0—
a titleEfficient Vision Transformers for Edge Deployment 210.385
a questionhow can I make vision transformers efficient on edge devices? 180.368
proseWe want to cut the compute and memory cost of vision transformers so they can run on resource-constrained edge hardware without losing accuracy. 290.430

Keywords return nothing. That is not a bug — a bare term has almost no overlap with a full abstract, so it lands under the relevance floor. The same is true of a bare method name: diffusion models returns 0 results, while "generated images are hard to attribute to their source model" returns 26. Describe the problem, not the technique.

Broad is worse, not better. machine learning returns 5 and evaluation returns 2, while "detecting hallucination in retrieval-augmented generation" scores 0.556 — the highest in any test here. Specificity helps; vagueness has nothing to match against.

More detail helps, up to about a thousand characters.

Query lengthResultsTop score
159 chars — one sentence590.462
459 chars — a paragraph850.598
1,059 chars960.652
1,953 chars980.652 (unchanged)

The ranker truncates at 256 tokens, roughly 1,000 characters, so anything past that is ignored — the last two rows score identically. Put the substance first; there is no benefit to sending a whole paper.

POST /api/topics/search — Rank research topics

Ranks the published research topics against a free-text description of what you want to work on. Separate from paper search: it never touches the paper index, answers in about 5 ms, and returns topic keys you join against GET /api/research-suggestions.

Needs a key. Any valid key will do — the public free key above works, and no analysis rights are required.

It has its own allowance of 2,000 requests per day, counted separately from paper search in both directions: ranking topics never consumes your paper-search quota, and a key that has exhausted that quota still works here.

The site's own pages call this without a key and are not capped — a page cannot hold a secret, so a first-party request is attributed to the site's key instead. The exemption is decided by Origin, so it does not extend to an API caller who omits the header.

curl -X POST https://priorwork.fyi/api/topics/search \
  -H "Content-Type: application/json" \
  -d '{"q": "protein folding"}'

# → {"degraded": false, "results": [{"key": "6e3242e12882", "score": 0.45}, …]}
FieldTypeDefaultDescription
qstring required What you want to work on, in your own words
min_scorefloat0.30 Relevance floor. Below it a “match” is vocabulary collision rather than subject overlap
limitintunset A safety bound, not a page size. Leave it off and the floor decides how many results there are; clamps at 500

Response

{
  "artifact": "162e7c8fb8cd",
  "degraded": false,
  "results": [
    { "key": "6e3242e12882", "score": 0.450090 },
    { "key": "a9d4b3708af5", "score": 0.413924 }
  ]
}
FieldTypeMeaning
artifactstring Id of the topic set these keys came from. Compare it against a cached copy to know when to refetch
results[].keystring Stable topic id. Join it against GET /api/research-suggestions — this endpoint returns keys, never topic text, so the two can never disagree about what a topic says
results[].scorefloat Cosine similarity, descending. Not comparable across queries — rank within a response, don't threshold between them
degradedbool true means ranking was unavailable and results is empty. Fall back to whatever you had
stalebool Present only on a deployment mismatch: the ranker's vectors describe a different set of topics, so its keys would not resolve

Zero results is a legitimate answer, not an error — it means nothing published is close to that question, which is more useful than a list of near-misses. degraded: true is the different case: ranking was unavailable, so fall back to whatever you had. Limited to 60 requests per minute per address and 2,000 per day per key.

POST /api/topics/validate — Has this been done? premium

Retrieves the closest prior work for a project description and asks whether any of it already does the job. Requires an API key with analysis rights. Each call counts against your daily quota.

curl -X POST https://priorwork.fyi/api/topics/validate \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Verifier-free reward shaping for open-domain reasoning",
    "abstract": "We remove the dependence on rule-based answer verifiers by ...",
    "why_it_matters": "Current methods only work where answers can be checked ..."
  }'
FieldTypeDefaultDescription
titlestring required Working title. Worth about 30 points of top-1 retrieval accuracy — do not leave it out
abstractstring required The idea, as you would write it in an abstract
why_it_mattersstring required The limitation this removes. This is the framing the judge matches on
max_papersint10 3–20. How many retrieved papers the judge reads

Response

{
  "verdict": "PARTIAL",
  "found_prior_work": true,
  "reason": "Paper [2] removes the verifier requirement, but only for maths.",
  "papers": [
    { "paper_id": "Reinforcing_General_Reasoning_Without_Verifiers_2026",
      "title": "Reinforcing General Reasoning Without Verifiers",
      "similarity": 0.824, "year": "2026",
      "conference": "ICLR", "download_url": "https://..." }
  ],
  "considered": [ /* every paper the judge read, same shape */ ],
  "sensitivity_note": "This detects roughly a third of work that already exists ..."
}
FieldTypeMeaning
verdictstring ALREADY_DONE, PARTIAL or OPEN. A 200 always carries one of these three
found_prior_workbool True for ALREADY_DONE and PARTIAL only. The single field worth branching on
reasonstring One sentence naming the paper that decided it
papersarray Only the papers the verdict rests on. Empty for OPEN
consideredarray Everything the judge read, so you can see what it was working from. Anything at or above 0.97 similarity — your own paper — is excluded before judging
sensitivity_notestring Shipped in every response, because the caveat below decides whether the answer is useful or misleading

Phrasing the three fields

title is not decoration. The index stores every paper as Title: …\nAbstract: …, so supplying one makes your submission the same shape as the documents it is matched against — worth about 30 points of top-1 accuracy (63% → 95% over 100 queries whose target paper was known).

why_it_matters should name the constraint you are removing, not the benefit. Gaps in this corpus are overwhelmingly phrased as limitations — "requires rule-based verifiers", "restricted to portrait scenes", "assumes access to the retain set" — and the paper that closes one is the paper that lifts that requirement. Matching works best when your framing has the same shape.

// weak — states a benefit
"why_it_matters": "This would make reasoning models more useful."

// strong — names the constraint being lifted
"why_it_matters": "Current methods need a rule-based checker, which limits them to maths and code."

abstract is the work itself: what you would do and how. Minimum 50 characters, and the same thousand-character guidance as search applies — say the substance early.

Read the verdict in one direction only. This finds roughly a third of work that already exists, against a ~4% false-positive rate. ALREADY_DONE and PARTIAL are worth acting on, and papers names what decided it. OPEN means nothing was found among the papers read — it is not evidence that your idea is novel, which is why there is no is_novel field.

StatusCodeWhen
400MISSING_FIELDS A required field is missing or blank
401AUTH_REQUIRED No API key supplied
403ANALYSIS_NOT_PERMITTED Valid key, but it lacks analysis rights — the free tier
422NOTHING_TO_VERIFY Every retrieved paper was your own submission, or nothing cleared the threshold
503VERIFICATION_UNAVAILABLE The model was unreachable or returned no verdict. Retryable

A 200 always carries a real verdict — the ways a judgement can fail to exist are errors with their own codes, never a fourth verdict value.

🔒 Data Privacy Note

A PDF you send — uploaded to /api/query, or fetched by us from a URL you pass to /api/search/pdf-url — is written to a temporary file, read, and deleted when the request finishes. Neither the file nor its text is ever stored.

What you send through sections, and the two synthesis fields written about it (relevance_to_query, query_positioning), are removed after 30 days. They are kept that long so a change to the analysis prompt can be judged against earlier output.

LLM analysis runs on Google Vertex AI. With analysis=summaries or synthesis the retrieved papers go there; with analyze_my_draft your sections go too. Leave analysis off and nothing you send leaves our hardware.