> ## Documentation Index
> Fetch the complete documentation index at: https://docs.consensus.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a PRISMA-ready search corpus

> Assemble a reproducible, deduplicated record set with the flow counts a systematic review has to report.

## What you get

A deduplicated corpus, a search strategy locked before results were seen, and the counts PRISMA asks for: records identified, duplicates removed, records screened, records excluded with reasons.

<Note>
  This is a recipe built on the API, not a packaged product. Consensus supplies the search, filters, and pagination; you own the strategy log and the flow diagram. It is one of the most requested workflows we do not yet ship end to end.
</Note>

## Who it's for

Methodologists and research-software teams producing a corpus that has to survive peer review, plus anyone publishing where PRISMA reporting is mandatory.

## Lock the strategy first

Reproducibility is decided before you search, not after. Write down and persist:

* the full query list
* every filter, exactly as it will be sent
* the inclusion and exclusion criteria
* the date the search was run

A strategy adjusted after seeing results is a search, not a method. If you must change it, version it and report both.

## Sweep to exhaustion

```python theme={null}
import os, requests

API = "https://api.consensus.app/v1/search"
HEADERS = {"x-api-key": os.environ["CONSENSUS_API_KEY"]}
STRATEGY = dict(
    study_types=["rct", "meta-analysis", "systematic review"],
    human=True, year_min=2015, exclude_preprints=True, page_size=200,
)

def sweep(query):
    page, out = 0, []
    while page <= 49:                      # 0-indexed; 49 is the ceiling
        r = requests.get(API, headers=HEADERS, params={"query": query, "page": page, **STRATEGY})
        r.raise_for_status()
        body = r.json()
        out.extend(body["results"])
        if body["is_end"] or body.get("next_page") is None:
            break
        page = body["next_page"]
    return out

corpus, per_query = {}, {}
for query in QUERY_SET:                    # your locked list
    found = sweep(query)
    per_query[query] = len(found)          # pre-dedup count, needed for PRISMA
    for paper in found:
        corpus.setdefault(paper["doi"], paper)
```

<Note>
  Pagination and page sizes above 20 need a paid plan or Enterprise key; `page_size` caps at 300 (Pro, Teams), 750 (Deep), higher on Enterprise. Over-large requests are clamped, not rejected — read the `page_size` echoed back. See [rate limits](/use-cases/best-practices#rate-limits-and-result-caps).
</Note>

## Deduplicate and count

Merge on `doi`, keeping the first-seen record plus which queries found it. Retain **both** the pre- and post-deduplication totals — PRISMA reports each separately, and you cannot reconstruct them later.

Records without a DOI need a fallback key (normalized title plus year). Count how many took that path; a large number signals a coverage or record-quality problem worth mentioning.

## What PRISMA wants back

| Flow stage                     | Where it comes from                                                     |
| ------------------------------ | ----------------------------------------------------------------------- |
| Records identified             | Sum of per-query pre-dedup counts                                       |
| Duplicates removed             | Pre-dedup total minus unique DOIs                                       |
| Records screened               | Size of the deduplicated corpus                                         |
| Records excluded, with reasons | From [abstract screening](/use-cases/abstract-screening), per criterion |
| Full-text assessed             | Records escalated past abstract screening                               |
| Studies included               | Final set                                                               |

<Warning>
  Consensus is one source. A review claiming comprehensive coverage will normally be expected to search additional databases and registries, and reviewers will ask which ones. Report Consensus as one search source with its date and strategy, not as the whole search.
</Warning>

## Audit requirements

Follow the [grounding rules](/use-cases/best-practices#grounding-and-auditability). Persist per query: the query text, filters exactly as sent, pages walked, records returned, and the run date. That table *is* your methods section's evidence.

## What to check before you trust it

* **Confirm you actually reached the end.** A sweep that stopped at page 49 with `is_end` false has truncated results — say so, or narrow the query and re-run.
* **Check the dedup key.** Preprint and published versions of the same study carry different DOIs and will both survive.
* **Re-run the strategy on the reporting date.** Literature moves; reviewers expect a search date, and a stale corpus invites a "please update" revision.

## Related

<CardGroup cols={2}>
  <Card title="Screen abstracts against inclusion criteria" icon="list-check" href="/use-cases/abstract-screening">
    The next step, with the exclusion reasons PRISMA needs.
  </Card>

  <Card title="Write the search-strategy section of your methods" icon="file-lines" href="/use-cases/search-strategy-methods">
    Turn the strategy log into publishable prose.
  </Card>

  <Card title="Best practices" icon="shapes" href="/use-cases/best-practices">
    Exhaustive sweep, rate limits, and the five primitives.
  </Card>

  <Card title="All use cases" icon="grid-2" href="/use-cases">
    Browse the gallery by persona.
  </Card>
</CardGroup>
