Documentation Index
Fetch the complete documentation index at: https://mintlify.com/bio-xyz/BioAgents/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Paper Retrieval API provides access to previously generated research papers. Use this to retrieve papers, get fresh download URLs, and list all papers for a conversation.
Authentication
All endpoints require authentication via:
- JWT token in
Authorization header
- API key in
X-API-Key header
- x402/b402 payment proof
URL Expiration
Presigned URLs expire after 1 hour. Always request fresh URLs when downloading papers:
- ✅ Request URL → Download immediately
- ✅ Request URL → Download within 1 hour
- ❌ Cache URL → Download later (will fail after 1 hour)
Endpoints
Get Paper
GET /api/deep-research/paper/:paperId
Get fresh presigned URLs for a paper
Path Parameters
Paper ID (UUID returned from generation)
Response
{
"success": true,
"paperId": "550e8400-e29b-41d4-a716-446655440000",
"conversationId": "660e8400-e29b-41d4-a716-446655440000",
"pdfPath": "user/USER_ID/conversation/CONV_ID/papers/PAPER_ID/paper.pdf",
"pdfUrl": "https://s3.amazonaws.com/bucket/path?X-Amz-Signature=...",
"rawLatexUrl": "https://s3.amazonaws.com/bucket/path/main.tex?X-Amz-Signature=...",
"createdAt": "2024-01-01T12:00:00Z"
}
S3 storage path (for reference)
Presigned URL for PDF download (expires in 1 hour)
Presigned URL for LaTeX source (may be null for older papers)
Paper creation timestamp (ISO 8601)
cURL Example
curl -X GET https://api.bioagents.ai/api/deep-research/paper/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Download Example
# Get paper URLs
RESPONSE=$(curl -s -X GET \
https://api.bioagents.ai/api/deep-research/paper/$PAPER_ID \
-H "Authorization: Bearer $JWT_TOKEN")
# Extract URLs
PDF_URL=$(echo $RESPONSE | jq -r '.pdfUrl')
LATEX_URL=$(echo $RESPONSE | jq -r '.rawLatexUrl')
# Download files
curl -o paper.pdf "$PDF_URL"
curl -o main.tex "$LATEX_URL"
List Papers
GET /api/deep-research/conversations/:conversationId/papers
List all papers for a conversation
Path Parameters
Conversation ID to list papers for
Response
{
"success": true,
"conversationId": "660e8400-e29b-41d4-a716-446655440000",
"papers": [
{
"paperId": "550e8400-e29b-41d4-a716-446655440000",
"pdfPath": "user/.../papers/.../paper.pdf",
"status": "completed",
"createdAt": "2024-01-01T12:00:00Z"
},
{
"paperId": "660e8400-e29b-41d4-a716-446655440001",
"pdfPath": "user/.../papers/.../paper.pdf",
"status": "completed",
"createdAt": "2024-01-01T11:00:00Z"
}
]
}
Array of paper metadata objects, sorted by creation date (newest first)
Paper status: pending, processing, completed, or failed
Creation timestamp (ISO 8601)
cURL Example
curl -X GET https://api.bioagents.ai/api/deep-research/conversations/CONVERSATION_ID/papers \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Download All Papers Example
# Get paper list
RESPONSE=$(curl -s -X GET \
https://api.bioagents.ai/api/deep-research/conversations/$CONVERSATION_ID/papers \
-H "Authorization: Bearer $JWT_TOKEN")
# Extract paper IDs
echo $RESPONSE | jq -r '.papers[].paperId' | while read PAPER_ID; do
# Get fresh URLs for each paper
PAPER=$(curl -s https://api.bioagents.ai/api/deep-research/paper/$PAPER_ID \
-H "Authorization: Bearer $JWT_TOKEN")
# Download PDF
PDF_URL=$(echo $PAPER | jq -r '.pdfUrl')
curl -o "paper_${PAPER_ID}.pdf" "$PDF_URL"
echo "Downloaded: paper_${PAPER_ID}.pdf"
done
Check Paper Status
GET /api/deep-research/paper/:paperId/status
Check paper generation status (for async jobs)
See Paper Generation API for details.
Error Responses
401 Unauthorized
{
"error": "Authentication required",
"message": "Valid authentication is required to access papers"
}
403 Forbidden
{
"error": "Access denied",
"message": "You do not have permission to access this paper"
}
This occurs when attempting to access another user’s paper.
404 Not Found (Paper)
{
"error": "Paper not found",
"message": "Paper with id 550e8400-e29b-41d4-a716-446655440000 not found"
}
404 Not Found (Conversation)
{
"error": "Conversation not found",
"message": "Conversation with id 660e8400-e29b-41d4-a716-446655440000 not found"
}
500 Internal Server Error
{
"error": "Failed to get paper",
"message": "Storage provider unavailable"
}
503 Service Unavailable
{
"error": "Storage unavailable",
"message": "Storage provider is not configured"
}
Each paper includes:
File Structure
user/{userId}/conversation/{conversationId}/papers/{paperId}/
├── paper.pdf # Compiled PDF
├── main.tex # LaTeX source
└── figures/ # Embedded figures (if any)
├── figure1.png
└── figure2.png
Paper Contents
- Title: Derived from research objective
- Abstract: Summary of findings
- Sections: Introduction, Methods, Results, Discussion, Conclusion
- References: All cited papers with DOIs
- Figures: Analysis artifacts with captions
Integration Examples
JavaScript/TypeScript
interface Paper {
paperId: string;
conversationId: string;
pdfUrl: string;
rawLatexUrl?: string;
createdAt: string;
}
async function getPaper(paperId: string, token: string): Promise<Paper> {
const response = await fetch(
`https://api.bioagents.ai/api/deep-research/paper/${paperId}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
if (!response.ok) {
throw new Error(`Failed to get paper: ${response.statusText}`);
}
return response.json();
}
async function downloadPaper(paperId: string, token: string): Promise<Blob> {
const paper = await getPaper(paperId, token);
const response = await fetch(paper.pdfUrl);
return response.blob();
}
// Usage
const paper = await getPaper('550e8400-e29b-41d4-a716-446655440000', token);
const blob = await downloadPaper(paper.paperId, token);
// Create download link
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'research-paper.pdf';
a.click();
URL.revokeObjectURL(url);
Python
import requests
import json
from typing import Dict, List
class PaperClient:
def __init__(self, base_url: str, token: str):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {token}"}
def get_paper(self, paper_id: str) -> Dict:
"""Get paper metadata with fresh URLs"""
response = requests.get(
f"{self.base_url}/api/deep-research/paper/{paper_id}",
headers=self.headers
)
response.raise_for_status()
return response.json()
def list_papers(self, conversation_id: str) -> List[Dict]:
"""List all papers for a conversation"""
response = requests.get(
f"{self.base_url}/api/deep-research/conversations/{conversation_id}/papers",
headers=self.headers
)
response.raise_for_status()
return response.json()["papers"]
def download_paper(self, paper_id: str, output_path: str):
"""Download paper PDF"""
paper = self.get_paper(paper_id)
# Download from presigned URL
response = requests.get(paper["pdfUrl"])
response.raise_for_status()
with open(output_path, "wb") as f:
f.write(response.content)
print(f"Downloaded: {output_path}")
# Usage
client = PaperClient("https://api.bioagents.ai", token)
papers = client.list_papers(conversation_id)
for paper in papers:
if paper["status"] == "completed":
client.download_paper(paper["paperId"], f"paper_{paper['paperId']}.pdf")
Best Practices
1. Always Request Fresh URLs
Don’t cache presigned URLs for more than a few minutes:
// ❌ Bad: Cache URL for long-term use
const paper = await getPaper(paperId);
localStorage.setItem('pdfUrl', paper.pdfUrl); // Will expire!
// ✅ Good: Request fresh URL when needed
async function downloadWhenNeeded(paperId) {
const paper = await getPaper(paperId);
return fetch(paper.pdfUrl);
}
2. Handle Missing LaTeX Sources
Older papers may not have LaTeX sources:
const paper = await getPaper(paperId);
if (paper.rawLatexUrl) {
// Download LaTeX source
const latex = await fetch(paper.rawLatexUrl);
} else {
console.log('LaTeX source not available for this paper');
}
3. Verify Paper Status Before Download
const papers = await listPapers(conversationId);
for (const paper of papers) {
if (paper.status === 'completed') {
await downloadPaper(paper.paperId);
} else if (paper.status === 'failed') {
console.error(`Paper ${paper.paperId} generation failed`);
} else {
console.log(`Paper ${paper.paperId} is ${paper.status}`);
}
}