# Elicit API - **OpenAPI Version:** `3.1.0` - **API Version:** `2.0.0` The Elicit API provides programmatic access to Elicit's research capabilities, including semantic search over 138 million+ academic papers and automated report generation. ## Authentication All API requests require a Bearer token in the `Authorization` header: ```properties Authorization: Bearer elk_live_your_key_here ``` API keys can be created and managed from your [Elicit account settings](https://elicit.com/settings). ## Billing API access requires a Pro plan or above. Search requests are rate-limited based on your plan tier — see the Search endpoint for details. Manage your plan in [account settings](https://elicit.com/settings). ## Code Examples Working examples in curl, Python, and JavaScript, plus integrations (CLI tool, Slack bot, Claude Code skill): **[github.com/elicit/api-examples](https://github.com/elicit/api-examples)** ## Error Handling All errors return a consistent JSON structure with an `error` object containing a machine-readable `code` and a human-readable `message`. ## MCP Server All API functionality is also available via [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server, enabling use from Claude Desktop, Claude Code, and other MCP-compatible clients. Authentication is via OAuth 2.0. ### Claude Code ```csharp claude mcp add --transport http elicit https://elicit.com/api/mcp ``` Then run `/mcp`, select the `elicit` server, and choose **Authenticate** to open a browser for login. ### Claude Desktop **Via the UI:** Click the icon next to your name > **Settings** > **Connectors** > **Add custom connector**. Enter `Elicit` for the name and `https://elicit.com/api/mcp` for the URL. **Or via config file** — add to `claude_desktop_config.json`: ```json { "mcpServers": { "elicit": { "type": "url", "url": "https://elicit.com/api/mcp" } } } ``` ### Other MCP clients Connect any MCP client using HTTP transport to `https://elicit.com/api/mcp`. OAuth discovery is available at `https://elicit.com/api/mcp/.well-known/oauth-protected-resource`. For MCP setup guides, tool reference, and usage examples, see [github.com/elicit/api-examples/tree/main/integrations/mcp](https://github.com/elicit/api-examples/tree/main/integrations/mcp). ## Servers - **URL:** `https://elicit.com/api/v2` - **Description:** Elicit ## Operations ### Search for academic papers - **Method:** `POST` - **Path:** `/search/papers` - **Tags:** Search Search Elicit's database of over 138 million academic papers using natural language queries. Semantic search uses natural language understanding to find relevant papers even when the exact terms don't match. Set `corpus` to `pubmed` to restrict results to PubMed, or leave it as the default `elicit` for the full paper index. Set `searchMode` to `"keyword"` to interpret the query as a Lucene-style boolean expression instead of natural language. Filters and `searchMode: "keyword"` are mutually exclusive — put any filter expressions directly into the query string when using keyword search. Mixing them returns a 400. To search clinical trials instead, use [`POST /api/v2/search/trials`](#tag/Search/paths/~1search~1trials/post). ### Limits Each plan caps how many results a single search request may return: | Plan | Results per request | | ---------- | ------------------- | | Basic | No access | | Plus | No access | | Pro | 300 | | Scale | 500 | | Enterprise | 10,000 | Search is rate-limited only by the global limit of 100 requests per minute per IP address, applied across all endpoints and all plans. Exceeding it returns a `429` and blocks the IP for 5 minutes. Upgrade your plan in [account settings](https://elicit.com/settings) for higher per-request result caps. ### Example ```bash curl -X POST https://elicit.com/api/v2/search/papers \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"query": "effects of sleep deprivation on cognitive performance"}' ``` #### Request Body ##### Content-Type: application/json - **`query` (required)** `string` — The search query string - **`corpus`** `string`, possible values: `"elicit", "pubmed"`, default: `"elicit"` — Paper corpus to search. \`elicit\` (default) searches Elicit's full paper index; \`pubmed\` restricts to PubMed. - **`filters`** `object` — Filters to narrow search results - **`excludeKeywords`** `array` — Keywords to exclude from results **Items:** `string` - **`hasPdf`** `boolean` — Only include papers with available PDFs - **`includeKeywords`** `array` — Keywords that must appear in the paper **Items:** `string` - **`maxEpochS`** `integer` — Maximum publication date as Unix epoch seconds - **`maxQuartile`** `integer` — Maximum journal quartile (1 = top 25%) - **`maxYear`** `integer` — Maximum publication year - **`minEpochS`** `integer` — Minimum publication date as Unix epoch seconds - **`minYear`** `integer` — Minimum publication year - **`pubmedOnly`** `boolean` — Only include papers from PubMed - **`retracted`** `string`, possible values: `"exclude_retracted", "include_retracted", "only_retracted"` — How to handle retracted papers. Defaults to exclude\_retracted. - **`typeTags`** `array` — Filter by study type **Items:** `string`, possible values: `"Review", "Meta-Analysis", "Systematic Review", "RCT", "Longitudinal"` - **`maxResults`** `integer`, default: `10` — Maximum number of results to return (1-10000) - **`searchMode`** `string`, possible values: `"semantic", "keyword"`, default: `"semantic"` — How to interpret \`query\`. \`semantic\` (default) runs Elicit's semantic search. \`keyword\` sends the query as a Lucene-style boolean expression directly to the corpus search API. Mutually exclusive with \`filters\` / \`trialFilters\` — put filter expressions into the query string in keyword mode. **Example:** ```json { "query": "GLP-1 receptor agonists for weight loss", "searchMode": "semantic", "maxResults": 10, "corpus": "elicit", "filters": { "minYear": 2020, "maxYear": 2025, "minEpochS": 1672531200, "maxEpochS": 1789413033, "maxQuartile": 2, "includeKeywords": [ "semaglutide", "liraglutide" ], "excludeKeywords": [ "rodent", "mouse model" ], "typeTags": [ "RCT", "Meta-Analysis" ], "hasPdf": false, "pubmedOnly": false, "retracted": "exclude_retracted" } } ``` #### Responses ##### Status: 200 Search results returned successfully. ###### Content-Type: application/json - **`papers` (required)** `array` — Papers matching the query **Items:** - **`abstract` (required)** `string | null` — Paper abstract - **`authors` (required)** `array` — List of author names **Items:** `string` - **`citedByCount` (required)** `integer | null` — Number of citations this paper has received - **`doi` (required)** `string | null` — Digital Object Identifier - **`elicitId` (required)** `string | null` — Elicit internal paper identifier - **`fullTextUrl` (required)** `string | null` — Best available full-text / PDF link, or null when none is known. - **`journalQuartile` (required)** `integer | null` — SJR journal quartile (1 = top 25%). Null when the journal is unranked/unknown or for the \`pubmed\` corpus. - **`pmid` (required)** `string | null` — PubMed identifier - **`studyTypeTags` (required)** `array` — Study design tags (e.g. RCT, Meta-Analysis, Systematic Review, Review, Longitudinal). Populated for the \`elicit\` corpus; empty for the \`pubmed\` corpus. **Items:** `string` - **`title` (required)** `string` — Paper title - **`urls` (required)** `array` — URLs for the paper **Items:** `string` - **`venue` (required)** `string | null` — Publication venue - **`year` (required)** `integer | null` — Publication year - **`warnings`** `array` — Non-fatal warnings emitted while executing the search (e.g. phrases ignored by the PubMed parser). **Items:** - **`corpus` (required)** `string`, possible values: `"elicit", "pubmed", "clinical_trials"` — Corpus that emitted the warning - **`message` (required)** `string` — Human-readable warning message - **`searchMode` (required)** `string`, possible values: `"semantic", "keyword"` — Search mode in effect when the warning was emitted - **`warningDetails` (required)** `object` - **`messages` (required)** `array` — Underlying warning messages **Items:** `string` - **`type` (required)** `string` — Warning category **Example:** ```json { "papers": [ { "elicitId": null, "title": "", "authors": [ "" ], "year": null, "abstract": null, "doi": null, "pmid": null, "venue": null, "citedByCount": null, "urls": [ "" ], "studyTypeTags": [ "" ], "journalQuartile": null, "fullTextUrl": null } ], "warnings": [ { "corpus": "elicit", "searchMode": "semantic", "message": "", "warningDetails": { "type": "", "messages": [ "" ] } } ] } ``` ##### Status: 400 Invalid request. The request body failed validation — check that \`query\` is present and \`maxResults\` is between 1 and 10000. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Search clinical trials - **Method:** `POST` - **Path:** `/search/trials` - **Tags:** Search Search for clinical trials. Trial records come from ClinicalTrials.gov. Pass `trialFilters` to narrow by phase, recruitment status, or whether the trial has posted results. Set `searchMode` to `"keyword"` to send the query as a Lucene-style boolean expression directly to the underlying advanced-filter API. Filters and `searchMode: "keyword"` are mutually exclusive — put filter expressions directly into the query when using keyword search. Mixing them returns a 400. To search academic papers instead, use [`POST /api/v2/search/papers`](#tag/Search/paths/~1search~1papers/post). ### Limits Each plan caps how many results a single search request may return: | Plan | Results per request | | ---------- | ------------------- | | Basic | No access | | Plus | No access | | Pro | 300 | | Scale | 500 | | Enterprise | 10,000 | Search is rate-limited only by the global limit of 100 requests per minute per IP address, applied across all endpoints and all plans. Exceeding it returns a `429` and blocks the IP for 5 minutes. Upgrade your plan in [account settings](https://elicit.com/settings) for higher per-request result caps. ### Example ```bash curl -X POST https://elicit.com/api/v2/search/trials \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"query": "semaglutide obesity", "trialFilters": {"phase": ["PHASE3"]}}' ``` #### Request Body ##### Content-Type: application/json - **`query` (required)** `string` — The search query string - **`maxResults`** `integer`, default: `10` — Maximum number of results to return (1-10000) - **`searchMode`** `string`, possible values: `"semantic", "keyword"`, default: `"semantic"` — How to interpret \`query\`. \`semantic\` (default) runs Elicit's semantic search. \`keyword\` sends the query as a Lucene-style boolean expression directly to the corpus search API. Mutually exclusive with \`filters\` / \`trialFilters\` — put filter expressions into the query string in keyword mode. - **`trialFilters`** `object` — Clinical-trials filters (phase, recruitment status, results) - **`hasResults`** `boolean` — Only include trials that have posted results - **`phase`** `array` — Clinical trial phases to include **Items:** `string`, possible values: `"NA", "EARLY_PHASE1", "PHASE1", "PHASE2", "PHASE3", "PHASE4"` - **`recruitmentStatus`** `array` — Trial recruitment statuses to include **Items:** `string`, possible values: `"ACTIVE_NOT_RECRUITING", "COMPLETED", "ENROLLING_BY_INVITATION", "NOT_YET_RECRUITING", "RECRUITING", "SUSPENDED", "TERMINATED", "WITHDRAWN", "AVAILABLE"` **Example:** ```json { "query": "GLP-1 receptor agonists for weight loss", "searchMode": "semantic", "maxResults": 10, "trialFilters": { "phase": [ "PHASE2", "PHASE3" ], "recruitmentStatus": [ "RECRUITING", "ACTIVE_NOT_RECRUITING" ], "hasResults": true } } ``` #### Responses ##### Status: 200 Trial search results returned successfully. ###### Content-Type: application/json - **`trials` (required)** `array` — Clinical trials matching the query **Items:** - **`completionDate` (required)** `string | null` — Completion date (ISO \`YYYY-MM-DD\` or partial). - **`conditions` (required)** `array` — Conditions / diseases being studied. **Items:** `string` - **`enrollmentCount` (required)** `integer | null` — Actual or anticipated enrollment count. - **`hasResults` (required)** `boolean | null` — Whether the trial has posted results. - **`interventions` (required)** `array` — Intervention names. **Items:** `string` - **`lastUpdatedYear` (required)** `integer | null` — Year the trial record was last updated. - **`leadSponsor` (required)** `string | null` — Lead sponsor name. - **`nctId` (required)** `string` — NCT identifier for the trial - **`overallStatus` (required)** `string | null` — Overall recruitment status (RECRUITING, COMPLETED, TERMINATED, etc.). Null when the trial has no status posted. - **`phase` (required)** `array` — Trial phases (may list multiple, e.g. PHASE2 + PHASE3). Empty for N/A. **Items:** `string` - **`primaryCompletionDate` (required)** `string | null` — Primary completion date (ISO \`YYYY-MM-DD\` or partial). - **`startDate` (required)** `string | null` — Trial start date (ISO \`YYYY-MM-DD\` or partial). - **`studyType` (required)** `string | null` — Study type (INTERVENTIONAL, OBSERVATIONAL, EXPANDED\_ACCESS). - **`summary` (required)** `string | null` — Plain-text trial description / brief summary - **`title` (required)** `string` — Trial title - **`url` (required)** `string` — Link to the trial's public record - **`warnings`** `array` — Non-fatal warnings emitted while executing the search. **Items:** - **`corpus` (required)** `string`, possible values: `"elicit", "pubmed", "clinical_trials"` — Corpus that emitted the warning - **`message` (required)** `string` — Human-readable warning message - **`searchMode` (required)** `string`, possible values: `"semantic", "keyword"` — Search mode in effect when the warning was emitted - **`warningDetails` (required)** `object` - **`messages` (required)** `array` — Underlying warning messages **Items:** `string` - **`type` (required)** `string` — Warning category **Example:** ```json { "trials": [ { "nctId": "NCT05646706", "title": "", "summary": null, "url": "https://clinicaltrials.gov/study/NCT05646706", "overallStatus": null, "phase": [ "" ], "studyType": null, "enrollmentCount": null, "conditions": [ "" ], "interventions": [ "" ], "leadSponsor": null, "startDate": null, "primaryCompletionDate": null, "completionDate": null, "hasResults": null, "lastUpdatedYear": null } ], "warnings": [ { "corpus": "elicit", "searchMode": "semantic", "message": "", "warningDetails": { "type": "", "messages": [ "" ] } } ] } ``` ##### Status: 400 Invalid request. The request body failed validation. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Create a new report - **Method:** `POST` - **Path:** `/sessions/reports` - **Tags:** Reports Start an asynchronous report generation job. Elicit will search for relevant papers, screen them for relevance, extract structured data, and produce a full research report. Reports are long-running operations (typically 5–15 minutes). The response includes a `sessionId` and a `links.self` URL that you poll for status. The report is also visible at the `url` returned in the response, where you can watch it progress in real time. ### Workflow 1. **POST /api/v2/sessions/reports** — submit your research question (returns immediately with `sessionId`) 2. **GET `links.self`** (`/api/v2/sessions/reports/:sessionId`) — poll until `status` is `completed` or `failed` 3. Use the `pdfUrl` and `docxUrl` fields on the completed response to download the report, and `txtUrl`, `bibUrl`, and `risUrl` to download its reference list (APA text, BibTeX, and RIS) ### Example ```bash # 1. Create the report curl -X POST https://elicit.com/api/v2/sessions/reports \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"researchQuestion": "What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?"}' # 2. Poll for completion (repeat until status is "completed" or "failed") curl https://elicit.com/api/v2/sessions/reports/{sessionId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Request Body ##### Content-Type: application/json - **`researchQuestion` (required)** `string` — The research question to investigate. Elicit will search for relevant papers, screen them, and extract data to produce a structured report. - **`isPublic`** `boolean`, default: `false` — Whether the report should be publicly accessible via its URL without authentication. Defaults to false. - **`maxExtractPapers`** `integer`, default: `10` — Maximum number of papers to include in the final extraction table. Papers are screened for relevance before extraction. Defaults to 10. - **`maxSearchPapers`** `integer`, default: `50` — Maximum number of papers to retrieve during the search phase. More papers means a more comprehensive but slower report. Defaults to 50. - **`title`** `string` — Optional title for the report. If provided, Elicit will use this as the report title instead of generating one automatically from the research question. **Example:** ```json { "researchQuestion": "What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?", "title": "GLP-1 Receptor Agonists and Cardiovascular Outcomes", "maxSearchPapers": 50, "maxExtractPapers": 10, "isPublic": false } ``` #### Responses ##### Status: 202 Report creation accepted. The report is now being generated asynchronously. Poll \`links.self\` for status. ###### Content-Type: application/json - **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`status` (required)** `string` — Initial status is always processing - **`type` (required)** `string` - **`url` (required)** `string` — URL to view the report in the Elicit web interface as it progresses **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "isPublic": false, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ##### Status: 400 Invalid request. Check that \`researchQuestion\` is present and within length limits. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Get report status and results - **Method:** `GET` - **Path:** `/sessions/reports/{sessionId}` - **Tags:** Reports Poll the status of a report created via `POST /api/v2/sessions/reports`. ### Status transitions - **processing** — Elicit is actively searching, screening, and extracting data. You can watch progress in real time at the `url`. - **pausedForInsufficientQuota** — The account exceeded its usage limit mid-run. The report stays paused until resumed via the `links.resume` URL (or the Elicit web interface) once the limit is resolved. - **completed** — The report is finished. The `result` field contains the report content. - **failed** — Something went wrong. The `error` field contains details. - **unknown** — Status is not tracked for this report (legacy or user-created reports). ### Polling recommendation Poll every 30–60 seconds. Reports typically complete in 5–15 minutes depending on the number of papers. ### Including the full report body By default, the `reportBody` and `abstract` fields are omitted to keep polling responses lightweight. To include them, add `?include=reportBody` to the request. ### Example ```bash # Poll for status curl https://elicit.com/api/v2/sessions/reports/{sessionId} \ -H "Authorization: Bearer elk_live_your_key_here" # Fetch with full report body curl "https://elicit.com/api/v2/sessions/reports/{sessionId}?include=reportBody" \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 Report status and results (if completed). ###### Content-Type: application/json - **`executionStage` (required)** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage. Advances through gathering\_sources → screening\_abstract → extracting\_data → generating\_report → done. Null for reports created before this field was introduced or when the stage isn't known. - **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the report. Transitions: processing ⇄ pausedForInsufficientQuota (paused when the account exceeds its usage limit; stays paused until explicitly resumed via the resume endpoint or the Elicit web interface), processing → completed/failed. Poll until completed or failed. - **`type` (required)** `string` - **`url` (required)** `string` — URL to view the report in the Elicit web interface - **`bibUrl`** `string | null` — Pre-signed URL to download the report's references as a BibTeX (.bib) file. Only present when status is completed and the report has a non-empty bibliography. Expires after 7 days — re-fetch the report for a fresh URL. - **`docxUrl`** `string | null` — Pre-signed URL to download the report as DOCX. Only present when status is completed and assets have been generated. Expires after 7 days — re-fetch the report for a fresh URL. - **`error`** `object` — Error details, only present when status is failed - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message - **`exportsStatus`** `string`, possible values: `"ready", "generating", "unavailable"` — Availability of the reference-list exports (\`txtUrl\`/\`bibUrl\`/\`risUrl\`); \`pdfUrl\`/\`docxUrl\` are unaffected. Only present when status is completed. \`ready\`: absent URLs genuinely have no export. \`generating\`: the exports are currently being generated and nothing is cached yet. \`unavailable\`: export generation failed and nothing is cached. - **`pdfUrl`** `string | null` — Pre-signed URL to download the report as PDF. Only present when status is completed and assets have been generated. Expires after 7 days — re-fetch the report for a fresh URL. - **`result`** `object` — Report output, only present when status is completed - **`summary` (required)** `string` — AI-generated executive summary of the findings - **`title` (required)** `string` — Auto-generated title for the report - **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. - **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. - **`risUrl`** `string | null` — Pre-signed URL to download the report's references as an RIS (.ris) file. Only present when status is completed and the report has a non-empty bibliography. Expires after 7 days — re-fetch the report for a fresh URL. - **`txtUrl`** `string | null` — Pre-signed URL to download the report's reference list as a plain-text (APA) file. Only present when status is completed and the report has a non-empty bibliography. Expires after 7 days — re-fetch the report for a fresh URL. **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "isPublic": false, "result": { "title": "GLP-1 Receptor Agonists and Cardiovascular Outcomes: A Systematic Review", "summary": "This review analyzed 42 studies examining the cardiovascular effects of GLP-1 receptor agonists. The evidence suggests significant reductions in major adverse cardiovascular events (MACE), with semaglutide showing the strongest effect (HR 0.74, 95% CI 0.58-0.95)...", "reportBody": "# Introduction\n\nGLP-1 receptor agonists have emerged as...", "abstract": "This systematic review examines the cardiovascular effects of..." }, "error": { "code": "", "message": "" }, "pdfUrl": "https://s3.amazonaws.com/...", "docxUrl": "https://s3.amazonaws.com/...", "txtUrl": "https://s3.amazonaws.com/...", "bibUrl": "https://s3.amazonaws.com/...", "risUrl": "https://s3.amazonaws.com/...", "exportsStatus": "ready", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Report not found. Either the report ID is invalid or the report belongs to a different user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Create a new systematic review - **Method:** `POST` - **Path:** `/sessions/systematic-reviews` - **Tags:** Systematic Reviews Start a systematic review. Elicit runs the stages you configure — searches, abstract screening, fulltext screening, extraction, and a report. Each stage runs only when you include it; omit a stage to skip it. The default example below runs a complete review end-to-end. Systematic reviews are long-running operations. The response includes a `sessionId` and a `links.self` URL (`/api/v2/sessions/systematic-reviews/:sessionId`) that you poll for status. You can also watch progress live at the `url` in the response. ### Plan limits | Plan | Max columns | Max results per query | Max total results | Figure extraction | | ---------- | ----------- | --------------------- | ----------------- | ----------------- | | Pro | 20 | 1,000 | 5,000 | No | | Scale | 30 | 5,000 | 20,000 | Yes | | Enterprise | 40 | 10,000 | 40,000 | Yes | ### Example ```bash curl -X POST https://elicit.com/api/v2/sessions/systematic-reviews \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "researchQuestion": "Do GLP-1 receptor agonists reduce MACE in T2D patients?", "searches": [{ "query": "GLP-1 cardiovascular outcomes", "maxResults": 200 }], "abstractScreening": { "generate": true }, "fulltextScreening": { "reuseAbstractCriteria": true }, "extraction": { "generate": true, "useFigures": false }, "generateReport": true }' ``` #### Request Body ##### Content-Type: application/json - **`researchQuestion` (required)** `string` — The research question the review is investigating. - **`abstractScreening`** `object` — Abstract-stage screening. Supply \`criteria\`, \`generate: true\`, or both. Omit the field to skip. - **`criteria`** `array` — Explicit screening criteria. **Items:** - **`instructions` (required)** `string` — Plain-language instructions used to judge whether a paper meets this criterion - **`name` (required)** `string` — Short name for the criterion - **`depth`** `string`, possible values: `"fast", "thorough"`, default: `"thorough"` — How thoroughly Elicit judges each abstract against your criteria. \`thorough\` (default) applies the criteria in full and records the quotes behind each decision. \`fast\` costs a fraction as much per paper, but wrongly excludes more papers that met your criteria and returns decisions without supporting quotes — use it to triage a large candidate set, not for a final screen. Send the same request with \`dryRun: true\` to compare what each setting costs in credits. - **`generate`** `boolean`, default: `false` — When true, Elicit generates additional screening criteria. - **`dryRun`** `boolean` — Deprecated. Omit this field to create the review. - **`extraction`** `object` — Extraction stage. Supply \`questions\`, \`generate\`, or both. Omit to skip extraction entirely. - **`generate`** `boolean`, default: `false` — When true, Elicit generates additional extraction columns. - **`questions`** `array` — Explicit extraction columns. **Items:** - **`instructions` (required)** `string` — Plain-language instructions describing what to extract - **`name` (required)** `string` — Column header for this extraction question - **`choices`** `array` — Optional fixed list of allowed answers. Omit for free-text extraction. When set, the model is constrained to one of these values. **Items:** `string` - **`useFigures`** `boolean`, default: `false` — When true, Elicit also reads figures and charts when answering your extraction questions, so it can pick up results that appear only in a figure. Extraction takes longer and costs extra credits on every column (returned as \`figuresCredits\` in a \`dryRun\` estimate). Requires a plan that includes figure extraction. - **`fulltextScreening`** `object` — Fulltext-stage screening. Supply \`criteria\`, \`reuseAbstractCriteria: true\`, or both. Requires \`abstractScreening\` to be present. Omit to skip. - **`criteria`** `array` — Explicit fulltext-stage criteria. **Items:** - **`instructions` (required)** `string` — Plain-language instructions used to judge whether a paper meets this criterion - **`name` (required)** `string` — Short name for the criterion - **`depth`** `string`, possible values: `"fast", "thorough"`, default: `"thorough"` — How thoroughly Elicit judges each full text against your criteria. \`thorough\` (default) applies the criteria in full and records the quotes behind each decision. \`fast\` costs less per paper, but wrongly excludes more papers that met your criteria and returns decisions without supporting quotes. Send the same request with \`dryRun: true\` to compare what each setting costs in credits. - **`reuseAbstractCriteria`** `boolean`, default: `false` — When true, the abstract-stage criteria are also applied at the fulltext stage. - **`generateReport`** `boolean`, default: `false` — Generate a full report at the end of the review. Requires \`extraction\`. - **`isPublic`** `boolean`, default: `false` — Whether the review should be publicly accessible via its URL without authentication. Defaults to false. - **`protocolDetails`** `string` — Free-form context (PICO, methodology, inclusion/exclusion rationale) used when Elicit generates screening criteria, extraction columns, or the final report. - **`searches`** `array`, default: `[]` — Searches that feed the review pipeline. If omitted or empty, Elicit runs a semantic search using \`researchQuestion\` as the query. Total search results are subject to plan-specific limits. **Items:** - **`query` (required)** `string` — Search query - **`corpus`** `string`, possible values: `"elicit", "pubmed", "clinical_trials"`, default: `"elicit"` — Corpus to search. \`elicit\` (default) searches Elicit's full academic paper index, spanning most research domains. \`pubmed\` restricts results to PubMed. \`clinical\_trials\` returns registered trials only. - **`maxResults`** `integer`, default: `200` — Maximum number of papers to retrieve from this search. Plan-specific caps apply. - **`searchMode`** `string`, possible values: `"semantic", "keyword"`, default: `"semantic"` — \`semantic\` (default) uses vector-similarity retrieval; \`keyword\` uses literal keyword matching. - **`title`** `string` — Optional title for the review. **Example:** ```json { "researchQuestion": "Do GLP-1 receptor agonists reduce MACE in T2D patients?", "protocolDetails": "", "searches": [], "abstractScreening": { "criteria": [ { "name": "Human study", "instructions": "The study must be conducted in human subjects (not in vitro or animal-only)." } ], "generate": false, "depth": "thorough" }, "fulltextScreening": { "criteria": [ { "name": "Human study", "instructions": "The study must be conducted in human subjects (not in vitro or animal-only)." } ], "reuseAbstractCriteria": false, "depth": "thorough" }, "extraction": { "questions": [ { "name": "MACE hazard ratio", "instructions": "Extract the hazard ratio and 95% confidence interval for 3-point MACE.", "choices": [ "yes", "no", "maybe" ] } ], "generate": false, "useFigures": false }, "generateReport": true, "title": "", "isPublic": false, "dryRun": false } ``` #### Responses ##### Status: 202 Systematic review creation accepted. The review is now running asynchronously. Poll \`links.self\` for status. ###### Content-Type: application/json - **`isPublic` (required)** `boolean` — Whether the review is publicly accessible via its URL without authentication - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`status` (required)** `string` — Initial status is always processing - **`type` (required)** `string` - **`url` (required)** `string` — URL to view the review in the Elicit web interface **Example:** ```json { "type": "systematicReview", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "url": "", "isPublic": true, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ##### Status: 400 Invalid request. Check that the config matches the schema — e.g. each enabled stage has at least one source of material (\`criteria\` / \`questions\` and/or \`generate\`). ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 Access denied. Either API access is not available on your plan, or the systematic-reviews surface requires features your plan does not include (guided flow, or figure extraction when \`useFigures: true\`). ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Get systematic review status and results - **Method:** `GET` - **Path:** `/sessions/systematic-reviews/{sessionId}` - **Tags:** Systematic Reviews Poll the status of a systematic review created via `POST /api/v2/sessions/systematic-reviews`. ### Status transitions - **processing** — the pipeline is running. Watch progress at `url`. - **pausedForInsufficientQuota** — the account exceeded its usage limit mid-run. The review stays paused until resumed via the `links.resume` URL (or the Elicit web interface) once the limit is resolved. - **completed** — the pipeline finished. Stage-organized exports appear under `data`. Only stages that actually ran are included. - **failed** — something went wrong. The `error` field contains details. `data` may still contain exports for stages that completed before the failure. - **unknown** — status is not tracked (legacy or user-created). ### Response shape `data` is populated as soon as each stage's outputs land — you don't need to wait for `status: completed`. Stages that haven't produced data yet (or that aren't part of this review's config) are simply omitted. - `data.search.{csv,xlsx}` — gather-stage paper list. - `data.screen.{csv,xlsx}` — abstract-screening results. - `data.fulltext.{csv,xlsx}` — fulltext-screening results (only when fulltext screening is configured). - `data.extract.{csv,xlsx}` — extraction-stage results. - `data.report` — structured content under `result`, plus optional `pdf` / `docx` / `txt` (APA reference list) / `bib` (BibTeX) / `ris` presigned download URLs. All stage URLs are presigned for 7 days and serve with `Content-Disposition: attachment` so browser downloads land with the canonical filename. `dataFreshness` is the ISO timestamp when the cached exports were last regenerated, or `null` when nothing has been generated yet. ### Including the full report body By default, `data.report.result.reportBody` and `data.report.result.abstract` are omitted to keep responses light. Append `?include=reportBody` to include them. #### Responses ##### Status: 200 Systematic review status and results (if completed). ###### Content-Type: application/json - **`dataFreshness` (required)** `string | null` — ISO timestamp when the exports in \`data\` were last written to S3. null when no exports have been generated yet — see \`exportsStatus\` for why. - **`executionStage` (required)** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage. Advances through gathering\_sources → screening\_abstract → screening\_fulltext → extracting\_data → generating\_report → done. Null when the stage isn't known — treat it as unknown, not as not-started. - **`exportsStatus` (required)** `string`, possible values: `"ready", "generating", "unavailable"` — Availability of the export download URLs in \`data\`. \`ready\`: the URLs reflect the latest complete export set. \`generating\`: exports are currently being generated and nothing is cached yet. \`unavailable\`: export generation failed and nothing is cached — the structured report content still ships. - **`isPublic` (required)** `boolean` — Whether the review is publicly accessible via its URL without authentication - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status. Transitions: processing ⇄ pausedForInsufficientQuota (paused when the account exceeds its usage limit; stays paused until explicitly resumed via the resume endpoint or the Elicit web interface), processing → completed/failed. Poll until completed or failed. - **`type` (required)** `string` - **`url` (required)** `string` — URL to view the review in the Elicit web interface - **`data`** `object` — Stage-organized content and export URLs: per-stage \`search\`/\`screen\`/\`fulltext\`/\`extract\` CSV + XLSX downloads and \`report\` content plus pdf/docx/txt/bib/ris downloads. When \`exportsStatus\` is \`ready\`, stages absent from \`data\` did not run; when it is \`generating\` or \`unavailable\`, download URLs are temporarily missing rather than nonexistent. - **`extract`** `object` — Extraction-stage results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`fulltext`** `object` — Fulltext-screening results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`report`** `object` — Report-stage content and exports. - **`result` (required)** `object` — Structured report content (title, summary, optional body + abstract). - **`summary` (required)** `string` — AI-generated executive summary of the findings - **`title` (required)** `string` — Auto-generated title - **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. - **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. - **`bib`** `string`, format: `uri` — Presigned URL for a BibTeX bibliography of the papers synthesized in the report. Expires in 7 days. - **`docx`** `string`, format: `uri` — Presigned URL for the report DOCX. Expires in 7 days. - **`pdf`** `string`, format: `uri` — Presigned URL for the report PDF. Expires in 7 days. - **`ris`** `string`, format: `uri` — Presigned URL for a RIS bibliography of the papers synthesized in the report. Expires in 7 days. - **`txt`** `string`, format: `uri` — Presigned URL for an APA-style plain-text reference list of the papers synthesized in the report. Expires in 7 days. - **`screen`** `object` — Abstract-screening results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`search`** `object` — Gather-stage paper list exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`error`** `object` — Error details, only present when status is failed - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "type": "systematicReview", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "url": "", "isPublic": true, "error": { "code": "", "message": "" }, "data": { "search": { "csv": "", "xlsx": "" }, "screen": { "csv": "", "xlsx": "" }, "fulltext": { "csv": "", "xlsx": "" }, "extract": { "csv": "", "xlsx": "" }, "report": { "result": { "title": "", "summary": "", "reportBody": null, "abstract": null }, "pdf": "", "docx": "", "txt": "", "bib": "", "ris": "" } }, "dataFreshness": null, "exportsStatus": "ready", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ##### Status: 401 Authentication failed. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Review not found. Either the review ID is invalid or the review belongs to a different user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### List sessions - **Method:** `GET` - **Path:** `/sessions` - **Tags:** Sessions List all sessions — reports, systematic reviews, and research-agent sessions — for the authenticated user in a single feed, ordered by creation date (newest first). Each item carries its `sessionId`, a `type` field (`report`, `systematicReview`, or `agent`), and a `links` object with the URLs for the item's follow-up requests: `links.self` is the typed get endpoint for its full status and results, and `links.resume` appears only while the session is paused for insufficient quota. Agent items omit `executionStage` (agent sessions have no pipeline stages); for them `status: "completed"` means idle and awaiting input rather than terminally finished. Results are paginated using cursor-based pagination. Use the `nextCursor` value from the response to fetch the next page. Filters apply to all session types; pass `type` to list a single kind. ### Example ```bash # First page curl https://elicit.com/api/v2/sessions?limit=10 \ -H "Authorization: Bearer elk_live_your_key_here" # Next page curl "https://elicit.com/api/v2/sessions?limit=10&cursor=2025-06-15T14:30:00.000Z_5ad08bfb-cbe0-4911-a8c3-309760d33029" \ -H "Authorization: Bearer elk_live_your_key_here" # Only reports created via the API curl "https://elicit.com/api/v2/sessions?type=report&source=api" \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 List of sessions. ###### Content-Type: application/json - **`nextCursor` (required)** `string | null` — Opaque cursor for the next page; pass it back as \`cursor\`. Null if there are no more results. - **`sessions` (required)** `array` — Reports, systematic reviews, and research-agent sessions interleaved, ordered by creation date (newest first) **Items:** - **`createdAt` (required)** `string` — ISO 8601 timestamp of when the report was created - **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`source` (required)** `string`, possible values: `"user", "api", "mcp", "agent_session"` — How the report was created - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the report - **`title` (required)** `string` — Report title (the research question) - **`type` (required)** `string`, possible values: `"report", "systematicReview", "agent"` — Which kind of session this is; use it to pick the matching typed get endpoint - **`url` (required)** `string` — URL to view the report in the Elicit web interface - **`executionStage`** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage, or null when not yet known. Omitted entirely for agent sessions, which have no pipeline stages. - **`role`** `string`, possible values: `"owner", "shared"` — The caller's relationship to this session: "owner" for a session the caller created, or "shared" for an agent session another user shared with them read-only. Reports and systematic reviews are always "owner". - **`totalCount` (required)** `integer` — Total sessions matching the filters across all pages. **Example:** ```json { "sessions": [ { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "title": "What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "source": "api", "createdAt": "2025-06-15T14:30:00.000Z", "isPublic": false, "role": "owner", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ], "nextCursor": "2025-06-15T14:30:00.000Z_5ad08bfb-cbe0-4911-a8c3-309760d33029", "totalCount": 1 } ``` ##### Status: 401 Authentication failed. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Resume a paused session - **Method:** `POST` - **Path:** `/sessions/{sessionId}/resume` - **Tags:** Sessions Resume a report, systematic review, or research-agent session that was automatically paused because your account was over its usage limit (`status: "pausedForInsufficientQuota"` from the get endpoints). Pass the `sessionId` from the create response or `GET /api/v2/sessions` — the session type is resolved automatically. Paused sessions also carry a ready-made `links.resume` URL for this endpoint. A paused session stays paused until it is explicitly resumed. Once the usage limit is resolved (for example after upgrading or when a new billing period starts), call this endpoint — or use the resume banner in the Elicit web interface — to continue the run. ### Example ```bash curl -X POST https://elicit.com/api/v2/sessions/{sessionId}/resume \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 Session resumed. \`status\` reflects the row after the resume; poll \`links.self\` for progress. ###### Content-Type: application/json - **`executionStage` (required)** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — The stage the session resumed at - **`isPublic` (required)** `boolean` - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Status after the resume — normally processing; completed or failed if the run finished while the resume was in flight. - **`type` (required)** `string`, possible values: `"report", "systematicReview", "agent"` — Which kind of session was resumed - **`url` (required)** `string` — URL to view this session in the Elicit web interface **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "screening_abstract", "url": "", "isPublic": true, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ##### Status: 401 Authentication failed. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Session not found. Either the session ID is invalid or the session belongs to a different user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 409 The session is not currently paused, so there is nothing to resume. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Share a session - **Method:** `POST` - **Path:** `/sessions/{sessionId}/shares` - **Tags:** Sessions Share a session read-only with another person by email. Works for every session type — reports, systematic reviews, and Research Agent sessions. Sessions are shared read-only: the recipient can view the session but cannot modify, resume, stop, or re-share it (agent sessions are read-only by design; report and systematic-review shares are read-only through the API). If the email belongs to an existing Elicit account the share takes effect immediately (`status: "registered"`). Otherwise a pending invitation is created and an email is sent (`status: "invited"`); the share activates when they create an account. Only the session owner can manage shares. A recipient of a shared **agent** session sees it in `GET /api/v2/sessions` with `role: "shared"`; a recipient of a shared **report** or **systematic review** opens it via the returned web-app `url` — it will **not** appear in their `GET /api/v2/sessions` list, which stays owner-only for review sessions. ### Example ```bash curl -X POST https://elicit.com/api/v2/sessions/{sessionId}/shares \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"email":"colleague@example.com"}' ``` #### Request Body ##### Content-Type: application/json - **`email` (required)** `string`, format: `email` — Email address to share the session with, as a read-only recipient. **Example:** ```json { "email": "colleague@example.com" } ``` #### Responses ##### Status: 201 The session was shared with the recipient. ###### Content-Type: application/json - **`sessionId` (required)** `string` — Unique identifier for the session. - **`share` (required)** `object` - **`email` (required)** `string` — Email address the session is shared with. - **`role` (required)** `string` — Access level of the share. Sessions are always shared read-only. - **`status` (required)** `string`, possible values: `"registered", "invited"` — "registered" when the recipient already has an Elicit account and can read the session now; "invited" when a pending invitation was created for an email without an account. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "share": { "email": "colleague@example.com", "status": "registered", "role": "reader" }, "url": "" } ``` ##### Status: 400 Invalid request. The email is missing/malformed, or it is the caller's own address (you cannot share a session with yourself). ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 The share could not be created: the session's recipient cap was reached, or inviting people without an Elicit account is not available on this account. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Session not found. The session ID is invalid or belongs to a different user (or, for an agent session, the Research Agent API is not enabled for this account). ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### List a session's shares - **Method:** `GET` - **Path:** `/sessions/{sessionId}/shares` - **Tags:** Sessions List everyone a session is shared with **read-only** — both registered recipients and pending email invitations. Reports and systematic reviews can also have editors or reviewers added in the Elicit web app; those higher-permission collaborators are managed there and are not returned here. Only the session owner can list shares. ### Example ```bash curl https://elicit.com/api/v2/sessions/{sessionId}/shares \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 The session's current read-only shares. ###### Content-Type: application/json - **`sessionId` (required)** `string` — Unique identifier for the session. - **`shares` (required)** `array` — Everyone the session is currently shared with — both registered recipients and pending email invitations. **Items:** - **`email` (required)** `string` — Email address the session is shared with. - **`role` (required)** `string` — Access level of the share. Sessions are always shared read-only. - **`status` (required)** `string`, possible values: `"registered", "invited"` — "registered" when the recipient already has an Elicit account and can read the session now; "invited" when a pending invitation was created for an email without an account. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "shares": [ { "email": "colleague@example.com", "status": "registered", "role": "reader" } ], "url": "" } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Session not found. The session ID is invalid or belongs to a different user (or, for an agent session, the Research Agent API is not enabled for this account). ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Revoke a session share - **Method:** `DELETE` - **Path:** `/sessions/{sessionId}/shares` - **Tags:** Sessions Revoke a read-only share by email. Removes either an active share (for a registered recipient) or a pending invitation. Only the session owner can revoke shares. The operation is idempotent: revoking an email that isn't currently shared returns `revoked: false` with `200 OK`. ### Example ```bash curl -X DELETE https://elicit.com/api/v2/sessions/{sessionId}/shares \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"email":"colleague@example.com"}' ``` #### Request Body ##### Content-Type: application/json - **`email` (required)** `string`, format: `email` — Email address whose share (or pending invite) should be revoked. **Example:** ```json { "email": "colleague@example.com" } ``` #### Responses ##### Status: 200 The share was revoked, or there was nothing to revoke (idempotent). ###### Content-Type: application/json - **`email` (required)** `string` — Email address whose share was revoked. - **`revoked` (required)** `boolean` — Whether an existing share or pending invite was removed. False when there was nothing to revoke (the call is idempotent either way). - **`sessionId` (required)** `string` — Unique identifier for the session. **Example:** ```json { "sessionId": "", "email": "", "revoked": true } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Session not found. The session ID is invalid or belongs to a different user (or, for an agent session, the Research Agent API is not enabled for this account). ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Get usage status - **Method:** `GET` - **Path:** `/usage` - **Tags:** Usage Report the authenticated account's current usage against its plan. Returns whether the account still has usage available (`hasUsageRemaining`), the percentage of plan usage consumed this billing period, the billing-period bounds, and — only when extra usage is enabled — the extra-usage spend and limit in USD cents. ### Example ```bash curl https://elicit.com/api/v2/usage \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 Current usage status. ###### Content-Type: application/json - **`extraUsage` (required)** `object` — Extra-usage amount and limit in USD cents. Null when extra usage is not enabled. - **`hasUsageRemaining` (required)** `boolean` — Whether the account still has usage available this billing period. False once both the plan limit and (if enabled) the extra-usage limit are exhausted. - **`percentUsed` (required)** `number` — Percentage of plan usage consumed this billing period. - **`periodEnd` (required)** `string` — ISO 8601 end of the current billing period. Monthly usage limits reset at this time. - **`periodStart` (required)** `string` — ISO 8601 start of the current billing period. **Example:** ```json { "hasUsageRemaining": true, "percentUsed": 1, "periodStart": "", "periodEnd": "", "extraUsage": { "limitUsdCents": null, "spentUsdCents": 1 } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 409 Usage reporting is not available for this account, or usage data is not ready yet. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Create a Research Agent session - **Method:** `POST` - **Path:** `/sessions/agents` - **Tags:** Research Agent Start a stateful Research Agent session. Elicit investigates the query asynchronously, reports its activity as structured events, and may produce downloadable artifacts. The response returns immediately with a `sessionId`. Use the events endpoint to follow the research, then send messages to refine or continue it. The session is also available at the returned `url`. This endpoint is in early access. It returns `404 not_found` unless the Research Agent API has been enabled for the authenticated account or organization. ### End-to-end workflow A full research task may involve several requests against a single session. To drive it end to end: 1. **(Optional) Upload files.** POST /api/v2/files, PUT the bytes to the presigned URL, and keep each `file_id` (see the Upload endpoint). 2. **Create the session.** POST /api/v2/sessions/agents with your `query` and any `attachments`. The response is immediate with `status: "processing"` and a `sessionId`. 3. **Poll for activity.** GET /api/v2/sessions/agents/:sessionId/events. Pass the returned `cursor` unchanged on each subsequent poll to receive immutable event occurrences not observed at that checkpoint. Append them in response order and deduplicate retries by `eventId`. Poll every 3–10 seconds while the top-level `status` is `processing`. 4. **Detect idle.** The agent is ready for another request when a `session_idle` event appears and the top-level `status` returns to `completed`. For a Research Agent session, `completed` means **idle and awaiting input** — not that the session is permanently closed. Watch for these events along the way: - `question` — the agent needs input; answer it with a follow-up message. - `error` — the agent encountered an error; `retryable` indicates whether resending is worthwhile. - `session_paused` — the account hit its usage limit; the status becomes `pausedForInsufficientQuota`. Resolve the limit, then resume the session via POST /api/v2/sessions/:sessionId/resume (or the Elicit web interface) before continuing. 5. **Send a follow-up.** POST /api/v2/sessions/agents/:sessionId/messages with your message (and any `attachments`). Correlate the returned `messageId` with the matching `user_message` event, then return to step 3. 6. **Retrieve artifacts.** GET /api/v2/sessions/agents/:sessionId/artifacts to list what the agent produced: files appear under `artifacts` (GET .../artifacts/:artifactId/download for a short-lived presigned download URL — treat it as a credential), and interactive outputs (tables, prose, presentations, figures) appear under `deliveredOutputs` (GET .../artifacts/:artifactId/content for their contents). 7. **(Optional) Stop early.** POST /api/v2/sessions/agents/:sessionId/stop to interrupt a running turn, then poll the events endpoint for the `session_stopped` event. ### Session status The list, detail, and events endpoints all report the same top-level `status`: - `processing` — the agent is working (or the session has not started yet). - `completed` — idle and awaiting input; the latest work finished successfully. - `failed` — the latest work ended with an error. - `pausedForInsufficientQuota` — paused at the account usage limit; resume once the limit clears. - `unknown` — status could not be determined (legacy sessions only). All errors return the standard `{ "error": { "code", "message" } }` envelope. ### Example ```bash # Minimal curl -X POST https://elicit.com/api/v2/sessions/agents \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"query":"What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?"}' # With an uploaded file attached to the initial turn curl -X POST https://elicit.com/api/v2/sessions/agents \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"query":"Summarize the attached trial and compare it to the current literature.","attachments":[{"file_id":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"}]}' ``` #### Request Body ##### Content-Type: application/json - **`query` (required)** `string` — The initial query for the research agent. Elicit creates a stateful research session that investigates the query. The session is continuable in the Elicit web interface. - **`attachments`** `array` — Files to attach to this turn, each referencing a file\_id from POST /api/v2/files. Attached files are made available to the research agent exactly as uploads made in the web interface are. **Items:** - **`file_id` (required)** `string`, format: `uuid` — The file\_id returned by POST /api/v2/files for a previously uploaded file. **Example:** ```json { "query": "What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?", "attachments": [ { "file_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" } ] } ``` #### Responses ##### Status: 202 Session creation accepted. The Research Agent is processing the initial query asynchronously. ###### Content-Type: application/json - **`sessionId` (required)** `string` — Unique identifier for the research agent session. - **`status` (required)** `string` — Initial status is always processing. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "status": "processing", "url": "https://elicit.com/agent/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" } ``` ##### Status: 400 Invalid request. \`query\` must contain 1–2,000 characters. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Research Agent API early access is not enabled for this account. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Get Research Agent session status - **Method:** `GET` - **Path:** `/sessions/agents/{sessionId}` - **Tags:** Research Agent Fetch the status and basic metadata of a research-agent session — the typed detail endpoint that an agent item's `links.self` in `GET /api/v2/sessions` points to. ### Status values - **processing** — The agent is working, or the session is queued and hasn't started. - **completed** — The agent is idle and awaiting input. This is *not* a terminal state: the session can be continued (agent sessions have no terminal "finished" state). - **failed** — The last turn ended with an error. - **pausedForInsufficientQuota** — The account exceeded its usage limit. The session stays paused until resumed via the `links.resume` URL (or the Elicit web interface). No event payload is returned here; use the session's events endpoint for the reduced activity stream. ### Example ```bash curl https://elicit.com/api/v2/sessions/agents/{sessionId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 Research-agent session status and metadata. ###### Content-Type: application/json - **`createdAt` (required)** `string` — ISO 8601 timestamp of when the session was created. - **`isPublic` (required)** `boolean` — Whether the session is publicly accessible via its URL without authentication. - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`source` (required)** `string`, possible values: `"user", "api", "mcp", "agent_session"` — How the session was created. - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the session: "processing" (running, or not yet started), "completed" (idle and awaiting input — not terminally finished), "failed" (the last turn ended with an error), or "pausedForInsufficientQuota" (paused at the account usage limit; resume once the limit clears). - **`title` (required)** `string` — Human-readable title of the session. - **`type` (required)** `string` — Discriminator identifying this as a research-agent session. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "type": "agent", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "title": "", "url": "", "source": "api", "createdAt": "2025-06-15T14:30:00.000Z", "isPublic": true, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The Research Agent API is not enabled for this account, or the session does not exist or belongs to another user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Get Research Agent session events - **Method:** `GET` - **Path:** `/sessions/agents/{sessionId}/events` - **Tags:** Research Agent Get a reduced view of a Research Agent session's activity. Streaming text, thinking, and tool-input deltas are collapsed into complete typed entries. With no `cursor`, the response contains the full reduced history. Pass the returned cursor unchanged on the next poll to receive immutable event occurrences not observed at that checkpoint. The public event kinds are `user_message`, `agent_message`, `question`, `activity`, `artifacts_delivered`, `delivered_outputs`, `error`, `session_idle`, `session_paused`, `session_resumed`, `stop_requested`, and `session_stopped`. Internal tool names, sandbox paths, raw tool results, and candidate counters are never returned. Every event includes a stable `eventId` and an ISO 8601 `createdAt` timestamp when available. Events are immutable and append-only. A resource can have several snapshots: for example, an `activity` may first be `started` and later `completed`. Those occurrences share an `activityId` but have distinct `eventId` values. Append incremental responses in response order and deduplicate retries by `eventId`. The top-level `status` has exactly the same meaning and value as the list and detail endpoints. Lifecycle facts that are not part of the shared session status vocabulary are represented by explicit events: the agent becomes ready for more input with `session_idle`, a stop completes with `session_stopped`, and pause/resume use `session_paused`/`session_resumed`. ### Polling example ```bash # Full history curl https://elicit.com/api/v2/sessions/agents/{sessionId}/events \ -H "Authorization: Bearer elk_live_your_key_here" # Only event occurrences not observed at the cursor checkpoint curl "https://elicit.com/api/v2/sessions/agents/{sessionId}/events?cursor={cursor}" \ -H "Authorization: Bearer elk_live_your_key_here" ``` Poll every 3–10 seconds while `status` is `processing`. The agent is ready for another request when a `session_idle` event appears and the status returns to `completed` (idle, awaiting input). A `question` event indicates that the agent needs input. A `session_stopped` event confirms that a stop request was processed. If a cursor is rejected, refetch once without a cursor and rebuild local event state. #### Responses ##### Status: 200 Full or incremental reduced session activity. ###### Content-Type: application/json - **`cursor` (required)** `string` — Opaque session-bound checkpoint. Always present. Pass it unchanged as the \`cursor\` query param on the next poll to receive later event occurrences. - **`events` (required)** `array` — Append-only view of the session's activity. Streaming deltas are collapsed into immutable resource snapshots; raw stream events are never returned. Later snapshots retain the same resource ID and receive a new eventId. With no cursor this is the full history; with a cursor it contains only later occurrences. **Items:** **One of:** - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`isInitial` (required)** `boolean` - **`kind` (required)** `string` - **`messageId` (required)** `string` - **`text` (required)** `string` * **`citations` (required)** `array` **Items:** - **`citationId` (required)** `string` — Identifier for this citation within the agent message. - **`quote` (required)** `string` — The passage from the source that supports the message. - **`reference` (required)** `string | null` — The inline citation this entry resolves. It matches, character for character, a single reference token inside the \`\…\\` markup in the message text (one entry per token, after comma-separated tokens are split). Use it to map inline references in the text to this citation; use the \`source\` field to identify the underlying source. \`null\` for citations with no inline reference (e.g. legacy quotes-array or artifact-content citations). - **`source` (required)** `object` - **`authors` (required)** `array` — Authors of the cited work, in display order. **Items:** `string` - **`doi` (required)** `string | null` — Digital Object Identifier (DOI), when available. - **`title` (required)** `string | null` — Title of the cited work. - **`url` (required)** `string | null` — Best available URL for the cited work. - **`venue` (required)** `string | null` — Journal, conference, repository, or other publication venue. - **`year` (required)** `integer | null` — Publication year. * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` * **`messageId` (required)** `string` * **`suggestedFollowUps` (required)** `array` **Items:** `string` * **`text` (required)** `string` — The agent's reply. Contains inline \`\…\\` markup wrapping one or more comma-separated reference tokens; split them and match each token against \`citations\[].reference\` to resolve it. Strip the markup for display. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` - **`options` (required)** `array | null` - **`prefilledText` (required)** `string | null` - **`questionId` (required)** `string` - **`responseFormat` (required)** `string`, possible values: `"text", "single_select", "multi_select"` - **`text` (required)** `string` * **`activityId` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` * **`status` (required)** `string`, possible values: `"started", "completed", "failed"` * **`summary` (required)** `string | null` * **`title` (required)** `string` - **`artifacts` (required)** `array` **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the artifact, stable within a session. Pass it to the download endpoint to retrieve the file. Never a raw storage key. - **`contentType` (required)** `string | null` — MIME type of the artifact, when known. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was produced, when known. - **`filename` (required)** `string` — Suggested filename for the downloaded artifact. - **`format` (required)** `string | null` — Subtype within the artifact (e.g. "pdf", "docx", "pptx"). For agent files it is the filename extension; null only when the filename has no extension. - **`kind` (required)** `string`, possible values: `"agent-saved-file", "agent-delivered-file", "prose-export", "presentation-export", "figure-export", "report-asset", "report-citation"` — The kind of artifact produced in the session. A delivered file lists once as "agent-delivered-file"; "agent-saved-file" denotes a file the agent saved to its workspace but did not deliver. - **`sizeBytes` (required)** `number | null` — Size of the artifact in bytes, when known. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`deliveredOutputs` (required)** `array` — Artifacts delivered by this source-history occurrence. This is an immutable metadata snapshot; query the artifacts resource for currently supported download formats. **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, stable within a session. Pass it to the artifact content endpoint to retrieve its contents. Never a raw storage key or entity hash. - **`caption` (required)** `string | null` — Optional caption describing the artifact. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was delivered, when known. - **`kind` (required)** `string`, possible values: `"table", "prose", "presentation", "figure"` — The kind of interactive artifact: table, prose, presentation, or figure. - **`rowCount` (required)** `integer | null` — Number of rows for a table artifact; null for non-table kinds. - **`title` (required)** `string` — Human-readable title of the artifact. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`code` (required)** `string`, possible values: `"agent_timed_out", "agent_api_error", "agent_failed"` - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` - **`message` (required)** `string` - **`retryable` (required)** `boolean` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`sessionId` (required)** `string` — Unique identifier for the research agent session. - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the session. Uses exactly the same value and semantics as the list and detail endpoints. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "processing", "events": [ { "eventId": "", "createdAt": null, "kind": "user_message", "messageId": "", "text": "", "isInitial": true } ], "cursor": "", "url": "" } ``` ##### Status: 400 The cursor is malformed, belongs to another session, or is ahead of the session's current position. Retry without a cursor. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The Research Agent API is not enabled for this account, or the session does not exist or belongs to another user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Send a message to a Research Agent session - **Method:** `POST` - **Path:** `/sessions/agents/{sessionId}/messages` - **Tags:** Research Agent Insert a follow-up message and start another asynchronous turn. Use messages to refine a result, answer the agent, redirect the research, or request another artifact. The response includes a `messageId`. The corresponding `user_message` event carries the same value, allowing the client to confirm delivery. Attach previously uploaded files by including their `file_id`s in the `attachments` array (see the Upload endpoint). If the session is paused for insufficient quota, resolve the usage limit and resume it via `POST /api/v2/sessions/:sessionId/resume` (or the Elicit web interface) before sending another message. ### Example ```bash curl -X POST https://elicit.com/api/v2/sessions/agents/{sessionId}/messages \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"message":"Focus on randomized controlled trials only."}' ``` #### Request Body ##### Content-Type: application/json - **`message` (required)** `string` — The message to insert into the running research agent session. - **`attachments`** `array` — Files to attach to this turn, each referencing a file\_id from POST /api/v2/files. Attached files are made available to the research agent exactly as uploads made in the web interface are. **Items:** - **`file_id` (required)** `string`, format: `uuid` — The file\_id returned by POST /api/v2/files for a previously uploaded file. **Example:** ```json { "message": "Focus on randomized controlled trials only.", "attachments": [ { "file_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" } ] } ``` #### Responses ##### Status: 202 Message accepted. The session is processing another turn. ###### Content-Type: application/json - **`messageId` (required)** `string` — Identifier of the inserted message. Correlate it with the messageId on the matching user\_message event. - **`sessionId` (required)** `string` — Unique identifier for the research agent session. - **`status` (required)** `string` — The session is processing the inserted message. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "processing", "messageId": "", "url": "" } ``` ##### Status: 400 Invalid request. \`message\` must contain 1–2,000 characters. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The Research Agent API is not enabled for this account, or the session does not exist or belongs to another user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 409 The session failed or is paused for insufficient quota and cannot accept a message. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Upload a file - **Method:** `POST` - **Path:** `/files` - **Tags:** Research Agent, Library Stage a file so it can be attached to a Research Agent turn or imported into your library. This is a two-step, presigned upload: 1. **POST /api/v2/files** with the filename, MIME type, and exact byte size. The response returns a `file_id` and a short-lived presigned `upload_url`. 2. **PUT** the raw file bytes to `upload_url` with the same `Content-Type` and a `Content-Length` matching `size_bytes`. Do not send an `Authorization` header on the PUT — the URL is already signed. Then either pass `{ "file_id": "..." }` in the `attachments` array of a create-session or send-message request — attached files are made available to the agent exactly as uploads made in the web interface are — or pass the `file_id` in `fileIds` to `POST /api/v2/library/imports` to parse the PDF into your library. A staged file can be used once. The request/response fields for this endpoint are deliberately `snake_case` (`content_type`, `size_bytes`, `file_id`, `upload_url`, `expires_at`), unlike the camelCase used elsewhere in the v2 surface. Files are capped at 30 MB, and a session accepts a bounded number of attachments; the `upload_url` and `file_id` expire at `expires_at`. This endpoint is in early access. It returns `404 not_found` unless the Research Agent API has been enabled for the authenticated account or organization. ### Example ```bash # 1. Register the upload curl -X POST https://elicit.com/api/v2/files \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"filename":"trial-results.pdf","content_type":"application/pdf","size_bytes":245678}' # 2. Upload the bytes to the returned upload_url curl -X PUT "{upload_url}" \ -H "Content-Type: application/pdf" \ --data-binary @trial-results.pdf # 3. Attach {"file_id": "..."} to a create-session or /messages request, # or import it with POST /library/imports {"fileIds": ["..."]} ``` #### Request Body ##### Content-Type: application/json - **`content_type` (required)** `string` — MIME type of the file. - **`filename` (required)** `string` — Original filename of the upload. Used as the display name in the session. - **`size_bytes` (required)** `integer` — Exact size of the file in bytes. Must match the uploaded object exactly. Maximum 31457280 bytes (30 MB). **Example:** ```json { "filename": "trial-results.pdf", "content_type": "application/pdf", "size_bytes": 245678 } ``` #### Responses ##### Status: 200 Upload registered. PUT the file bytes to \`upload\_url\` before it expires. ###### Content-Type: application/json - **`expires_at` (required)** `string` — ISO 8601 timestamp after which the upload URL and the staged file\_id are no longer valid. - **`file_id` (required)** `string` — Opaque identifier for the staged upload. Pass it in the \`attachments\` array of a create-session or send-message request to attach the file to that turn. - **`upload_url` (required)** `string` — Short-lived presigned S3 PUT URL. Upload the file bytes directly to it with the same Content-Type and Content-Length declared here. **Example:** ```json { "file_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "upload_url": "", "expires_at": "2026-07-23T15:00:00.000Z" } ``` ##### Status: 400 Invalid request. The filename, content type, or size is missing or invalid, or the size exceeds the 30 MB limit. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 402 Insufficient quota. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Research Agent API early access is not enabled for this account. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### List Research Agent session artifacts - **Method:** `GET` - **Path:** `/sessions/agents/{sessionId}/artifacts` - **Tags:** Research Agent List files and interactive outputs produced in a Research Agent session. File-backed artifacts are listed under `artifacts`. Only the latest version of each is listed. A delivered file appears once as `agent-delivered-file`; `agent-saved-file` denotes a workspace file that the agent saved but did not deliver. Interactive outputs delivered as session outputs (tables, prose, presentations, figures) are listed under `deliveredOutputs`; retrieve their contents from the artifact content endpoint. Use the opaque, session-scoped `artifactId` with the download endpoint (for `artifacts`) or the content endpoint (for `deliveredOutputs`). Do not construct or decode artifact IDs. ### Example ```bash curl https://elicit.com/api/v2/sessions/agents/{sessionId}/artifacts \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 Latest artifacts produced in the session. ###### Content-Type: application/json - **`artifacts` (required)** `array` — File-backed artifacts produced in the session. Only the latest version of each artifact is listed. Retrieve contents via the download endpoint. **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the artifact, stable within a session. Pass it to the download endpoint to retrieve the file. Never a raw storage key. - **`contentType` (required)** `string | null` — MIME type of the artifact, when known. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was produced, when known. - **`filename` (required)** `string` — Suggested filename for the downloaded artifact. - **`format` (required)** `string | null` — Subtype within the artifact (e.g. "pdf", "docx", "pptx"). For agent files it is the filename extension; null only when the filename has no extension. - **`kind` (required)** `string`, possible values: `"agent-saved-file", "agent-delivered-file", "prose-export", "presentation-export", "figure-export", "report-asset", "report-citation"` — The kind of artifact produced in the session. A delivered file lists once as "agent-delivered-file"; "agent-saved-file" denotes a file the agent saved to its workspace but did not deliver. - **`sizeBytes` (required)** `number | null` — Size of the artifact in bytes, when known. - **`deliveredOutputs` (required)** `array` — Interactive outputs (tables, prose, presentations, figures) delivered as session outputs. Only the latest delivery of each is listed. Retrieve contents via the artifact content endpoint. **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, stable within a session. Pass it to the artifact content endpoint to retrieve its contents. Never a raw storage key or entity hash. - **`caption` (required)** `string | null` — Optional caption describing the artifact. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was delivered, when known. - **`downloadFormats` (required)** `array` — File formats this artifact can be downloaded as from the content endpoint via ?format=\ (tables: csv/xlsx; prose: md; empty for other kinds). The JSON body is returned when no format is given. **Items:** `string`, possible values: `"csv", "xlsx", "md"` - **`kind` (required)** `string`, possible values: `"table", "prose", "presentation", "figure"` — The kind of interactive artifact: table, prose, presentation, or figure. - **`rowCount` (required)** `integer | null` — Number of rows for a table artifact; null for non-table kinds. - **`title` (required)** `string` — Human-readable title of the artifact. - **`sessionId` (required)** `string` — Unique identifier for the research agent session. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "artifacts": [ { "artifactId": "", "kind": "agent-saved-file", "format": null, "filename": "", "contentType": null, "sizeBytes": null, "createdAt": "2025-06-15T14:30:00.000Z" } ], "deliveredOutputs": [ { "artifactId": "", "kind": "table", "title": "", "caption": null, "rowCount": null, "createdAt": "2025-06-15T14:30:00.000Z", "downloadFormats": [ "csv" ] } ], "url": "" } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The Research Agent API is not enabled for this account, or the session does not exist or belongs to another user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Get interactive artifact contents - **Method:** `GET` - **Path:** `/sessions/agents/{sessionId}/artifacts/{artifactId}/content` - **Tags:** Research Agent Materialize the contents of an interactive artifact listed under `deliveredOutputs` on the list-artifacts endpoint. The response is structured JSON discriminated on `kind`: tables carry `columns` and `rows`; prose and figures carry supported content (cleaned text, the original markdown, and resolved citations); presentations carry slides. The default `format` is `json` (omitting the parameter is equivalent to `?format=json`). Tables can also be downloaded with `?format=csv` or `?format=xlsx`, and prose with `?format=md`. File responses are served with `Content-Disposition: attachment`, not as JSON. Unsupported kind/format combinations return `400 download_not_available`. ### Example ```bash # Structured JSON curl https://elicit.com/api/v2/sessions/agents/{sessionId}/artifacts/{artifactId}/content \ -H "Authorization: Bearer elk_live_your_key_here" # Table as CSV curl "https://elicit.com/api/v2/sessions/agents/{sessionId}/artifacts/{artifactId}/content?format=csv" \ -H "Authorization: Bearer elk_live_your_key_here" \ -O -J # Prose as portable Markdown curl "https://elicit.com/api/v2/sessions/agents/{sessionId}/artifacts/{artifactId}/content?format=md" \ -H "Authorization: Bearer elk_live_your_key_here" \ -O -J ``` #### Responses ##### Status: 200 Contents of the interactive artifact: structured JSON, a CSV/XLSX file for a table, or a Markdown file for prose. ###### Content-Type: application/json **One of:** - **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, echoing the request. Can also be re-requested with ?format=\ to download as a file (tables: csv/xlsx, prose: md). - **`caption` (required)** `string | null` — Optional caption describing the artifact. - **`columns` (required)** `array` — Ordered column keys for the table, in first-seen order across the rows. **Items:** `string` - **`kind` (required)** `string` - **`rows` (required)** `array` — Table rows, each a mapping from column key to cell. **Items:** - **`title` (required)** `string` — Human-readable title of the artifact. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. * **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, echoing the request. Can also be re-requested with ?format=\ to download as a file (tables: csv/xlsx, prose: md). * **`caption` (required)** `string | null` — Optional caption describing the artifact. * **`content` (required)** `object` - **`citations` (required)** `array` — Citations backing this content, resolved to the same shape as message citations. **Items:** - **`citationId` (required)** `string` — Identifier for this citation within the agent message. - **`quote` (required)** `string` — The passage from the source that supports the message. - **`reference` (required)** `string | null` — The inline citation this entry resolves. It matches, character for character, a single reference token inside the \`\…\\` markup in the message text (one entry per token, after comma-separated tokens are split). Use it to map inline references in the text to this citation; use the \`source\` field to identify the underlying source. \`null\` for citations with no inline reference (e.g. legacy quotes-array or artifact-content citations). - **`source` (required)** `object` - **`authors` (required)** `array` — Authors of the cited work, in display order. **Items:** `string` - **`doi` (required)** `string | null` — Digital Object Identifier (DOI), when available. - **`title` (required)** `string | null` — Title of the cited work. - **`url` (required)** `string | null` — Best available URL for the cited work. - **`venue` (required)** `string | null` — Journal, conference, repository, or other publication venue. - **`year` (required)** `integer | null` — Publication year. - **`markdown` (required)** `string` — The original markdown content, including inline citation markup. - **`text` (required)** `string` — Human-readable content with inline citation markup removed. * **`kind` (required)** `string` * **`title` (required)** `string` — Human-readable title of the artifact. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. - **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, echoing the request. Can also be re-requested with ?format=\ to download as a file (tables: csv/xlsx, prose: md). - **`caption` (required)** `string | null` — Optional caption describing the artifact. - **`kind` (required)** `string` - **`slides` (required)** `array` — Ordered slides, each with a title and supported content. **Items:** - **`content` (required)** `object` - **`citations` (required)** `array` — Citations backing this content, resolved to the same shape as message citations. **Items:** - **`citationId` (required)** `string` — Identifier for this citation within the agent message. - **`quote` (required)** `string` — The passage from the source that supports the message. - **`reference` (required)** `string | null` — The inline citation this entry resolves. It matches, character for character, a single reference token inside the \`\…\\` markup in the message text (one entry per token, after comma-separated tokens are split). Use it to map inline references in the text to this citation; use the \`source\` field to identify the underlying source. \`null\` for citations with no inline reference (e.g. legacy quotes-array or artifact-content citations). - **`source` (required)** `object` - **`authors` (required)** `array` — Authors of the cited work, in display order. **Items:** `string` - **`doi` (required)** `string | null` — Digital Object Identifier (DOI), when available. - **`title` (required)** `string | null` — Title of the cited work. - **`url` (required)** `string | null` — Best available URL for the cited work. - **`venue` (required)** `string | null` — Journal, conference, repository, or other publication venue. - **`year` (required)** `integer | null` — Publication year. - **`markdown` (required)** `string` — The original markdown content, including inline citation markup. - **`text` (required)** `string` — Human-readable content with inline citation markup removed. - **`speakerNotes` (required)** `string | null` — Speaker notes, when present. - **`title` (required)** `string` — Slide title. - **`title` (required)** `string` — Human-readable title of the artifact. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. * **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, echoing the request. Can also be re-requested with ?format=\ to download as a file (tables: csv/xlsx, prose: md). * **`caption` (required)** `string | null` — Optional caption describing the artifact. * **`description` (required)** `object` - **`citations` (required)** `array` — Citations backing this content, resolved to the same shape as message citations. **Items:** - **`citationId` (required)** `string` — Identifier for this citation within the agent message. - **`quote` (required)** `string` — The passage from the source that supports the message. - **`reference` (required)** `string | null` — The inline citation this entry resolves. It matches, character for character, a single reference token inside the \`\…\\` markup in the message text (one entry per token, after comma-separated tokens are split). Use it to map inline references in the text to this citation; use the \`source\` field to identify the underlying source. \`null\` for citations with no inline reference (e.g. legacy quotes-array or artifact-content citations). - **`source` (required)** `object` - **`authors` (required)** `array` — Authors of the cited work, in display order. **Items:** `string` - **`doi` (required)** `string | null` — Digital Object Identifier (DOI), when available. - **`title` (required)** `string | null` — Title of the cited work. - **`url` (required)** `string | null` — Best available URL for the cited work. - **`venue` (required)** `string | null` — Journal, conference, repository, or other publication venue. - **`year` (required)** `integer | null` — Publication year. - **`markdown` (required)** `string` — The original markdown content, including inline citation markup. - **`text` (required)** `string` — Human-readable content with inline citation markup removed. * **`kind` (required)** `string` * **`renderer` (required)** `string | null` — Figure renderer, when known. * **`spec` (required)** `string | null` — Figure spec, when known. * **`title` (required)** `string` — Human-readable title of the artifact. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "artifactId": "", "title": "", "caption": null, "url": "", "kind": "table", "columns": [ "" ], "rows": [ { "additionalProperty": { "text": null, "citations": [ { "citationId": "", "reference": null, "quote": "", "source": { "title": null, "authors": [ "" ], "year": null, "doi": null, "url": null, "venue": null } } ], "source": { "title": null, "authors": [ "" ], "year": null, "doi": null, "url": null, "venue": null } } } ] } ``` ###### Content-Type: text/csv `string`, format: `binary` **Example:** ```json {} ``` ###### Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet `string`, format: `binary` **Example:** ```xml ``` ###### Content-Type: text/markdown `string`, format: `binary` **Example:** ```json {} ``` ##### Status: 400 The requested file format is not available for this artifact kind. Tables support CSV/XLSX and prose supports Markdown. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Research Agent API early access is not enabled, the session was not found, or the artifact is not in the session's current deliveredOutputs list. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Create an artifact download URL - **Method:** `GET` - **Path:** `/sessions/agents/{sessionId}/artifacts/{artifactId}/download` - **Tags:** Research Agent Create a short-lived presigned URL for an artifact returned by the list-artifacts endpoint. The URL expires after 30 minutes. Call this endpoint again to issue a fresh URL. Treat the URL as a credential while it is valid: do not log it or store it as a permanent share link. ### Example ```bash curl https://elicit.com/api/v2/sessions/agents/{sessionId}/artifacts/{artifactId}/download \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 Short-lived artifact download URL. ###### Content-Type: application/json - **`contentType` (required)** `string | null` — MIME type of the artifact, when known. - **`downloadUrl` (required)** `string` — Short-lived presigned URL to download the artifact contents. - **`expiresAt` (required)** `string` — ISO 8601 timestamp after which the download URL is no longer valid. - **`filename` (required)** `string` — Suggested filename for the downloaded artifact. **Example:** ```json { "downloadUrl": "", "expiresAt": "2025-06-15T15:00:00.000Z", "filename": "", "contentType": null } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 Research Agent API early access is not enabled, the session was not found, or the artifact is not in the session's current artifact list. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Stop a Research Agent session - **Method:** `POST` - **Path:** `/sessions/agents/{sessionId}/stop` - **Tags:** Research Agent Request an asynchronous interrupt using the same stop action as the Elicit web interface. Stopping does not delete or permanently close the session. The session remains visible and may be continued later. When the response status is `stopping`, poll the events endpoint until a `session_stopped` event appears. The operation is idempotent. If the session is already stopped or failed, it returns the existing state with `200 OK`. ### Example ```bash curl -X POST https://elicit.com/api/v2/sessions/agents/{sessionId}/stop \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 The session had already stopped or failed. ###### Content-Type: application/json - **`sessionId` (required)** `string` — Unique identifier for the research agent session. - **`status` (required)** `string`, possible values: `"stopping", "stopped", "failed"` — "stopping" when a stop was queued (the session halts asynchronously; poll the events endpoint for the session\_stopped event). "stopped" or "failed" when the session had already ended and no stop was needed. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "stopping", "url": "" } ``` ##### Status: 202 The stop request was queued. Poll the events endpoint until the session is stopped. ###### Content-Type: application/json - **`sessionId` (required)** `string` — Unique identifier for the research agent session. - **`status` (required)** `string`, possible values: `"stopping", "stopped", "failed"` — "stopping" when a stop was queued (the session halts asynchronously; poll the events endpoint for the session\_stopped event). "stopped" or "failed" when the session had already ended and no stop was needed. - **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "stopping", "url": "" } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The Research Agent API is not enabled for this account, or the session does not exist or belongs to another user. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### List library sources - **Method:** `GET` - **Path:** `/library/sources` - **Tags:** Library Returns your own sources, newest first. A shared collection's papers are listed with `collectionId`, and each carries your `role`. Filters combine with AND. `q` matches each term as a case-insensitive substring of the title, authors, abstract, venue, or Elicit id. A DOI-shaped term matches the DOI. `doi` and `elicitId` are exact filters. `fullTextStatus` filters by whether parsed full text is attached. Default page size 50, maximum 100. `totalCount` counts all matches, not the page. ### Example ```bash curl "https://elicit.com/api/v2/library/sources?q=semaglutide&fullTextStatus=available" \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 One page of matching sources. ###### Content-Type: application/json - **`nextCursor` (required)** `string | null` — Pass as ?cursor= to fetch the next page; null on the last page. - **`sources` (required)** `array` **Items:** - **`abstract` (required)** `string | null` — Abstract as markdown. - **`authors` (required)** `array` **Items:** `string` - **`collectionIds` (required)** `array` — Collections this source belongs to that are visible to you. **Items:** `string`, format: `uuid` - **`createdAt` (required)** `string` - **`doi` (required)** `string | null` - **`elicitId` (required)** `string | null` — Elicit corpus id, present once the paper has been matched to the corpus. - **`fullTextStatus` (required)** `string`, possible values: `"pending", "available", "unavailable"` — Whether parsed full text is attached: pending — a PDF is still parsing, or none has been looked for yet; available — parsed and attached; unavailable — looked for, none found. - **`id` (required)** `string`, format: `uuid` — Stable id of the source. - **`links` (required)** `object` - **`fullText` (required)** `string` — API URL of the parsed full text; 404s until fullTextStatus is available. - **`self` (required)** `string` — API URL of this source. - **`pdfUrls` (required)** `array` **Items:** `string` - **`role` (required)** `string`, possible values: `"writer", "reader"` — Your role on this source: \`writer\` for your own sources and for a shared collection's papers when you own or can edit that collection; \`reader\` for a shared collection's papers you can only view. Any role can read the source and use it in reviews. Writers edit metadata, attach a PDF, delete, and add to collections. - **`title` (required)** `string | null` - **`updatedAt` (required)** `string` - **`url` (required)** `string | null` - **`venue` (required)** `string | null` - **`year` (required)** `integer | null` - **`totalCount` (required)** `integer` — Total matches for the query across all pages. **Example:** ```json { "sources": [ { "id": "", "title": null, "authors": [ "" ], "year": null, "venue": null, "abstract": null, "doi": null, "url": null, "elicitId": null, "pdfUrls": [ "" ], "collectionIds": [ "" ], "role": "writer", "fullTextStatus": "pending", "createdAt": "", "updatedAt": "", "links": { "self": "", "fullText": "" } } ], "nextCursor": null, "totalCount": 1 } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Save library sources - **Method:** `POST` - **Path:** `/library/sources` - **Tags:** Library Saves 1–100 papers. Each item is one of: an `elicitId`; a `pdfUrls` entry, metadata optional; or a `title` with at least one of `doi`, `authors`, `year`, `venue`, `abstract`, `url`. A `doi` alone is rejected. Elicit fills missing metadata from its corpus or the parsed PDF. `pdfUrls` is how to attach a PDF: Elicit fetches and parses it in the background when the paper is not in the corpus. Do not download PDFs yourself; for local files, use imports. The response lists each item in request order. An item that matches a paper already in your library returns that source with `created: false` and `duplicateOf` set. With `onDuplicate: skip` (default), fields the existing source lacked are filled from the item and listed in `updatedFields`. Existing values do not change. Adding `pdfUrls`, `doi`, or `elicitId` to an existing source starts enrichment for it again. With `onDuplicate: create`, a copy is saved and the pair is recorded as a potential duplicate. `collectionIds` adds every returned source to those collections; each source's `collections` reports, per collection, the id the collection holds for the paper and whether this call added it. A group collection holds its own copy under a different id, so the returned source's `collectionIds` does not list it. Metadata and full text for new sources arrive asynchronously. A new source starts with `fullTextStatus: pending`. When `fullTextStatus` changes, enrichment is complete. A source that still has `title: null` at that point has an identifier that is not in the corpus. ### Example ```bash curl -X POST https://elicit.com/api/v2/library/sources \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"sources":[{"doi":"10.1056/NEJMoa2307563"},{"title":"Attention Is All You Need","authors":["Ashish Vaswani"],"year":2017}],"collectionIds":["b458052a-84e2-4e47-b5c4-00e11390a265"]}' ``` #### Request Body ##### Content-Type: application/json - **`sources` (required)** `array` **Items:** **Any of:** - **`elicitId` (required)** `string` - **`abstract`** `string` — Plain text or markdown; blank lines separate paragraphs. - **`authors`** `array` **Items:** `string` - **`doi`** `string` — Send the title and authors with it, so the record is useful if the DOI is not in Elicit's corpus. - **`pdfUrls`** `array` — Direct PDF links. Fetched and parsed when the paper is not in the Elicit corpus; a PDF URL alone is enough. **Items:** `string`, format: `uri` - **`title`** `string` - **`url`** `string`, format: `uri` - **`venue`** `string` - **`year`** `integer` * **`pdfUrls` (required)** `array` — Direct PDF links. Fetched and parsed when the paper is not in the Elicit corpus; a PDF URL alone is enough. **Items:** `string`, format: `uri` * **`abstract`** `string` — Plain text or markdown; blank lines separate paragraphs. * **`authors`** `array` **Items:** `string` * **`doi`** `string` — Send the title and authors with it, so the record is useful if the DOI is not in Elicit's corpus. * **`elicitId`** `string` * **`title`** `string` * **`url`** `string`, format: `uri` * **`venue`** `string` * **`year`** `integer` **Any of:** - **`collectionIds`** `array` — Collections you own or can edit to add every returned source to, duplicates included. **Items:** `string`, format: `uuid` - **`onDuplicate`** `string`, possible values: `"skip", "create"` — skip (default): an item matching an already-saved source returns that source, updating any fields it lacked, instead of creating one. create: saves anyway and records a potential-duplicate pair for the app's review-duplicates flow. **Example:** ```json { "sources": [ { "title": "", "authors": [ "" ], "year": 1000, "venue": "", "abstract": "", "doi": "", "elicitId": "", "url": "", "pdfUrls": [ "" ] } ], "collectionIds": [ "" ], "onDuplicate": "skip" } ``` #### Responses ##### Status: 200 One entry per item, in request order. ###### Content-Type: application/json - **`sources` (required)** `array` **Items:** **All of:** - **`abstract` (required)** `string | null` — Abstract as markdown. - **`authors` (required)** `array` **Items:** `string` - **`collectionIds` (required)** `array` — Collections this source belongs to that are visible to you. **Items:** `string`, format: `uuid` - **`createdAt` (required)** `string` - **`doi` (required)** `string | null` - **`elicitId` (required)** `string | null` — Elicit corpus id, present once the paper has been matched to the corpus. - **`fullTextStatus` (required)** `string`, possible values: `"pending", "available", "unavailable"` — Whether parsed full text is attached: pending — a PDF is still parsing, or none has been looked for yet; available — parsed and attached; unavailable — looked for, none found. - **`id` (required)** `string`, format: `uuid` — Stable id of the source. - **`links` (required)** `object` - **`fullText` (required)** `string` — API URL of the parsed full text; 404s until fullTextStatus is available. - **`self` (required)** `string` — API URL of this source. - **`pdfUrls` (required)** `array` **Items:** `string` - **`role` (required)** `string`, possible values: `"writer", "reader"` — Your role on this source: \`writer\` for your own sources and for a shared collection's papers when you own or can edit that collection; \`reader\` for a shared collection's papers you can only view. Any role can read the source and use it in reviews. Writers edit metadata, attach a PDF, delete, and add to collections. - **`title` (required)** `string | null` - **`updatedAt` (required)** `string` - **`url` (required)** `string | null` - **`venue` (required)** `string | null` - **`year` (required)** `integer | null` **Example:** ```json { "sources": [ { "id": "", "title": null, "authors": [ "" ], "year": null, "venue": null, "abstract": null, "doi": null, "url": null, "elicitId": null, "pdfUrls": [ "" ], "collectionIds": [ "" ], "role": "writer", "fullTextStatus": "pending", "createdAt": "", "updatedAt": "", "links": { "self": "", "fullText": "" } } ] } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The collection does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Retrieve a library source - **Method:** `GET` - **Path:** `/library/sources/{sourceId}` - **Tags:** Library Retrieves a source by id. `fullTextStatus` values: `pending`, Elicit has not finished looking for a PDF; `available`, full text is ready; `unavailable`, no PDF was found. ### Example ```bash curl https://elicit.com/api/v2/library/sources/{sourceId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 The source. ###### Content-Type: application/json - **`abstract` (required)** `string | null` — Abstract as markdown. - **`authors` (required)** `array` **Items:** `string` - **`collectionIds` (required)** `array` — Collections this source belongs to that are visible to you. **Items:** `string`, format: `uuid` - **`createdAt` (required)** `string` - **`doi` (required)** `string | null` - **`elicitId` (required)** `string | null` — Elicit corpus id, present once the paper has been matched to the corpus. - **`fullTextStatus` (required)** `string`, possible values: `"pending", "available", "unavailable"` — Whether parsed full text is attached: pending — a PDF is still parsing, or none has been looked for yet; available — parsed and attached; unavailable — looked for, none found. - **`id` (required)** `string`, format: `uuid` — Stable id of the source. - **`links` (required)** `object` - **`fullText` (required)** `string` — API URL of the parsed full text; 404s until fullTextStatus is available. - **`self` (required)** `string` — API URL of this source. - **`pdfUrls` (required)** `array` **Items:** `string` - **`role` (required)** `string`, possible values: `"writer", "reader"` — Your role on this source: \`writer\` for your own sources and for a shared collection's papers when you own or can edit that collection; \`reader\` for a shared collection's papers you can only view. Any role can read the source and use it in reviews. Writers edit metadata, attach a PDF, delete, and add to collections. - **`title` (required)** `string | null` - **`updatedAt` (required)** `string` - **`url` (required)** `string | null` - **`venue` (required)** `string | null` - **`year` (required)** `integer | null` **Example:** ```json { "id": "", "title": null, "authors": [ "" ], "year": null, "venue": null, "abstract": null, "doi": null, "url": null, "elicitId": null, "pdfUrls": [ "" ], "collectionIds": [ "" ], "role": "writer", "fullTextStatus": "pending", "createdAt": "", "updatedAt": "", "links": { "self": "", "fullText": "" } } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The source does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Delete a library source - **Method:** `DELETE` - **Path:** `/library/sources/{sourceId}` - **Tags:** Library Deletes a source you are a `writer` on: your own, or a shared collection's paper when you own or can edit that collection; that paper goes to the collection's trash. A repeat returns `204`. A source you can only read returns `403`. ### Example ```bash curl -X DELETE https://elicit.com/api/v2/library/sources/{sourceId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 204 Deleted (or already deleted). ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The source does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Retrieve a source's full text - **Method:** `GET` - **Path:** `/library/sources/{sourceId}/full-text` - **Tags:** Library Returns the parsed full text of the source's PDF as markdown: title, abstract, and body. A `404` has one of three codes. `full_text_pending`: the PDF search or parse is in progress; retry later. `full_text_unavailable`: no PDF was found. `not_found`: the source is not visible to you. ### Example ```bash curl https://elicit.com/api/v2/library/sources/{sourceId}/full-text \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 The parsed full text. ###### Content-Type: application/json - **`markdown` (required)** `string` — The parsed paper — title, abstract, and body — as markdown. **Example:** ```json { "markdown": "" } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The source is not visible to you, or has no full text (yet). Check the code. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### List library collections - **Method:** `GET` - **Path:** `/library/collections` - **Tags:** Library Returns the collections you own and the collections shared with you. `role` is your access level. `sharedVia` is set on collections shared with you. `links.sources` lists the sources in the collection. Send `nextCursor` as `cursor` to get the next page. ### Example ```bash curl https://elicit.com/api/v2/library/collections \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 One page of collections. ###### Content-Type: application/json - **`collections` (required)** `array` **Items:** - **`description` (required)** `string` - **`id` (required)** `string`, format: `uuid` - **`kind` (required)** `string`, possible values: `"personal", "group"` — \`personal\`: never shared; lists your own sources. \`group\`: has been shared at least once; owns copies of its sources, and stays a group collection. - **`links` (required)** `object` - **`self` (required)** `string` — API URL of this collection. - **`sources` (required)** `string` — URL listing the sources in this collection. - **`name` (required)** `string` - **`role` (required)** `string`, possible values: `"owner", "writer", "reader"` — Your access level. A reader can view the collection. A writer can also add and remove sources and edit the name and description. An owner can also delete the collection and change who it is shared with. - **`sourceCount` (required)** `integer` - **`sharedVia`** `string`, possible values: `"direct", "organization"` — \`direct\` if the owner shared the collection with you. \`organization\` if the owner shared it with your organization. Absent on your own collections. - **`nextCursor` (required)** `string | null` - **`totalCount` (required)** `integer` **Example:** ```json { "collections": [ { "id": "", "name": "", "description": "", "role": "owner", "kind": "personal", "sharedVia": "direct", "sourceCount": 1, "links": { "self": "", "sources": "" } } ], "nextCursor": null, "totalCount": 1 } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Create a collection - **Method:** `POST` - **Path:** `/library/collections` - **Tags:** Library Creates an empty collection. Names are not unique. Store the returned id. ### Example ```bash curl -X POST https://elicit.com/api/v2/library/collections \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"name":"GLP-1 cardiovascular trials"}' ``` #### Request Body ##### Content-Type: application/json - **`name` (required)** `string` - **`description`** `string` **Example:** ```json { "name": "", "description": "" } ``` #### Responses ##### Status: 201 The new collection. ###### Content-Type: application/json - **`description` (required)** `string` - **`id` (required)** `string`, format: `uuid` - **`kind` (required)** `string`, possible values: `"personal", "group"` — \`personal\`: never shared; lists your own sources. \`group\`: has been shared at least once; owns copies of its sources, and stays a group collection. - **`links` (required)** `object` - **`self` (required)** `string` — API URL of this collection. - **`sources` (required)** `string` — URL listing the sources in this collection. - **`name` (required)** `string` - **`role` (required)** `string`, possible values: `"owner", "writer", "reader"` — Your access level. A reader can view the collection. A writer can also add and remove sources and edit the name and description. An owner can also delete the collection and change who it is shared with. - **`sourceCount` (required)** `integer` - **`sharedVia`** `string`, possible values: `"direct", "organization"` — \`direct\` if the owner shared the collection with you. \`organization\` if the owner shared it with your organization. Absent on your own collections. **Example:** ```json { "id": "", "name": "", "description": "", "role": "owner", "kind": "personal", "sharedVia": "direct", "sourceCount": 1, "links": { "self": "", "sources": "" } } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Retrieve a library collection - **Method:** `GET` - **Path:** `/library/collections/{collectionId}` - **Tags:** Library Retrieves a collection by id. `role` is your access level. ### Example ```bash curl https://elicit.com/api/v2/library/collections/{collectionId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 The collection. ###### Content-Type: application/json - **`description` (required)** `string` - **`id` (required)** `string`, format: `uuid` - **`kind` (required)** `string`, possible values: `"personal", "group"` — \`personal\`: never shared; lists your own sources. \`group\`: has been shared at least once; owns copies of its sources, and stays a group collection. - **`links` (required)** `object` - **`self` (required)** `string` — API URL of this collection. - **`sources` (required)** `string` — URL listing the sources in this collection. - **`name` (required)** `string` - **`role` (required)** `string`, possible values: `"owner", "writer", "reader"` — Your access level. A reader can view the collection. A writer can also add and remove sources and edit the name and description. An owner can also delete the collection and change who it is shared with. - **`sourceCount` (required)** `integer` - **`sharedVia`** `string`, possible values: `"direct", "organization"` — \`direct\` if the owner shared the collection with you. \`organization\` if the owner shared it with your organization. Absent on your own collections. **Example:** ```json { "id": "", "name": "", "description": "", "role": "owner", "kind": "personal", "sharedVia": "direct", "sourceCount": 1, "links": { "self": "", "sources": "" } } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The collection does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Update a collection - **Method:** `PATCH` - **Path:** `/library/collections/{collectionId}` - **Tags:** Library Updates `name` and/or `description`. Omitted fields do not change. A body with neither returns `400`. Needs edit access. ### Example ```bash curl -X PATCH https://elicit.com/api/v2/library/collections/{collectionId} \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"description":"Outcome trials, 2016 onward."}' ``` #### Request Body ##### Content-Type: application/json - **`description`** `string` - **`name`** `string` **Example:** ```json { "name": "", "description": "" } ``` #### Responses ##### Status: 200 The updated collection. ###### Content-Type: application/json - **`description` (required)** `string` - **`id` (required)** `string`, format: `uuid` - **`kind` (required)** `string`, possible values: `"personal", "group"` — \`personal\`: never shared; lists your own sources. \`group\`: has been shared at least once; owns copies of its sources, and stays a group collection. - **`links` (required)** `object` - **`self` (required)** `string` — API URL of this collection. - **`sources` (required)** `string` — URL listing the sources in this collection. - **`name` (required)** `string` - **`role` (required)** `string`, possible values: `"owner", "writer", "reader"` — Your access level. A reader can view the collection. A writer can also add and remove sources and edit the name and description. An owner can also delete the collection and change who it is shared with. - **`sourceCount` (required)** `integer` - **`sharedVia`** `string`, possible values: `"direct", "organization"` — \`direct\` if the owner shared the collection with you. \`organization\` if the owner shared it with your organization. Absent on your own collections. **Example:** ```json { "id": "", "name": "", "description": "", "role": "owner", "kind": "personal", "sharedVia": "direct", "sourceCount": 1, "links": { "self": "", "sources": "" } } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The collection does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Delete a collection - **Method:** `DELETE` - **Path:** `/library/collections/{collectionId}` - **Tags:** Library Deletes a collection you own. Its sources stay in their owners' libraries. A repeat returns `404`. ### Example ```bash curl -X DELETE https://elicit.com/api/v2/library/collections/{collectionId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 204 Deleted. ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The collection does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Import uploaded PDFs - **Method:** `POST` - **Path:** `/library/imports` - **Tags:** Library Imports uploaded PDFs into your library. Elicit parses each file, extracts its metadata, attaches the full text, and checks for duplicates. 1. Stage each file with `POST /api/v2/files` and PUT the bytes to `upload_url`. 2. Send the `file_id`s here. The response is `202` and an import with every file `pending`. `collectionId` adds each imported paper to a collection, duplicates included. 3. Poll `links.self` until `status` is `completed`. Each file ends as `created` (`sourceId`), `duplicate` (`duplicateOf`), or `failed` (`error`). A file id can be imported once. Files must be PDFs. A byte-identical copy of a PDF in your library is always a `duplicate`. A rejected request imports nothing and uses no file ids. Requires the early-access Research Agent API. ### Example ```bash curl -X POST https://elicit.com/api/v2/library/imports \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"fileIds":["5515a6d4-1b17-4f0d-8484-ccc783b912bc"],"collectionId":"b458052a-84e2-4e47-b5c4-00e11390a265"}' ``` #### Request Body ##### Content-Type: application/json - **`fileIds` (required)** `array` — Ids of staged files whose bytes have been uploaded. PDFs only; each file imports once. **Items:** `string`, format: `uuid` - **`collectionId`** `string`, format: `uuid` — A collection you own or can edit to add the imported sources to, duplicates included. - **`onDuplicate`** `string`, possible values: `"skip", "create"` — skip (default): a PDF matching an already-saved source is reported as its duplicate and not saved. create: saves it as a new source anyway. **Example:** ```json { "fileIds": [ "" ], "collectionId": "", "onDuplicate": "skip" } ``` #### Responses ##### Status: 202 Import accepted; every file is pending. Poll \`links.self\`. ###### Content-Type: application/json - **`completedAt` (required)** `string | null` - **`createdAt` (required)** `string` - **`files` (required)** `array` **Items:** - **`duplicateOf` (required)** `string | null`, format: `uuid` — The already-saved source this file matched. - **`error` (required)** `object | null` — processing-error and server-error may succeed on retry. - **`code` (required)** `string`, possible values: `"duplicate", "processing-error", "server-error", "invalid-file", "unknown"` - **`message` (required)** `string` - **`fileId` (required)** `string`, format: `uuid` - **`filename` (required)** `string` - **`sourceId` (required)** `string | null`, format: `uuid` - **`status` (required)** `string`, possible values: `"pending", "created", "duplicate", "failed"` - **`id` (required)** `string`, format: `uuid` - **`links` (required)** `object` - **`self` (required)** `string` — Poll this URL until status is completed. - **`status` (required)** `string`, possible values: `"processing", "completed"` **Example:** ```json { "id": "", "status": "processing", "files": [ { "fileId": "", "filename": "", "status": "pending", "sourceId": null, "duplicateOf": null, "error": { "code": "duplicate", "message": "" } } ], "createdAt": "", "completedAt": null, "links": { "self": "" } } ``` ##### Status: 400 A file is not a PDF, a file has not been uploaded, or the body is invalid. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 A file\_id is unknown or belongs to another user, the collection is not visible to you, or the Research Agent API is not enabled. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 409 A file\_id was already imported or attached to a session. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 410 The staged upload expired before it was imported; stage it again. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Retrieve an import - **Method:** `GET` - **Path:** `/library/imports/{importId}` - **Tags:** Library Retrieves an import. `status` is `processing` or `completed`. `completed` does not mean that every file succeeded. File `status` values: `pending`; `created`, with `sourceId`; `duplicate`, with `duplicateOf`; `failed`, with `error`. `error.code` values: `invalid-file`, do not retry; `processing-error` and `server-error`, a retry may succeed; `unknown`. ### Example ```bash curl https://elicit.com/api/v2/library/imports/{importId} \ -H "Authorization: Bearer elk_live_your_key_here" ``` #### Responses ##### Status: 200 The import and its per-file results. ###### Content-Type: application/json - **`completedAt` (required)** `string | null` - **`createdAt` (required)** `string` - **`files` (required)** `array` **Items:** - **`duplicateOf` (required)** `string | null`, format: `uuid` — The already-saved source this file matched. - **`error` (required)** `object | null` — processing-error and server-error may succeed on retry. - **`code` (required)** `string`, possible values: `"duplicate", "processing-error", "server-error", "invalid-file", "unknown"` - **`message` (required)** `string` - **`fileId` (required)** `string`, format: `uuid` - **`filename` (required)** `string` - **`sourceId` (required)** `string | null`, format: `uuid` - **`status` (required)** `string`, possible values: `"pending", "created", "duplicate", "failed"` - **`id` (required)** `string`, format: `uuid` - **`links` (required)** `object` - **`self` (required)** `string` — Poll this URL until status is completed. - **`status` (required)** `string`, possible values: `"processing", "completed"` **Example:** ```json { "id": "", "status": "processing", "files": [ { "fileId": "", "filename": "", "status": "pending", "sourceId": null, "duplicateOf": null, "error": { "code": "duplicate", "message": "" } } ], "createdAt": "", "completedAt": null, "links": { "self": "" } } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The import does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Add sources to a collection - **Method:** `POST` - **Path:** `/library/collections/{collectionId}/sources` - **Tags:** Library Adds up to 500 of your sources to a collection you own or can edit. `addedCount` is the number added. A source is skipped if it is already in the collection, or if a paper in the collection is the same paper. Papers match by Elicit id, DOI, title, or identical PDF. Each skipped source appears in `duplicates` with `duplicateOf`, the id of the paper already in the collection (its own id when it was already a member). Each added source appears in `added` with `collectionSourceId`, the id the collection holds for it: in a group collection the collection gets its own copy of each added source, under its own id, and your source stays yours. If any id is not a source you own, the request returns `404` and adds nothing. ### Example ```bash curl -X POST https://elicit.com/api/v2/library/collections/{collectionId}/sources \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"sourceIds":["8e2d4d52-3b8a-4f6c-9e1a-2c7b6d5e4f30"]}' ``` #### Request Body ##### Content-Type: application/json - **`sourceIds` (required)** `array` — Ids of your library sources. **Items:** `string`, format: `uuid` **Example:** ```json { "sourceIds": [ "" ] } ``` #### Responses ##### Status: 200 How many sources were newly added. ###### Content-Type: application/json - **`added` (required)** `array` — The sources this call added. **Items:** - **`collectionSourceId` (required)** `string`, format: `uuid` — Id of the paper inside the collection. A group collection keeps its own copy, so this differs from sourceId; a personal collection holds the source itself. - **`sourceId` (required)** `string`, format: `uuid` - **`addedCount` (required)** `integer` — Sources newly added; sources already in the collection are skipped. - **`duplicates` (required)** `array` — Sources that were not added because the collection already has the same paper. Papers match by Elicit id, DOI, title, or identical PDF. **Items:** - **`duplicateOf` (required)** `string`, format: `uuid` — The id of the source that is already in the collection; the source itself when it was already a member. - **`sourceId` (required)** `string`, format: `uuid` **Example:** ```json { "addedCount": 1, "added": [ { "sourceId": "", "collectionSourceId": "" } ], "duplicates": [ { "sourceId": "", "duplicateOf": "" } ] } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The collection is not visible to you, or a sourceId is not a source you own. Nothing is applied. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### Remove sources from a collection - **Method:** `DELETE` - **Path:** `/library/collections/{collectionId}/sources` - **Tags:** Library Removes sources from a collection you own or can edit, whichever member added them. A member's own source stays in their library; a shared collection's own paper goes to the collection's trash for 30 days. Send the ids in a JSON body. `removedCount` is the number removed; an id that is not in the collection is skipped. ### Example ```bash curl -X DELETE https://elicit.com/api/v2/library/collections/{collectionId}/sources \ -H "Authorization: Bearer elk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"sourceIds":["8e2d4d52-3b8a-4f6c-9e1a-2c7b6d5e4f30"]}' ``` #### Request Body ##### Content-Type: application/json - **`sourceIds` (required)** `array` — Ids of your library sources. **Items:** `string`, format: `uuid` **Example:** ```json { "sourceIds": [ "" ] } ``` #### Responses ##### Status: 200 How many memberships were removed. ###### Content-Type: application/json - **`removedCount` (required)** `integer` — Sources removed; ids not in the collection are skipped. A member's own source stays in their library. A shared collection's own paper moves to the collection's trash for 30 days. **Example:** ```json { "removedCount": 1 } ``` ##### Status: 400 A malformed id, or an unknown or invalid query parameter. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 401 Authentication failed. The API key is missing, invalid, revoked, or expired. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 403 API access is not available on your current plan. Upgrade to Pro or above to use the API. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 404 The collection does not exist or is not visible to you. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ##### Status: 429 Rate limit exceeded. More than 100 requests per minute were received from your IP address; further requests are blocked for 5 minutes. ###### Content-Type: application/json - **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. - **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ##### Status: 500 An unexpected error occurred. Retry after a short delay. ###### Content-Type: application/json - **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ## Schemas ### PaperSearchRequest - **Type:**`object` * **`query` (required)** `string` — The search query string * **`corpus`** `string`, possible values: `"elicit", "pubmed"`, default: `"elicit"` — Paper corpus to search. \`elicit\` (default) searches Elicit's full paper index; \`pubmed\` restricts to PubMed. * **`filters`** `object` — Filters to narrow search results - **`excludeKeywords`** `array` — Keywords to exclude from results **Items:** `string` - **`hasPdf`** `boolean` — Only include papers with available PDFs - **`includeKeywords`** `array` — Keywords that must appear in the paper **Items:** `string` - **`maxEpochS`** `integer` — Maximum publication date as Unix epoch seconds - **`maxQuartile`** `integer` — Maximum journal quartile (1 = top 25%) - **`maxYear`** `integer` — Maximum publication year - **`minEpochS`** `integer` — Minimum publication date as Unix epoch seconds - **`minYear`** `integer` — Minimum publication year - **`pubmedOnly`** `boolean` — Only include papers from PubMed - **`retracted`** `string`, possible values: `"exclude_retracted", "include_retracted", "only_retracted"` — How to handle retracted papers. Defaults to exclude\_retracted. - **`typeTags`** `array` — Filter by study type **Items:** `string`, possible values: `"Review", "Meta-Analysis", "Systematic Review", "RCT", "Longitudinal"` * **`maxResults`** `integer`, default: `10` — Maximum number of results to return (1-10000) * **`searchMode`** `string`, possible values: `"semantic", "keyword"`, default: `"semantic"` — How to interpret \`query\`. \`semantic\` (default) runs Elicit's semantic search. \`keyword\` sends the query as a Lucene-style boolean expression directly to the corpus search API. Mutually exclusive with \`filters\` / \`trialFilters\` — put filter expressions into the query string in keyword mode. **Example:** ```json { "query": "GLP-1 receptor agonists for weight loss", "searchMode": "semantic", "maxResults": 10, "corpus": "elicit", "filters": { "minYear": 2020, "maxYear": 2025, "minEpochS": 1672531200, "maxEpochS": 1789413033, "maxQuartile": 2, "includeKeywords": [ "semaglutide", "liraglutide" ], "excludeKeywords": [ "rodent", "mouse model" ], "typeTags": [ "RCT", "Meta-Analysis" ], "hasPdf": false, "pubmedOnly": false, "retracted": "exclude_retracted" } } ``` ### PaperFilters - **Type:**`object` * **`excludeKeywords`** `array` — Keywords to exclude from results **Items:** `string` * **`hasPdf`** `boolean` — Only include papers with available PDFs * **`includeKeywords`** `array` — Keywords that must appear in the paper **Items:** `string` * **`maxEpochS`** `integer` — Maximum publication date as Unix epoch seconds * **`maxQuartile`** `integer` — Maximum journal quartile (1 = top 25%) * **`maxYear`** `integer` — Maximum publication year * **`minEpochS`** `integer` — Minimum publication date as Unix epoch seconds * **`minYear`** `integer` — Minimum publication year * **`pubmedOnly`** `boolean` — Only include papers from PubMed * **`retracted`** `string`, possible values: `"exclude_retracted", "include_retracted", "only_retracted"` — How to handle retracted papers. Defaults to exclude\_retracted. * **`typeTags`** `array` — Filter by study type **Items:** `string`, possible values: `"Review", "Meta-Analysis", "Systematic Review", "RCT", "Longitudinal"` **Example:** ```json { "minYear": 2020, "maxYear": 2025, "minEpochS": 1672531200, "maxEpochS": 1789413033, "maxQuartile": 2, "includeKeywords": [ "semaglutide", "liraglutide" ], "excludeKeywords": [ "rodent", "mouse model" ], "typeTags": [ "RCT", "Meta-Analysis" ], "hasPdf": false, "pubmedOnly": false, "retracted": "exclude_retracted" } ``` ### PaperSearchResponse - **Type:**`object` * **`papers` (required)** `array` — Papers matching the query **Items:** - **`abstract` (required)** `string | null` — Paper abstract - **`authors` (required)** `array` — List of author names **Items:** `string` - **`citedByCount` (required)** `integer | null` — Number of citations this paper has received - **`doi` (required)** `string | null` — Digital Object Identifier - **`elicitId` (required)** `string | null` — Elicit internal paper identifier - **`fullTextUrl` (required)** `string | null` — Best available full-text / PDF link, or null when none is known. - **`journalQuartile` (required)** `integer | null` — SJR journal quartile (1 = top 25%). Null when the journal is unranked/unknown or for the \`pubmed\` corpus. - **`pmid` (required)** `string | null` — PubMed identifier - **`studyTypeTags` (required)** `array` — Study design tags (e.g. RCT, Meta-Analysis, Systematic Review, Review, Longitudinal). Populated for the \`elicit\` corpus; empty for the \`pubmed\` corpus. **Items:** `string` - **`title` (required)** `string` — Paper title - **`urls` (required)** `array` — URLs for the paper **Items:** `string` - **`venue` (required)** `string | null` — Publication venue - **`year` (required)** `integer | null` — Publication year * **`warnings`** `array` — Non-fatal warnings emitted while executing the search (e.g. phrases ignored by the PubMed parser). **Items:** - **`corpus` (required)** `string`, possible values: `"elicit", "pubmed", "clinical_trials"` — Corpus that emitted the warning - **`message` (required)** `string` — Human-readable warning message - **`searchMode` (required)** `string`, possible values: `"semantic", "keyword"` — Search mode in effect when the warning was emitted - **`warningDetails` (required)** `object` - **`messages` (required)** `array` — Underlying warning messages **Items:** `string` - **`type` (required)** `string` — Warning category **Example:** ```json { "papers": [ { "elicitId": null, "title": "", "authors": [ "" ], "year": null, "abstract": null, "doi": null, "pmid": null, "venue": null, "citedByCount": null, "urls": [ "" ], "studyTypeTags": [ "" ], "journalQuartile": null, "fullTextUrl": null } ], "warnings": [ { "corpus": "elicit", "searchMode": "semantic", "message": "", "warningDetails": { "type": "", "messages": [ "" ] } } ] } ``` ### Paper - **Type:**`object` * **`abstract` (required)** `string | null` — Paper abstract * **`authors` (required)** `array` — List of author names **Items:** `string` * **`citedByCount` (required)** `integer | null` — Number of citations this paper has received * **`doi` (required)** `string | null` — Digital Object Identifier * **`elicitId` (required)** `string | null` — Elicit internal paper identifier * **`fullTextUrl` (required)** `string | null` — Best available full-text / PDF link, or null when none is known. * **`journalQuartile` (required)** `integer | null` — SJR journal quartile (1 = top 25%). Null when the journal is unranked/unknown or for the \`pubmed\` corpus. * **`pmid` (required)** `string | null` — PubMed identifier * **`studyTypeTags` (required)** `array` — Study design tags (e.g. RCT, Meta-Analysis, Systematic Review, Review, Longitudinal). Populated for the \`elicit\` corpus; empty for the \`pubmed\` corpus. **Items:** `string` * **`title` (required)** `string` — Paper title * **`urls` (required)** `array` — URLs for the paper **Items:** `string` * **`venue` (required)** `string | null` — Publication venue * **`year` (required)** `integer | null` — Publication year **Example:** ```json { "elicitId": null, "title": "", "authors": [ "" ], "year": null, "abstract": null, "doi": null, "pmid": null, "venue": null, "citedByCount": null, "urls": [ "" ], "studyTypeTags": [ "" ], "journalQuartile": null, "fullTextUrl": null } ``` ### SearchWarning - **Type:**`object` * **`corpus` (required)** `string`, possible values: `"elicit", "pubmed", "clinical_trials"` — Corpus that emitted the warning * **`message` (required)** `string` — Human-readable warning message * **`searchMode` (required)** `string`, possible values: `"semantic", "keyword"` — Search mode in effect when the warning was emitted * **`warningDetails` (required)** `object` - **`messages` (required)** `array` — Underlying warning messages **Items:** `string` - **`type` (required)** `string` — Warning category **Example:** ```json { "corpus": "elicit", "searchMode": "semantic", "message": "", "warningDetails": { "type": "", "messages": [ "" ] } } ``` ### SearchWarningDetails - **Type:**`object` * **`messages` (required)** `array` — Underlying warning messages **Items:** `string` * **`type` (required)** `string` — Warning category **Example:** ```json { "type": "", "messages": [ "" ] } ``` ### ErrorResponse - **Type:**`object` * **`error` (required)** `object` - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "error": { "code": "invalid_request", "message": "Invalid search request" } } ``` ### CloudflareRateLimitError - **Type:**`object` * **`error` (required)** `string` — Error label. Always \`Rate limit exceeded\` for the burst limit. * **`message` (required)** `string` — Human-readable detail. **Example:** ```json { "error": "Rate limit exceeded", "message": "Too many requests. Please try again later." } ``` ### TrialSearchRequest - **Type:**`object` * **`query` (required)** `string` — The search query string * **`maxResults`** `integer`, default: `10` — Maximum number of results to return (1-10000) * **`searchMode`** `string`, possible values: `"semantic", "keyword"`, default: `"semantic"` — How to interpret \`query\`. \`semantic\` (default) runs Elicit's semantic search. \`keyword\` sends the query as a Lucene-style boolean expression directly to the corpus search API. Mutually exclusive with \`filters\` / \`trialFilters\` — put filter expressions into the query string in keyword mode. * **`trialFilters`** `object` — Clinical-trials filters (phase, recruitment status, results) - **`hasResults`** `boolean` — Only include trials that have posted results - **`phase`** `array` — Clinical trial phases to include **Items:** `string`, possible values: `"NA", "EARLY_PHASE1", "PHASE1", "PHASE2", "PHASE3", "PHASE4"` - **`recruitmentStatus`** `array` — Trial recruitment statuses to include **Items:** `string`, possible values: `"ACTIVE_NOT_RECRUITING", "COMPLETED", "ENROLLING_BY_INVITATION", "NOT_YET_RECRUITING", "RECRUITING", "SUSPENDED", "TERMINATED", "WITHDRAWN", "AVAILABLE"` **Example:** ```json { "query": "GLP-1 receptor agonists for weight loss", "searchMode": "semantic", "maxResults": 10, "trialFilters": { "phase": [ "PHASE2", "PHASE3" ], "recruitmentStatus": [ "RECRUITING", "ACTIVE_NOT_RECRUITING" ], "hasResults": true } } ``` ### TrialFilters - **Type:**`object` * **`hasResults`** `boolean` — Only include trials that have posted results * **`phase`** `array` — Clinical trial phases to include **Items:** `string`, possible values: `"NA", "EARLY_PHASE1", "PHASE1", "PHASE2", "PHASE3", "PHASE4"` * **`recruitmentStatus`** `array` — Trial recruitment statuses to include **Items:** `string`, possible values: `"ACTIVE_NOT_RECRUITING", "COMPLETED", "ENROLLING_BY_INVITATION", "NOT_YET_RECRUITING", "RECRUITING", "SUSPENDED", "TERMINATED", "WITHDRAWN", "AVAILABLE"` **Example:** ```json { "phase": [ "PHASE2", "PHASE3" ], "recruitmentStatus": [ "RECRUITING", "ACTIVE_NOT_RECRUITING" ], "hasResults": true } ``` ### TrialSearchResponse - **Type:**`object` * **`trials` (required)** `array` — Clinical trials matching the query **Items:** - **`completionDate` (required)** `string | null` — Completion date (ISO \`YYYY-MM-DD\` or partial). - **`conditions` (required)** `array` — Conditions / diseases being studied. **Items:** `string` - **`enrollmentCount` (required)** `integer | null` — Actual or anticipated enrollment count. - **`hasResults` (required)** `boolean | null` — Whether the trial has posted results. - **`interventions` (required)** `array` — Intervention names. **Items:** `string` - **`lastUpdatedYear` (required)** `integer | null` — Year the trial record was last updated. - **`leadSponsor` (required)** `string | null` — Lead sponsor name. - **`nctId` (required)** `string` — NCT identifier for the trial - **`overallStatus` (required)** `string | null` — Overall recruitment status (RECRUITING, COMPLETED, TERMINATED, etc.). Null when the trial has no status posted. - **`phase` (required)** `array` — Trial phases (may list multiple, e.g. PHASE2 + PHASE3). Empty for N/A. **Items:** `string` - **`primaryCompletionDate` (required)** `string | null` — Primary completion date (ISO \`YYYY-MM-DD\` or partial). - **`startDate` (required)** `string | null` — Trial start date (ISO \`YYYY-MM-DD\` or partial). - **`studyType` (required)** `string | null` — Study type (INTERVENTIONAL, OBSERVATIONAL, EXPANDED\_ACCESS). - **`summary` (required)** `string | null` — Plain-text trial description / brief summary - **`title` (required)** `string` — Trial title - **`url` (required)** `string` — Link to the trial's public record * **`warnings`** `array` — Non-fatal warnings emitted while executing the search. **Items:** - **`corpus` (required)** `string`, possible values: `"elicit", "pubmed", "clinical_trials"` — Corpus that emitted the warning - **`message` (required)** `string` — Human-readable warning message - **`searchMode` (required)** `string`, possible values: `"semantic", "keyword"` — Search mode in effect when the warning was emitted - **`warningDetails` (required)** `object` - **`messages` (required)** `array` — Underlying warning messages **Items:** `string` - **`type` (required)** `string` — Warning category **Example:** ```json { "trials": [ { "nctId": "NCT05646706", "title": "", "summary": null, "url": "https://clinicaltrials.gov/study/NCT05646706", "overallStatus": null, "phase": [ "" ], "studyType": null, "enrollmentCount": null, "conditions": [ "" ], "interventions": [ "" ], "leadSponsor": null, "startDate": null, "primaryCompletionDate": null, "completionDate": null, "hasResults": null, "lastUpdatedYear": null } ], "warnings": [ { "corpus": "elicit", "searchMode": "semantic", "message": "", "warningDetails": { "type": "", "messages": [ "" ] } } ] } ``` ### Trial - **Type:**`object` * **`completionDate` (required)** `string | null` — Completion date (ISO \`YYYY-MM-DD\` or partial). * **`conditions` (required)** `array` — Conditions / diseases being studied. **Items:** `string` * **`enrollmentCount` (required)** `integer | null` — Actual or anticipated enrollment count. * **`hasResults` (required)** `boolean | null` — Whether the trial has posted results. * **`interventions` (required)** `array` — Intervention names. **Items:** `string` * **`lastUpdatedYear` (required)** `integer | null` — Year the trial record was last updated. * **`leadSponsor` (required)** `string | null` — Lead sponsor name. * **`nctId` (required)** `string` — NCT identifier for the trial * **`overallStatus` (required)** `string | null` — Overall recruitment status (RECRUITING, COMPLETED, TERMINATED, etc.). Null when the trial has no status posted. * **`phase` (required)** `array` — Trial phases (may list multiple, e.g. PHASE2 + PHASE3). Empty for N/A. **Items:** `string` * **`primaryCompletionDate` (required)** `string | null` — Primary completion date (ISO \`YYYY-MM-DD\` or partial). * **`startDate` (required)** `string | null` — Trial start date (ISO \`YYYY-MM-DD\` or partial). * **`studyType` (required)** `string | null` — Study type (INTERVENTIONAL, OBSERVATIONAL, EXPANDED\_ACCESS). * **`summary` (required)** `string | null` — Plain-text trial description / brief summary * **`title` (required)** `string` — Trial title * **`url` (required)** `string` — Link to the trial's public record **Example:** ```json { "nctId": "NCT05646706", "title": "", "summary": null, "url": "https://clinicaltrials.gov/study/NCT05646706", "overallStatus": null, "phase": [ "" ], "studyType": null, "enrollmentCount": null, "conditions": [ "" ], "interventions": [ "" ], "leadSponsor": null, "startDate": null, "primaryCompletionDate": null, "completionDate": null, "hasResults": null, "lastUpdatedYear": null } ``` ### ReportSessionCreated - **Type:**`object` * **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`status` (required)** `string` — Initial status is always processing * **`type` (required)** `string` * **`url` (required)** `string` — URL to view the report in the Elicit web interface as it progresses **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "isPublic": false, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### SessionLinks - **Type:**`object` * **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) * **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. **Example:** ```json { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } ``` ### ReportSessionDetail - **Type:**`object` * **`executionStage` (required)** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage. Advances through gathering\_sources → screening\_abstract → extracting\_data → generating\_report → done. Null for reports created before this field was introduced or when the stage isn't known. * **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the report. Transitions: processing ⇄ pausedForInsufficientQuota (paused when the account exceeds its usage limit; stays paused until explicitly resumed via the resume endpoint or the Elicit web interface), processing → completed/failed. Poll until completed or failed. * **`type` (required)** `string` * **`url` (required)** `string` — URL to view the report in the Elicit web interface * **`bibUrl`** `string | null` — Pre-signed URL to download the report's references as a BibTeX (.bib) file. Only present when status is completed and the report has a non-empty bibliography. Expires after 7 days — re-fetch the report for a fresh URL. * **`docxUrl`** `string | null` — Pre-signed URL to download the report as DOCX. Only present when status is completed and assets have been generated. Expires after 7 days — re-fetch the report for a fresh URL. * **`error`** `object` — Error details, only present when status is failed - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message * **`exportsStatus`** `string`, possible values: `"ready", "generating", "unavailable"` — Availability of the reference-list exports (\`txtUrl\`/\`bibUrl\`/\`risUrl\`); \`pdfUrl\`/\`docxUrl\` are unaffected. Only present when status is completed. \`ready\`: absent URLs genuinely have no export. \`generating\`: the exports are currently being generated and nothing is cached yet. \`unavailable\`: export generation failed and nothing is cached. * **`pdfUrl`** `string | null` — Pre-signed URL to download the report as PDF. Only present when status is completed and assets have been generated. Expires after 7 days — re-fetch the report for a fresh URL. * **`result`** `object` — Report output, only present when status is completed - **`summary` (required)** `string` — AI-generated executive summary of the findings - **`title` (required)** `string` — Auto-generated title for the report - **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. - **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. * **`risUrl`** `string | null` — Pre-signed URL to download the report's references as an RIS (.ris) file. Only present when status is completed and the report has a non-empty bibliography. Expires after 7 days — re-fetch the report for a fresh URL. * **`txtUrl`** `string | null` — Pre-signed URL to download the report's reference list as a plain-text (APA) file. Only present when status is completed and the report has a non-empty bibliography. Expires after 7 days — re-fetch the report for a fresh URL. **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "isPublic": false, "result": { "title": "GLP-1 Receptor Agonists and Cardiovascular Outcomes: A Systematic Review", "summary": "This review analyzed 42 studies examining the cardiovascular effects of GLP-1 receptor agonists. The evidence suggests significant reductions in major adverse cardiovascular events (MACE), with semaglutide showing the strongest effect (HR 0.74, 95% CI 0.58-0.95)...", "reportBody": "# Introduction\n\nGLP-1 receptor agonists have emerged as...", "abstract": "This systematic review examines the cardiovascular effects of..." }, "error": { "code": "", "message": "" }, "pdfUrl": "https://s3.amazonaws.com/...", "docxUrl": "https://s3.amazonaws.com/...", "txtUrl": "https://s3.amazonaws.com/...", "bibUrl": "https://s3.amazonaws.com/...", "risUrl": "https://s3.amazonaws.com/...", "exportsStatus": "ready", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### ReportResult - **Type:**`object` * **`summary` (required)** `string` — AI-generated executive summary of the findings * **`title` (required)** `string` — Auto-generated title for the report * **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. * **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. **Example:** ```json { "title": "GLP-1 Receptor Agonists and Cardiovascular Outcomes: A Systematic Review", "summary": "This review analyzed 42 studies examining the cardiovascular effects of GLP-1 receptor agonists. The evidence suggests significant reductions in major adverse cardiovascular events (MACE), with semaglutide showing the strongest effect (HR 0.74, 95% CI 0.58-0.95)...", "reportBody": "# Introduction\n\nGLP-1 receptor agonists have emerged as...", "abstract": "This systematic review examines the cardiovascular effects of..." } ``` ### SystematicReviewSessionCreated - **Type:**`object` * **`isPublic` (required)** `boolean` — Whether the review is publicly accessible via its URL without authentication * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`status` (required)** `string` — Initial status is always processing * **`type` (required)** `string` * **`url` (required)** `string` — URL to view the review in the Elicit web interface **Example:** ```json { "type": "systematicReview", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "url": "", "isPublic": true, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### SystematicReviewSessionDetail - **Type:**`object` * **`dataFreshness` (required)** `string | null` — ISO timestamp when the exports in \`data\` were last written to S3. null when no exports have been generated yet — see \`exportsStatus\` for why. * **`executionStage` (required)** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage. Advances through gathering\_sources → screening\_abstract → screening\_fulltext → extracting\_data → generating\_report → done. Null when the stage isn't known — treat it as unknown, not as not-started. * **`exportsStatus` (required)** `string`, possible values: `"ready", "generating", "unavailable"` — Availability of the export download URLs in \`data\`. \`ready\`: the URLs reflect the latest complete export set. \`generating\`: exports are currently being generated and nothing is cached yet. \`unavailable\`: export generation failed and nothing is cached — the structured report content still ships. * **`isPublic` (required)** `boolean` — Whether the review is publicly accessible via its URL without authentication * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status. Transitions: processing ⇄ pausedForInsufficientQuota (paused when the account exceeds its usage limit; stays paused until explicitly resumed via the resume endpoint or the Elicit web interface), processing → completed/failed. Poll until completed or failed. * **`type` (required)** `string` * **`url` (required)** `string` — URL to view the review in the Elicit web interface * **`data`** `object` — Stage-organized content and export URLs: per-stage \`search\`/\`screen\`/\`fulltext\`/\`extract\` CSV + XLSX downloads and \`report\` content plus pdf/docx/txt/bib/ris downloads. When \`exportsStatus\` is \`ready\`, stages absent from \`data\` did not run; when it is \`generating\` or \`unavailable\`, download URLs are temporarily missing rather than nonexistent. - **`extract`** `object` — Extraction-stage results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`fulltext`** `object` — Fulltext-screening results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`report`** `object` — Report-stage content and exports. - **`result` (required)** `object` — Structured report content (title, summary, optional body + abstract). - **`summary` (required)** `string` — AI-generated executive summary of the findings - **`title` (required)** `string` — Auto-generated title - **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. - **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. - **`bib`** `string`, format: `uri` — Presigned URL for a BibTeX bibliography of the papers synthesized in the report. Expires in 7 days. - **`docx`** `string`, format: `uri` — Presigned URL for the report DOCX. Expires in 7 days. - **`pdf`** `string`, format: `uri` — Presigned URL for the report PDF. Expires in 7 days. - **`ris`** `string`, format: `uri` — Presigned URL for a RIS bibliography of the papers synthesized in the report. Expires in 7 days. - **`txt`** `string`, format: `uri` — Presigned URL for an APA-style plain-text reference list of the papers synthesized in the report. Expires in 7 days. - **`screen`** `object` — Abstract-screening results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. - **`search`** `object` — Gather-stage paper list exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. * **`error`** `object` — Error details, only present when status is failed - **`code` (required)** `string` — Machine-readable error code - **`message` (required)** `string` — Human-readable error message **Example:** ```json { "type": "systematicReview", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "url": "", "isPublic": true, "error": { "code": "", "message": "" }, "data": { "search": { "csv": "", "xlsx": "" }, "screen": { "csv": "", "xlsx": "" }, "fulltext": { "csv": "", "xlsx": "" }, "extract": { "csv": "", "xlsx": "" }, "report": { "result": { "title": "", "summary": "", "reportBody": null, "abstract": null }, "pdf": "", "docx": "", "txt": "", "bib": "", "ris": "" } }, "dataFreshness": null, "exportsStatus": "ready", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### ReviewData - **Type:**`object` * **`extract`** `object` — Extraction-stage results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. * **`fulltext`** `object` — Fulltext-screening results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. * **`report`** `object` — Report-stage content and exports. - **`result` (required)** `object` — Structured report content (title, summary, optional body + abstract). - **`summary` (required)** `string` — AI-generated executive summary of the findings - **`title` (required)** `string` — Auto-generated title - **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. - **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. - **`bib`** `string`, format: `uri` — Presigned URL for a BibTeX bibliography of the papers synthesized in the report. Expires in 7 days. - **`docx`** `string`, format: `uri` — Presigned URL for the report DOCX. Expires in 7 days. - **`pdf`** `string`, format: `uri` — Presigned URL for the report PDF. Expires in 7 days. - **`ris`** `string`, format: `uri` — Presigned URL for a RIS bibliography of the papers synthesized in the report. Expires in 7 days. - **`txt`** `string`, format: `uri` — Presigned URL for an APA-style plain-text reference list of the papers synthesized in the report. Expires in 7 days. * **`screen`** `object` — Abstract-screening results exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. * **`search`** `object` — Gather-stage paper list exports. - **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. - **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. **Example:** ```json { "search": { "csv": "", "xlsx": "" }, "screen": { "csv": "", "xlsx": "" }, "fulltext": { "csv": "", "xlsx": "" }, "extract": { "csv": "", "xlsx": "" }, "report": { "result": { "title": "", "summary": "", "reportBody": null, "abstract": null }, "pdf": "", "docx": "", "txt": "", "bib": "", "ris": "" } } ``` ### StageData - **Type:**`object` * **`csv` (required)** `string`, format: `uri` — Presigned URL for the CSV export. Expires in 7 days. * **`xlsx` (required)** `string`, format: `uri` — Presigned URL for the XLSX export. Expires in 7 days. **Example:** ```json { "csv": "", "xlsx": "" } ``` ### ReportData - **Type:**`object` * **`result` (required)** `object` — Structured report content (title, summary, optional body + abstract). - **`summary` (required)** `string` — AI-generated executive summary of the findings - **`title` (required)** `string` — Auto-generated title - **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. - **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. * **`bib`** `string`, format: `uri` — Presigned URL for a BibTeX bibliography of the papers synthesized in the report. Expires in 7 days. * **`docx`** `string`, format: `uri` — Presigned URL for the report DOCX. Expires in 7 days. * **`pdf`** `string`, format: `uri` — Presigned URL for the report PDF. Expires in 7 days. * **`ris`** `string`, format: `uri` — Presigned URL for a RIS bibliography of the papers synthesized in the report. Expires in 7 days. * **`txt`** `string`, format: `uri` — Presigned URL for an APA-style plain-text reference list of the papers synthesized in the report. Expires in 7 days. **Example:** ```json { "result": { "title": "", "summary": "", "reportBody": null, "abstract": null }, "pdf": "", "docx": "", "txt": "", "bib": "", "ris": "" } ``` ### ReviewResult - **Type:**`object` * **`summary` (required)** `string` — AI-generated executive summary of the findings * **`title` (required)** `string` — Auto-generated title * **`abstract`** `string | null` — Report abstract in markdown format. Only included when ?include=reportBody is specified. * **`reportBody`** `string | null` — Full report content in markdown format. Only included when ?include=reportBody is specified. **Example:** ```json { "title": "", "summary": "", "reportBody": null, "abstract": null } ``` ### ListSessionsResponse - **Type:**`object` * **`nextCursor` (required)** `string | null` — Opaque cursor for the next page; pass it back as \`cursor\`. Null if there are no more results. * **`sessions` (required)** `array` — Reports, systematic reviews, and research-agent sessions interleaved, ordered by creation date (newest first) **Items:** - **`createdAt` (required)** `string` — ISO 8601 timestamp of when the report was created - **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication - **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. - **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` - **`source` (required)** `string`, possible values: `"user", "api", "mcp", "agent_session"` — How the report was created - **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the report - **`title` (required)** `string` — Report title (the research question) - **`type` (required)** `string`, possible values: `"report", "systematicReview", "agent"` — Which kind of session this is; use it to pick the matching typed get endpoint - **`url` (required)** `string` — URL to view the report in the Elicit web interface - **`executionStage`** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage, or null when not yet known. Omitted entirely for agent sessions, which have no pipeline stages. - **`role`** `string`, possible values: `"owner", "shared"` — The caller's relationship to this session: "owner" for a session the caller created, or "shared" for an agent session another user shared with them read-only. Reports and systematic reviews are always "owner". * **`totalCount` (required)** `integer` — Total sessions matching the filters across all pages. **Example:** ```json { "sessions": [ { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "title": "What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "source": "api", "createdAt": "2025-06-15T14:30:00.000Z", "isPublic": false, "role": "owner", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ], "nextCursor": "2025-06-15T14:30:00.000Z_5ad08bfb-cbe0-4911-a8c3-309760d33029", "totalCount": 1 } ``` ### SessionListItem - **Type:**`object` * **`createdAt` (required)** `string` — ISO 8601 timestamp of when the report was created * **`isPublic` (required)** `boolean` — Whether the report is publicly accessible via its URL without authentication * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`source` (required)** `string`, possible values: `"user", "api", "mcp", "agent_session"` — How the report was created * **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the report * **`title` (required)** `string` — Report title (the research question) * **`type` (required)** `string`, possible values: `"report", "systematicReview", "agent"` — Which kind of session this is; use it to pick the matching typed get endpoint * **`url` (required)** `string` — URL to view the report in the Elicit web interface * **`executionStage`** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — Current pipeline stage, or null when not yet known. Omitted entirely for agent sessions, which have no pipeline stages. * **`role`** `string`, possible values: `"owner", "shared"` — The caller's relationship to this session: "owner" for a session the caller created, or "shared" for an agent session another user shared with them read-only. Reports and systematic reviews are always "owner". **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "gathering_sources", "title": "What are the effects of GLP-1 receptor agonists on cardiovascular outcomes?", "url": "https://elicit.com/review/5ad08bfb-cbe0-4911-a8c3-309760d33029", "source": "api", "createdAt": "2025-06-15T14:30:00.000Z", "isPublic": false, "role": "owner", "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### ResumeSessionResponse - **Type:**`object` * **`executionStage` (required)** `string | null`, possible values: `"gathering_sources", "screening_abstract", "screening_fulltext", "extracting_data", "generating_report", "done", null` — The stage the session resumed at * **`isPublic` (required)** `boolean` * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Status after the resume — normally processing; completed or failed if the run finished while the resume was in flight. * **`type` (required)** `string`, possible values: `"report", "systematicReview", "agent"` — Which kind of session was resumed * **`url` (required)** `string` — URL to view this session in the Elicit web interface **Example:** ```json { "type": "report", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "executionStage": "screening_abstract", "url": "", "isPublic": true, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### CreateSessionShareResponse - **Type:**`object` * **`sessionId` (required)** `string` — Unique identifier for the session. * **`share` (required)** `object` - **`email` (required)** `string` — Email address the session is shared with. - **`role` (required)** `string` — Access level of the share. Sessions are always shared read-only. - **`status` (required)** `string`, possible values: `"registered", "invited"` — "registered" when the recipient already has an Elicit account and can read the session now; "invited" when a pending invitation was created for an email without an account. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "share": { "email": "colleague@example.com", "status": "registered", "role": "reader" }, "url": "" } ``` ### SessionShare - **Type:**`object` * **`email` (required)** `string` — Email address the session is shared with. * **`role` (required)** `string` — Access level of the share. Sessions are always shared read-only. * **`status` (required)** `string`, possible values: `"registered", "invited"` — "registered" when the recipient already has an Elicit account and can read the session now; "invited" when a pending invitation was created for an email without an account. **Example:** ```json { "email": "colleague@example.com", "status": "registered", "role": "reader" } ``` ### ListSessionSharesResponse - **Type:**`object` * **`sessionId` (required)** `string` — Unique identifier for the session. * **`shares` (required)** `array` — Everyone the session is currently shared with — both registered recipients and pending email invitations. **Items:** - **`email` (required)** `string` — Email address the session is shared with. - **`role` (required)** `string` — Access level of the share. Sessions are always shared read-only. - **`status` (required)** `string`, possible values: `"registered", "invited"` — "registered" when the recipient already has an Elicit account and can read the session now; "invited" when a pending invitation was created for an email without an account. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "shares": [ { "email": "colleague@example.com", "status": "registered", "role": "reader" } ], "url": "" } ``` ### DeleteSessionShareResponse - **Type:**`object` * **`email` (required)** `string` — Email address whose share was revoked. * **`revoked` (required)** `boolean` — Whether an existing share or pending invite was removed. False when there was nothing to revoke (the call is idempotent either way). * **`sessionId` (required)** `string` — Unique identifier for the session. **Example:** ```json { "sessionId": "", "email": "", "revoked": true } ``` ### GetUsageResponse - **Type:**`object` * **`extraUsage` (required)** `object` — Extra-usage amount and limit in USD cents. Null when extra usage is not enabled. * **`hasUsageRemaining` (required)** `boolean` — Whether the account still has usage available this billing period. False once both the plan limit and (if enabled) the extra-usage limit are exhausted. * **`percentUsed` (required)** `number` — Percentage of plan usage consumed this billing period. * **`periodEnd` (required)** `string` — ISO 8601 end of the current billing period. Monthly usage limits reset at this time. * **`periodStart` (required)** `string` — ISO 8601 start of the current billing period. **Example:** ```json { "hasUsageRemaining": true, "percentUsed": 1, "periodStart": "", "periodEnd": "", "extraUsage": { "limitUsdCents": null, "spentUsdCents": 1 } } ``` ### ExtraUsage - **Type:**`object` * **`limitUsdCents` (required)** `integer | null` — The extra-usage spending limit in USD cents, or null when extra usage is uncapped. * **`spentUsdCents` (required)** `integer` — Extra-usage spend so far this billing period, in USD cents. **Example:** ```json { "limitUsdCents": null, "spentUsdCents": 1 } ``` ### CreateAgentSessionResponse - **Type:**`object` * **`sessionId` (required)** `string` — Unique identifier for the research agent session. * **`status` (required)** `string` — Initial status is always processing. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "status": "processing", "url": "https://elicit.com/agent/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" } ``` ### AgentSessionDetail - **Type:**`object` * **`createdAt` (required)** `string` — ISO 8601 timestamp of when the session was created. * **`isPublic` (required)** `boolean` — Whether the session is publicly accessible via its URL without authentication. * **`links` (required)** `object` - **`self` (required)** `string` — API URL for this session's full status and results (the typed get endpoint for its type) - **`resume`** `string` — API URL to resume this session. Present only while the session is paused for insufficient quota. * **`sessionId` (required)** `string`, format: `uuid` — The session ID (UUID) returned by the create endpoints and \`GET /sessions\` * **`source` (required)** `string`, possible values: `"user", "api", "mcp", "agent_session"` — How the session was created. * **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the session: "processing" (running, or not yet started), "completed" (idle and awaiting input — not terminally finished), "failed" (the last turn ended with an error), or "pausedForInsufficientQuota" (paused at the account usage limit; resume once the limit clears). * **`title` (required)** `string` — Human-readable title of the session. * **`type` (required)** `string` — Discriminator identifying this as a research-agent session. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "type": "agent", "sessionId": "5ad08bfb-cbe0-4911-a8c3-309760d33029", "status": "processing", "title": "", "url": "", "source": "api", "createdAt": "2025-06-15T14:30:00.000Z", "isPublic": true, "links": { "self": "https://elicit.com/api/v2/sessions/reports/5ad08bfb-cbe0-4911-a8c3-309760d33029", "resume": "https://elicit.com/api/v2/sessions/5ad08bfb-cbe0-4911-a8c3-309760d33029/resume" } } ``` ### GetAgentSessionEventsResponse - **Type:**`object` * **`cursor` (required)** `string` — Opaque session-bound checkpoint. Always present. Pass it unchanged as the \`cursor\` query param on the next poll to receive later event occurrences. * **`events` (required)** `array` — Append-only view of the session's activity. Streaming deltas are collapsed into immutable resource snapshots; raw stream events are never returned. Later snapshots retain the same resource ID and receive a new eventId. With no cursor this is the full history; with a cursor it contains only later occurrences. **Items:** **One of:** - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`isInitial` (required)** `boolean` - **`kind` (required)** `string` - **`messageId` (required)** `string` - **`text` (required)** `string` * **`citations` (required)** `array` **Items:** - **`citationId` (required)** `string` — Identifier for this citation within the agent message. - **`quote` (required)** `string` — The passage from the source that supports the message. - **`reference` (required)** `string | null` — The inline citation this entry resolves. It matches, character for character, a single reference token inside the \`\…\\` markup in the message text (one entry per token, after comma-separated tokens are split). Use it to map inline references in the text to this citation; use the \`source\` field to identify the underlying source. \`null\` for citations with no inline reference (e.g. legacy quotes-array or artifact-content citations). - **`source` (required)** `object` - **`authors` (required)** `array` — Authors of the cited work, in display order. **Items:** `string` - **`doi` (required)** `string | null` — Digital Object Identifier (DOI), when available. - **`title` (required)** `string | null` — Title of the cited work. - **`url` (required)** `string | null` — Best available URL for the cited work. - **`venue` (required)** `string | null` — Journal, conference, repository, or other publication venue. - **`year` (required)** `integer | null` — Publication year. * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` * **`messageId` (required)** `string` * **`suggestedFollowUps` (required)** `array` **Items:** `string` * **`text` (required)** `string` — The agent's reply. Contains inline \`\…\\` markup wrapping one or more comma-separated reference tokens; split them and match each token against \`citations\[].reference\` to resolve it. Strip the markup for display. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` - **`options` (required)** `array | null` - **`prefilledText` (required)** `string | null` - **`questionId` (required)** `string` - **`responseFormat` (required)** `string`, possible values: `"text", "single_select", "multi_select"` - **`text` (required)** `string` * **`activityId` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` * **`status` (required)** `string`, possible values: `"started", "completed", "failed"` * **`summary` (required)** `string | null` * **`title` (required)** `string` - **`artifacts` (required)** `array` **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the artifact, stable within a session. Pass it to the download endpoint to retrieve the file. Never a raw storage key. - **`contentType` (required)** `string | null` — MIME type of the artifact, when known. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was produced, when known. - **`filename` (required)** `string` — Suggested filename for the downloaded artifact. - **`format` (required)** `string | null` — Subtype within the artifact (e.g. "pdf", "docx", "pptx"). For agent files it is the filename extension; null only when the filename has no extension. - **`kind` (required)** `string`, possible values: `"agent-saved-file", "agent-delivered-file", "prose-export", "presentation-export", "figure-export", "report-asset", "report-citation"` — The kind of artifact produced in the session. A delivered file lists once as "agent-delivered-file"; "agent-saved-file" denotes a file the agent saved to its workspace but did not deliver. - **`sizeBytes` (required)** `number | null` — Size of the artifact in bytes, when known. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`deliveredOutputs` (required)** `array` — Artifacts delivered by this source-history occurrence. This is an immutable metadata snapshot; query the artifacts resource for currently supported download formats. **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, stable within a session. Pass it to the artifact content endpoint to retrieve its contents. Never a raw storage key or entity hash. - **`caption` (required)** `string | null` — Optional caption describing the artifact. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was delivered, when known. - **`kind` (required)** `string`, possible values: `"table", "prose", "presentation", "figure"` — The kind of interactive artifact: table, prose, presentation, or figure. - **`rowCount` (required)** `integer | null` — Number of rows for a table artifact; null for non-table kinds. - **`title` (required)** `string` — Human-readable title of the artifact. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`code` (required)** `string`, possible values: `"agent_timed_out", "agent_api_error", "agent_failed"` - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` - **`message` (required)** `string` - **`retryable` (required)** `boolean` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` - **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. - **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. - **`kind` (required)** `string` * **`createdAt` (required)** `string | null` — ISO 8601 timestamp for the event. Null for historical events without one. * **`eventId` (required)** `string` — Stable opaque identifier for this immutable public event occurrence. * **`kind` (required)** `string` * **`sessionId` (required)** `string` — Unique identifier for the research agent session. * **`status` (required)** `string`, possible values: `"processing", "pausedForInsufficientQuota", "completed", "failed", "unknown"` — Current status of the session. Uses exactly the same value and semantics as the list and detail endpoints. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "processing", "events": [ { "eventId": "", "createdAt": null, "kind": "user_message", "messageId": "", "text": "", "isInitial": true } ], "cursor": "", "url": "" } ``` ### ReducedAgentEvent - **Type:** **Example:** ### PublicAgentArtifact - **Type:**`object` * **`artifactId` (required)** `string` — Opaque identifier for the artifact, stable within a session. Pass it to the download endpoint to retrieve the file. Never a raw storage key. * **`contentType` (required)** `string | null` — MIME type of the artifact, when known. * **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was produced, when known. * **`filename` (required)** `string` — Suggested filename for the downloaded artifact. * **`format` (required)** `string | null` — Subtype within the artifact (e.g. "pdf", "docx", "pptx"). For agent files it is the filename extension; null only when the filename has no extension. * **`kind` (required)** `string`, possible values: `"agent-saved-file", "agent-delivered-file", "prose-export", "presentation-export", "figure-export", "report-asset", "report-citation"` — The kind of artifact produced in the session. A delivered file lists once as "agent-delivered-file"; "agent-saved-file" denotes a file the agent saved to its workspace but did not deliver. * **`sizeBytes` (required)** `number | null` — Size of the artifact in bytes, when known. **Example:** ```json { "artifactId": "", "kind": "agent-saved-file", "format": null, "filename": "", "contentType": null, "sizeBytes": null, "createdAt": "2025-06-15T14:30:00.000Z" } ``` ### DeliveredOutputEventSnapshot - **Type:**`object` * **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, stable within a session. Pass it to the artifact content endpoint to retrieve its contents. Never a raw storage key or entity hash. * **`caption` (required)** `string | null` — Optional caption describing the artifact. * **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was delivered, when known. * **`kind` (required)** `string`, possible values: `"table", "prose", "presentation", "figure"` — The kind of interactive artifact: table, prose, presentation, or figure. * **`rowCount` (required)** `integer | null` — Number of rows for a table artifact; null for non-table kinds. * **`title` (required)** `string` — Human-readable title of the artifact. **Example:** ```json { "artifactId": "", "kind": "table", "title": "", "caption": null, "rowCount": null, "createdAt": "2025-06-15T14:30:00.000Z" } ``` ### PostAgentSessionMessageResponse - **Type:**`object` * **`messageId` (required)** `string` — Identifier of the inserted message. Correlate it with the messageId on the matching user\_message event. * **`sessionId` (required)** `string` — Unique identifier for the research agent session. * **`status` (required)** `string` — The session is processing the inserted message. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "processing", "messageId": "", "url": "" } ``` ### CreateFileResponse - **Type:**`object` * **`expires_at` (required)** `string` — ISO 8601 timestamp after which the upload URL and the staged file\_id are no longer valid. * **`file_id` (required)** `string` — Opaque identifier for the staged upload. Pass it in the \`attachments\` array of a create-session or send-message request to attach the file to that turn. * **`upload_url` (required)** `string` — Short-lived presigned S3 PUT URL. Upload the file bytes directly to it with the same Content-Type and Content-Length declared here. **Example:** ```json { "file_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "upload_url": "", "expires_at": "2026-07-23T15:00:00.000Z" } ``` ### GetAgentSessionArtifactsResponse - **Type:**`object` * **`artifacts` (required)** `array` — File-backed artifacts produced in the session. Only the latest version of each artifact is listed. Retrieve contents via the download endpoint. **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the artifact, stable within a session. Pass it to the download endpoint to retrieve the file. Never a raw storage key. - **`contentType` (required)** `string | null` — MIME type of the artifact, when known. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was produced, when known. - **`filename` (required)** `string` — Suggested filename for the downloaded artifact. - **`format` (required)** `string | null` — Subtype within the artifact (e.g. "pdf", "docx", "pptx"). For agent files it is the filename extension; null only when the filename has no extension. - **`kind` (required)** `string`, possible values: `"agent-saved-file", "agent-delivered-file", "prose-export", "presentation-export", "figure-export", "report-asset", "report-citation"` — The kind of artifact produced in the session. A delivered file lists once as "agent-delivered-file"; "agent-saved-file" denotes a file the agent saved to its workspace but did not deliver. - **`sizeBytes` (required)** `number | null` — Size of the artifact in bytes, when known. * **`deliveredOutputs` (required)** `array` — Interactive outputs (tables, prose, presentations, figures) delivered as session outputs. Only the latest delivery of each is listed. Retrieve contents via the artifact content endpoint. **Items:** - **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, stable within a session. Pass it to the artifact content endpoint to retrieve its contents. Never a raw storage key or entity hash. - **`caption` (required)** `string | null` — Optional caption describing the artifact. - **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was delivered, when known. - **`downloadFormats` (required)** `array` — File formats this artifact can be downloaded as from the content endpoint via ?format=\ (tables: csv/xlsx; prose: md; empty for other kinds). The JSON body is returned when no format is given. **Items:** `string`, possible values: `"csv", "xlsx", "md"` - **`kind` (required)** `string`, possible values: `"table", "prose", "presentation", "figure"` — The kind of interactive artifact: table, prose, presentation, or figure. - **`rowCount` (required)** `integer | null` — Number of rows for a table artifact; null for non-table kinds. - **`title` (required)** `string` — Human-readable title of the artifact. * **`sessionId` (required)** `string` — Unique identifier for the research agent session. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "artifacts": [ { "artifactId": "", "kind": "agent-saved-file", "format": null, "filename": "", "contentType": null, "sizeBytes": null, "createdAt": "2025-06-15T14:30:00.000Z" } ], "deliveredOutputs": [ { "artifactId": "", "kind": "table", "title": "", "caption": null, "rowCount": null, "createdAt": "2025-06-15T14:30:00.000Z", "downloadFormats": [ "csv" ] } ], "url": "" } ``` ### PublicDeliveredOutput - **Type:**`object` * **`artifactId` (required)** `string` — Opaque identifier for the interactive artifact, stable within a session. Pass it to the artifact content endpoint to retrieve its contents. Never a raw storage key or entity hash. * **`caption` (required)** `string | null` — Optional caption describing the artifact. * **`createdAt` (required)** `string | null` — ISO 8601 timestamp of when the artifact was delivered, when known. * **`downloadFormats` (required)** `array` — File formats this artifact can be downloaded as from the content endpoint via ?format=\ (tables: csv/xlsx; prose: md; empty for other kinds). The JSON body is returned when no format is given. **Items:** `string`, possible values: `"csv", "xlsx", "md"` * **`kind` (required)** `string`, possible values: `"table", "prose", "presentation", "figure"` — The kind of interactive artifact: table, prose, presentation, or figure. * **`rowCount` (required)** `integer | null` — Number of rows for a table artifact; null for non-table kinds. * **`title` (required)** `string` — Human-readable title of the artifact. **Example:** ```json { "artifactId": "", "kind": "table", "title": "", "caption": null, "rowCount": null, "createdAt": "2025-06-15T14:30:00.000Z", "downloadFormats": [ "csv" ] } ``` ### GetAgentSessionArtifactContentResponse - **Type:** **Example:** ### DownloadAgentSessionArtifactResponse - **Type:**`object` * **`contentType` (required)** `string | null` — MIME type of the artifact, when known. * **`downloadUrl` (required)** `string` — Short-lived presigned URL to download the artifact contents. * **`expiresAt` (required)** `string` — ISO 8601 timestamp after which the download URL is no longer valid. * **`filename` (required)** `string` — Suggested filename for the downloaded artifact. **Example:** ```json { "downloadUrl": "", "expiresAt": "2025-06-15T15:00:00.000Z", "filename": "", "contentType": null } ``` ### StopAgentSessionResponse - **Type:**`object` * **`sessionId` (required)** `string` — Unique identifier for the research agent session. * **`status` (required)** `string`, possible values: `"stopping", "stopped", "failed"` — "stopping" when a stop was queued (the session halts asynchronously; poll the events endpoint for the session\_stopped event). "stopped" or "failed" when the session had already ended and no stop was needed. * **`url` (required)** `string` — URL to view and continue the session in the Elicit web interface. **Example:** ```json { "sessionId": "", "status": "stopping", "url": "" } ``` ### ListLibrarySourcesResponse - **Type:**`object` * **`nextCursor` (required)** `string | null` — Pass as ?cursor= to fetch the next page; null on the last page. * **`sources` (required)** `array` **Items:** - **`abstract` (required)** `string | null` — Abstract as markdown. - **`authors` (required)** `array` **Items:** `string` - **`collectionIds` (required)** `array` — Collections this source belongs to that are visible to you. **Items:** `string`, format: `uuid` - **`createdAt` (required)** `string` - **`doi` (required)** `string | null` - **`elicitId` (required)** `string | null` — Elicit corpus id, present once the paper has been matched to the corpus. - **`fullTextStatus` (required)** `string`, possible values: `"pending", "available", "unavailable"` — Whether parsed full text is attached: pending — a PDF is still parsing, or none has been looked for yet; available — parsed and attached; unavailable — looked for, none found. - **`id` (required)** `string`, format: `uuid` — Stable id of the source. - **`links` (required)** `object` - **`fullText` (required)** `string` — API URL of the parsed full text; 404s until fullTextStatus is available. - **`self` (required)** `string` — API URL of this source. - **`pdfUrls` (required)** `array` **Items:** `string` - **`role` (required)** `string`, possible values: `"writer", "reader"` — Your role on this source: \`writer\` for your own sources and for a shared collection's papers when you own or can edit that collection; \`reader\` for a shared collection's papers you can only view. Any role can read the source and use it in reviews. Writers edit metadata, attach a PDF, delete, and add to collections. - **`title` (required)** `string | null` - **`updatedAt` (required)** `string` - **`url` (required)** `string | null` - **`venue` (required)** `string | null` - **`year` (required)** `integer | null` * **`totalCount` (required)** `integer` — Total matches for the query across all pages. **Example:** ```json { "sources": [ { "id": "", "title": null, "authors": [ "" ], "year": null, "venue": null, "abstract": null, "doi": null, "url": null, "elicitId": null, "pdfUrls": [ "" ], "collectionIds": [ "" ], "role": "writer", "fullTextStatus": "pending", "createdAt": "", "updatedAt": "", "links": { "self": "", "fullText": "" } } ], "nextCursor": null, "totalCount": 1 } ``` ### LibrarySource - **Type:**`object` * **`abstract` (required)** `string | null` — Abstract as markdown. * **`authors` (required)** `array` **Items:** `string` * **`collectionIds` (required)** `array` — Collections this source belongs to that are visible to you. **Items:** `string`, format: `uuid` * **`createdAt` (required)** `string` * **`doi` (required)** `string | null` * **`elicitId` (required)** `string | null` — Elicit corpus id, present once the paper has been matched to the corpus. * **`fullTextStatus` (required)** `string`, possible values: `"pending", "available", "unavailable"` — Whether parsed full text is attached: pending — a PDF is still parsing, or none has been looked for yet; available — parsed and attached; unavailable — looked for, none found. * **`id` (required)** `string`, format: `uuid` — Stable id of the source. * **`links` (required)** `object` - **`fullText` (required)** `string` — API URL of the parsed full text; 404s until fullTextStatus is available. - **`self` (required)** `string` — API URL of this source. * **`pdfUrls` (required)** `array` **Items:** `string` * **`role` (required)** `string`, possible values: `"writer", "reader"` — Your role on this source: \`writer\` for your own sources and for a shared collection's papers when you own or can edit that collection; \`reader\` for a shared collection's papers you can only view. Any role can read the source and use it in reviews. Writers edit metadata, attach a PDF, delete, and add to collections. * **`title` (required)** `string | null` * **`updatedAt` (required)** `string` * **`url` (required)** `string | null` * **`venue` (required)** `string | null` * **`year` (required)** `integer | null` **Example:** ```json { "id": "", "title": null, "authors": [ "" ], "year": null, "venue": null, "abstract": null, "doi": null, "url": null, "elicitId": null, "pdfUrls": [ "" ], "collectionIds": [ "" ], "role": "writer", "fullTextStatus": "pending", "createdAt": "", "updatedAt": "", "links": { "self": "", "fullText": "" } } ``` ### CreateLibrarySourceItem - **Type:** **Example:** ### CorpusReferenceItem - **Type:**`object` A paper from Elicit search, by `elicitId`. Other fields are optional. - **`elicitId` (required)** `string` - **`abstract`** `string` — Plain text or markdown; blank lines separate paragraphs. - **`authors`** `array` **Items:** `string` - **`doi`** `string` — Send the title and authors with it, so the record is useful if the DOI is not in Elicit's corpus. - **`pdfUrls`** `array` — Direct PDF links. Fetched and parsed when the paper is not in the Elicit corpus; a PDF URL alone is enough. **Items:** `string`, format: `uri` - **`title`** `string` - **`url`** `string`, format: `uri` - **`venue`** `string` - **`year`** `integer` **Example:** ```json { "title": "", "authors": [ "" ], "year": 1000, "venue": "", "abstract": "", "doi": "", "elicitId": "", "url": "", "pdfUrls": [ "" ] } ``` ### DocumentItem - **Type:**`object` A PDF by URL. Elicit parses it and fills the metadata; other fields are optional. - **`pdfUrls` (required)** `array` — Direct PDF links. Fetched and parsed when the paper is not in the Elicit corpus; a PDF URL alone is enough. **Items:** `string`, format: `uri` - **`abstract`** `string` — Plain text or markdown; blank lines separate paragraphs. - **`authors`** `array` **Items:** `string` - **`doi`** `string` — Send the title and authors with it, so the record is useful if the DOI is not in Elicit's corpus. - **`elicitId`** `string` - **`title`** `string` - **`url`** `string`, format: `uri` - **`venue`** `string` - **`year`** `integer` **Example:** ```json { "title": "", "authors": [ "" ], "year": 1000, "venue": "", "abstract": "", "doi": "", "elicitId": "", "url": "", "pdfUrls": [ "" ] } ``` ### CitationItem - **Type:**`object` A paper by `title` plus at least one of `doi`, `authors`, `year`, `venue`, `abstract`, `url`. **Any of:** **Example:** ```json { "title": "", "authors": [ "" ], "year": 1000, "venue": "", "abstract": "", "doi": "", "elicitId": "", "url": "", "pdfUrls": [ "" ] } ``` ### CreateLibrarySourcesResponse - **Type:**`object` * **`sources` (required)** `array` **Items:** **All of:** - **`abstract` (required)** `string | null` — Abstract as markdown. - **`authors` (required)** `array` **Items:** `string` - **`collectionIds` (required)** `array` — Collections this source belongs to that are visible to you. **Items:** `string`, format: `uuid` - **`createdAt` (required)** `string` - **`doi` (required)** `string | null` - **`elicitId` (required)** `string | null` — Elicit corpus id, present once the paper has been matched to the corpus. - **`fullTextStatus` (required)** `string`, possible values: `"pending", "available", "unavailable"` — Whether parsed full text is attached: pending — a PDF is still parsing, or none has been looked for yet; available — parsed and attached; unavailable — looked for, none found. - **`id` (required)** `string`, format: `uuid` — Stable id of the source. - **`links` (required)** `object` - **`fullText` (required)** `string` — API URL of the parsed full text; 404s until fullTextStatus is available. - **`self` (required)** `string` — API URL of this source. - **`pdfUrls` (required)** `array` **Items:** `string` - **`role` (required)** `string`, possible values: `"writer", "reader"` — Your role on this source: \`writer\` for your own sources and for a shared collection's papers when you own or can edit that collection; \`reader\` for a shared collection's papers you can only view. Any role can read the source and use it in reviews. Writers edit metadata, attach a PDF, delete, and add to collections. - **`title` (required)** `string | null` - **`updatedAt` (required)** `string` - **`url` (required)** `string | null` - **`venue` (required)** `string | null` - **`year` (required)** `integer | null` **Example:** ```json { "sources": [ { "id": "", "title": null, "authors": [ "" ], "year": null, "venue": null, "abstract": null, "doi": null, "url": null, "elicitId": null, "pdfUrls": [ "" ], "collectionIds": [ "" ], "role": "writer", "fullTextStatus": "pending", "createdAt": "", "updatedAt": "", "links": { "self": "", "fullText": "" } } ] } ``` ### CreatedLibrarySource - **Type:** **Example:** ### GetLibrarySourceFullTextResponse - **Type:**`object` * **`markdown` (required)** `string` — The parsed paper — title, abstract, and body — as markdown. **Example:** ```json { "markdown": "" } ``` ### ListLibraryCollectionsResponse - **Type:**`object` * **`collections` (required)** `array` **Items:** - **`description` (required)** `string` - **`id` (required)** `string`, format: `uuid` - **`kind` (required)** `string`, possible values: `"personal", "group"` — \`personal\`: never shared; lists your own sources. \`group\`: has been shared at least once; owns copies of its sources, and stays a group collection. - **`links` (required)** `object` - **`self` (required)** `string` — API URL of this collection. - **`sources` (required)** `string` — URL listing the sources in this collection. - **`name` (required)** `string` - **`role` (required)** `string`, possible values: `"owner", "writer", "reader"` — Your access level. A reader can view the collection. A writer can also add and remove sources and edit the name and description. An owner can also delete the collection and change who it is shared with. - **`sourceCount` (required)** `integer` - **`sharedVia`** `string`, possible values: `"direct", "organization"` — \`direct\` if the owner shared the collection with you. \`organization\` if the owner shared it with your organization. Absent on your own collections. * **`nextCursor` (required)** `string | null` * **`totalCount` (required)** `integer` **Example:** ```json { "collections": [ { "id": "", "name": "", "description": "", "role": "owner", "kind": "personal", "sharedVia": "direct", "sourceCount": 1, "links": { "self": "", "sources": "" } } ], "nextCursor": null, "totalCount": 1 } ``` ### LibraryCollection - **Type:**`object` * **`description` (required)** `string` * **`id` (required)** `string`, format: `uuid` * **`kind` (required)** `string`, possible values: `"personal", "group"` — \`personal\`: never shared; lists your own sources. \`group\`: has been shared at least once; owns copies of its sources, and stays a group collection. * **`links` (required)** `object` - **`self` (required)** `string` — API URL of this collection. - **`sources` (required)** `string` — URL listing the sources in this collection. * **`name` (required)** `string` * **`role` (required)** `string`, possible values: `"owner", "writer", "reader"` — Your access level. A reader can view the collection. A writer can also add and remove sources and edit the name and description. An owner can also delete the collection and change who it is shared with. * **`sourceCount` (required)** `integer` * **`sharedVia`** `string`, possible values: `"direct", "organization"` — \`direct\` if the owner shared the collection with you. \`organization\` if the owner shared it with your organization. Absent on your own collections. **Example:** ```json { "id": "", "name": "", "description": "", "role": "owner", "kind": "personal", "sharedVia": "direct", "sourceCount": 1, "links": { "self": "", "sources": "" } } ``` ### LibraryImport - **Type:**`object` * **`completedAt` (required)** `string | null` * **`createdAt` (required)** `string` * **`files` (required)** `array` **Items:** - **`duplicateOf` (required)** `string | null`, format: `uuid` — The already-saved source this file matched. - **`error` (required)** `object | null` — processing-error and server-error may succeed on retry. - **`code` (required)** `string`, possible values: `"duplicate", "processing-error", "server-error", "invalid-file", "unknown"` - **`message` (required)** `string` - **`fileId` (required)** `string`, format: `uuid` - **`filename` (required)** `string` - **`sourceId` (required)** `string | null`, format: `uuid` - **`status` (required)** `string`, possible values: `"pending", "created", "duplicate", "failed"` * **`id` (required)** `string`, format: `uuid` * **`links` (required)** `object` - **`self` (required)** `string` — Poll this URL until status is completed. * **`status` (required)** `string`, possible values: `"processing", "completed"` **Example:** ```json { "id": "", "status": "processing", "files": [ { "fileId": "", "filename": "", "status": "pending", "sourceId": null, "duplicateOf": null, "error": { "code": "duplicate", "message": "" } } ], "createdAt": "", "completedAt": null, "links": { "self": "" } } ``` ### AddLibraryCollectionSourcesResponse - **Type:**`object` * **`added` (required)** `array` — The sources this call added. **Items:** - **`collectionSourceId` (required)** `string`, format: `uuid` — Id of the paper inside the collection. A group collection keeps its own copy, so this differs from sourceId; a personal collection holds the source itself. - **`sourceId` (required)** `string`, format: `uuid` * **`addedCount` (required)** `integer` — Sources newly added; sources already in the collection are skipped. * **`duplicates` (required)** `array` — Sources that were not added because the collection already has the same paper. Papers match by Elicit id, DOI, title, or identical PDF. **Items:** - **`duplicateOf` (required)** `string`, format: `uuid` — The id of the source that is already in the collection; the source itself when it was already a member. - **`sourceId` (required)** `string`, format: `uuid` **Example:** ```json { "addedCount": 1, "added": [ { "sourceId": "", "collectionSourceId": "" } ], "duplicates": [ { "sourceId": "", "duplicateOf": "" } ] } ``` ### RemoveLibraryCollectionSourcesResponse - **Type:**`object` * **`removedCount` (required)** `integer` — Sources removed; ids not in the collection are skipped. A member's own source stays in their library. A shared collection's own paper moves to the collection's trash for 30 days. **Example:** ```json { "removedCount": 1 } ```