VerifyScience API

v1.0 Documentation

Go to Dashboard

API Documentation

Integrate AI-powered research verification into your applications with our comprehensive REST API

6
API Endpoints
REST
Architecture
JSON
Response Format
HTTPS
Secure Connection
1

Getting Started

Base URL

https://www.verifyscience.co.uk

Quick Start

  1. 1
    Sign up at verifyscience.co.uk
  2. 2
    Generate API key from Account Settings โ†’ API Keys
  3. 3
    Make requests using your API key in the Authorization header
One subscription for both GUI and API. Your verification quota is shared across web dashboard and API calls.
2

Authentication

All API requests require authentication using your API key in the Authorization header as a Bearer token.

Authorization: Bearer vs_live_your_api_key_here
Keep your API key secure! Never expose it in client-side code, public repositories, or version control systems. Treat it like a password.
3

Pricing & Rate Limits

Choose the plan that fits your needs. All plans include both web dashboard and API access with shared verification quotas.

Tier Price Verifications/Month Rate Limit Batch API
Free ยฃ0 3 5 requests/minute โ€”
Starter ยฃ4.99/month 199 20 requests/minute โ€”
Professional ยฃ9.99/month 499 60 requests/minute โœ“ up to 20 papers
Enterprise ยฃ19.99/month 1,999 120 requests/minute โœ“ up to 50 papers
Rate limits protect our infrastructure and ensure fair usage. Requests exceeding your rate limit will receive a 429 Too Many Requests response.
4

API Endpoints

Get User Information

GET
GET /v1/me

Retrieve information about your account, including subscription tier and remaining verifications.

Response

{
  "user_id": "user_abc123",
  "email": "[email protected]",
  "subscription": "professional",
  "verifications_left": 485,
  "verifications_limit": 499,
  "rate_limit": "60 requests/minute"
}

Start Verification

POST
POST /v1/verifications

Submit a research paper for AI-powered methodological analysis. Returns a job ID immediately; poll for results.

Request Body

{
  "content": "https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.0020124",
  "method": "url"
}
Field Type Description
content string ยท required The paper to verify. URL, DOI URL, or raw text. Minimum 50 characters. For DOI links, use the full resolved article URL (e.g. journals.plos.org/...) rather than a bare doi.org/ link โ€” short DOIs will be rejected.
method string ยท optional "url" (default) or "text". Use "url" when content is a URL; "text" when pasting raw paper content.

DOI links: Use the full article page URL, not the short doi.org redirect. Open-access papers on PLOS, PubMed Central, arXiv, and bioRxiv work reliably. Paywalled papers should be submitted as text โ€” paste the abstract and methods section directly.

Response

{
  "id": "job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
  "status": "processing",
  "message": "Verification started successfully"
}

Get Verification Result

GET
GET /v1/verifications/{id}

Retrieve the results of a verification job by its ID.

Response (Processing)

{
  "id": "job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
  "status": "processing",
  "progress": 45
}

Response (Completed)

{
  "id": "job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
  "status": "completed",
  "result": {
    "confidence": 78,
    "confidence_level": "High",
    "summary": "This research demonstrates strong methodology...",
    "domain_category": "Clinical trial methodology",
    "domain_detail": "Randomised controlled trial",
    "criteria": [
      {
        "name": "Analytical Dimension",
        "score": 85,
        "assessment": "Adequate sample size for statistical power"
      },
      {
        "name": "Methodology",
        "score": 82,
        "assessment": "Well-designed experimental approach"
      }
    ],
    "strengths": ["Large sample size", "Controlled variables"],
    "limitations": ["Limited follow-up period"],
    "created_at": "2026-03-25T00:30:00Z"
  }
}

confidence field: A holistic assessment of the paper's credibility (0–100), constrained to within ±20 points of the mean of the per-criterion analysis scores. It reflects the paper's methodological rigour, publication context, post-publication record, and weight of subsequent evidence. A server-side guardrail enforces this constraint; if the AI-generated score deviates beyond the ±20 band, it is clamped and the original value is preserved in confidence_original.

domain_category field: Abstracted research domain detected from the paper โ€” e.g. "Clinical trial methodology", "Qualitative research", "Computational / engineering research". Returned for all tiers. Displayed in the UI for Professional and Enterprise subscribers only.

domain_detail field: Specific methodology type โ€” e.g. "Randomised controlled trial", "Phenomenological interview study". Returned for Professional and Enterprise tiers only.

framework_applied field: The primary quality assessment framework applied. Returned for Enterprise tier only under contract. Not present in this example response.

criteria_applicability field: Per-criterion applicability map โ€” values are "standard", "adapted", or "not applicable". Returned for Professional and Enterprise tiers only. Not present in this example response.

List Verifications

GET
GET /v1/verifications

Retrieve a list of all your verification jobs with pagination support.

Query Parameters

  • limit (optional) - Number of results per page (default: 50, max: 100)
  • offset (optional) - Number of results to skip (default: 0)

Response

{
  "verifications": [
    {
      "id": "job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
      "status": "completed",
      "confidence": 78,
      "created_at": "2026-03-25T00:30:00Z"
    },
    {
      "id": "job_e4a1b2c3-d4e5-f6g7-h8i9-j0k1l2m3n4o5",
      "status": "processing",
      "progress": 45,
      "created_at": "2026-03-24T22:15:00Z"
    }
  ],
  "total": 14,
  "limit": 50,
  "offset": 0
}
6

Error Codes

The API uses standard HTTP status codes to indicate success or failure.

200

OK

Request succeeded

400

Bad Request

Invalid request parameters or missing required fields

401

Unauthorized

Missing or invalid API key

403

Forbidden

API key valid but lacks permission for this resource

404

Not Found

Requested resource doesn't exist

429

Too Many Requests

Rate limit exceeded - wait before retrying

500

Internal Server Error

Something went wrong on our end - please try again

Error Response Format

{
  "error": "Invalid API key",
  "message": "The provided API key is invalid or has been revoked",
  "code": "invalid_api_key"
}
5

Batch Verification API

Professional & Enterprise only
Batch API is available on Professional and Enterprise plans only. It allows you to submit multiple papers in a single request and receive results via email when processing is complete. Professional plans support up to 20 papers per batch. Enterprise plans support up to 50 papers per batch. Batch jobs consume your monthly verification quota.

Compare Two Papers

POST Professional+
POST /v1/compare

Submit two papers for side-by-side methodological comparison. Returns two job IDs immediately — poll each independently using GET /v1/verifications/{id}. Consumes 2 verifications. Requires Professional or Enterprise plan.

Request Body

{
  "content_a": "https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.0020124",
  "content_b": "https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.1001743"
}
Field Type Description
content_a string · required First paper. URL or raw text. Minimum 50 characters. Use full article page URL for DOIs.
content_b string · required Second paper. URL or raw text. Minimum 50 characters. Use full article page URL for DOIs.

Response (202 Accepted)

{
  "status": "ok",
  "job_a": "job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
  "job_b": "job_f1a3c921-11bb-4c2d-b711-889900aabbcc",
  "poll_a": "/v1/verifications/job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
  "poll_b": "/v1/verifications/job_f1a3c921-11bb-4c2d-b711-889900aabbcc",
  "verifications_consumed": 2,
  "message": "Both papers queued for analysis. Poll each job independently using the poll URLs."
}

Polling: Both jobs run in parallel. Poll poll_a and poll_b independently every 9–15 seconds. Professional tier takes 2–4 minutes per paper.

Python example

import requests, time

API_KEY = 'vs_live_your_api_key_here'
BASE = 'https://www.verifyscience.co.uk'
H = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}

r = requests.post(f'{BASE}/v1/compare', headers=H, json={
    'content_a': 'https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.0020124',
    'content_b': 'https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.1001743'
})
data = r.json()
job_a, job_b = data['job_a'], data['job_b']

def poll(job_id):
    for _ in range(80):
        d = requests.get(f'{BASE}/v1/verifications/{job_id}', headers=H).json()
        if d.get('status') == 'completed': return d['result']
        if d.get('status') == 'failed': raise Exception(d.get('error'))
        time.sleep(9)
    raise TimeoutError('Job timed out')

result_a, result_b = poll(job_a), poll(job_b)
delta = result_a['confidence'] - result_b['confidence']
print(f"A: {result_a['confidence']}  B: {result_b['confidence']}  Delta: {delta:+d}")

Submit Batch

POST Pro+
POST /api/verify-batch

Submit a list of paper URLs for parallel verification. Processing runs in the background โ€” results are delivered to your registered email address when complete. The response returns a batch_id for status polling.

Request Body

{
  "csv_content": "https://pubmed.ncbi.nlm.nih.gov/123456/\nhttps://www.nature.com/articles/example\nhttps://doi.org/10.1038/s41586-026-00001-1",
  "method": "url"
}

Parameters

  • csv_content required ยท string

    One URL or DOI per line. Blank lines are ignored. A header row starting with url, doi, or title is automatically detected and skipped.

  • method optional ยท string ยท default: "url"

    Input type. Accepted values: "url", "text".

Success Response โ€” 200

{
  "batch_id": "batch_550e8400-e29b-41d4-a716-446655440000",
  "total_papers": 3,
  "status": "queued",
  "message": "Batch verification queued successfully",
  "poll_url": "/api/verify-batch-status?batch_id=batch_550e8400-e29b-41d4-a716-446655440000",
  "estimated_time_minutes": 2
}

Tier Limit Errors โ€” 400 / 403

{
  "status": "error",
  "error": {
    "code": "BATCH_TOO_LARGE",
    "message": "Batch exceeds limit for professional tier",
    "details": {
      "papers_submitted": 25,
      "max_allowed": 20,
      "tier": "professional"
    },
    "next_steps": [
      "Reduce to 20 papers or less",
      "Enterprise plan supports up to 50 papers per batch"
    ]
  }
}

Get Batch Status

GET Pro+
GET /api/verify-batch-status?batch_id={batch_id}

Poll for real-time batch processing progress. The recommended polling interval is 5 seconds. When should_poll is false, processing is complete and polling should stop.

Query Parameters

  • batch_id required ยท string

    The batch ID returned from the submit endpoint. Format: batch_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

  • include_details optional ยท boolean ยท default: false

    When true, includes full verification results for all completed papers in the response.

Response โ€” Processing

{
  "batch_id": "batch_550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "total_papers": 3,
  "completed_papers": 1,
  "failed_papers": 0,
  "progress_percent": 33,
  "success_rate": 100,
  "created_at": "2026-04-05T08:30:00Z",
  "started_at": "2026-04-05T08:30:05Z",
  "estimated_seconds_remaining": 120,
  "should_poll": true,
  "poll_interval_seconds": 5
}

Response โ€” Completed (with include_details=true)

{
  "batch_id": "batch_550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "total_papers": 3,
  "completed_papers": 3,
  "failed_papers": 0,
  "progress_percent": 100,
  "success_rate": 100,
  "created_at": "2026-04-05T08:30:00Z",
  "started_at": "2026-04-05T08:30:05Z",
  "completed_at": "2026-04-05T08:32:18Z",
  "duration_seconds": 133,
  "should_poll": false,
  "verifications": [
    {
      "id": "job_dc2f5b45-73ac-420e-9eac-a78c2f9a0abe",
      "batch_index": 0,
      "status": "completed",
      "result": {
        "title": "Effects of Exercise on Cognitive Function in Older Adults",
        "confidence": 82,
        "summary": "Well-designed RCT with adequate statistical power...",
        "analysis": [
          { "criterion": "Analytical Dimension", "score": 85, "explanation": "..." },
          { "criterion": "Assessment Area", "score": 80, "explanation": "..." }
        ]
      },
      "completed_at": "2026-04-05T08:31:02Z"
    }
  ]
}

Batch API Limits at a Glance

Plan Batch API Access Max papers per batch Processing Results delivery
Free โ€” โ€” โ€” โ€”
Starter โ€” โ€” โ€” โ€”
Professional โœ“ 20 Parallel ยท 5 concurrent Email + in-app
Enterprise โœ“ 50 Parallel ยท 5 concurrent Email + in-app

Batch jobs consume your monthly verification quota. A 20-paper batch deducts 20 verifications from your allowance. The background processor runs every 60 seconds and applies a 30-minute timeout to any stalled job.

7

Code Examples

JavaScript (Fetch API)

// Start a verification
const startVerification = async () => {
  const response = await fetch('https://www.verifyscience.co.uk/v1/verifications', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer vs_live_your_api_key_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      text: 'Your research text here...',
      metadata: {
        title: 'Study Title',
        source: 'Journal Name'
      }
    })
  });

  const data = await response.json();
  console.log('Verification started:', data.id);
  
  // Poll for results
  return pollForResults(data.id);
};

// Check verification status
const pollForResults = async (jobId) => {
  const response = await fetch(`https://www.verifyscience.co.uk/v1/verifications/${jobId}`, {
    headers: {
      'Authorization': 'Bearer vs_live_your_api_key_here'
    }
  });

  const data = await response.json();
  
  if (data.status === 'completed') {
    console.log('Verification complete!', data.result);
    return data.result;
  } else {
    console.log('Still processing...', data.progress, '%');
    // Wait 2 seconds and check again
    await new Promise(resolve => setTimeout(resolve, 2000));
    return pollForResults(jobId);
  }
};

startVerification();

Python (Requests)

import requests
import time

API_KEY = 'vs_live_your_api_key_here'
BASE_URL = 'https://www.verifyscience.co.uk'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json'
}

# Start verification
response = requests.post(
    f'{BASE_URL}/v1/verifications',
    headers=headers,
    json={
        'text': 'Your research text here...',
        'metadata': {
            'title': 'Study Title',
            'source': 'Journal Name'
        }
    }
)

data = response.json()
job_id = data['id']
print(f'Verification started: {id}')

# Poll for results
while True:
    response = requests.get(
        f'{BASE_URL}/v1/verifications/{id}',
        headers=headers
    )
    data = response.json()
    
    if data['status'] == 'completed':
        print('Verification complete!')
        print(f"Confidence: {data['result']['confidence']}%")
        print(f"Summary: {data['result']['summary']}")
        break
    else:
        print(f"Still processing... {data.get('progress', 0)}%")
        time.sleep(2)

Node.js (Axios)

const axios = require('axios');

const API_KEY = 'vs_live_your_api_key_here';
const BASE_URL = 'https://www.verifyscience.co.uk';

const client = axios.create({
  baseURL: BASE_URL,
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  }
});

async function verifyResearch(text, metadata = {}) {
  try {
    // Start verification
    const { data: startData } = await client.post('/v1/verifications', {
      text,
      metadata
    });

    console.log('Verification started:', startData.id);

    // Poll for results
    while (true) {
      const { data: statusData } = await client.get(
        `/v1/verifications/${startData.id}`
      );

      if (statusData.status === 'completed') {
        console.log('Verification complete!');
        return statusData.result;
      }

      console.log(`Progress: ${statusData.progress}%`);
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
    throw error;
  }
}

// Example usage
verifyResearch(
  'Your research text here...',
  { title: 'Study Title', source: 'Journal Name' }
).then(result => {
  console.log('Confidence:', result.confidence);
  console.log('Summary:', result.summary);
});

Batch Verification (Python)

Professional+ only
import requests
import time

API_KEY = 'vs_live_your_api_key_here'
BASE_URL = 'https://www.verifyscience.co.uk'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json'
}

# Submit a batch of paper URLs (Professional: max 20, Enterprise: max 50)
urls = [
    'https://pubmed.ncbi.nlm.nih.gov/123456/',
    'https://www.nature.com/articles/example',
    'https://doi.org/10.1038/s41586-026-00001-1'
]

response = requests.post(
    f'{BASE_URL}/api/verify-batch',
    headers=headers,
    json={
        'csv_content': '\n'.join(urls),
        'method': 'url'
    }
)

data = response.json()
batch_id = data['batch_id']
print(f'Batch submitted: {batch_id}')
print(f'Estimated time: {data["estimated_time_minutes"]} minutes')

# Poll for results every 5 seconds
while True:
    response = requests.get(
        f'{BASE_URL}/api/verify-batch-status',
        headers=headers,
        params={
            'batch_id': batch_id,
            'include_details': 'true'
        }
    )
    status = response.json()

    print(f'Progress: {status["progress_percent"]}% '
          f'({status["completed_papers"]}/{status["total_papers"]} complete)')

    if not status.get('should_poll', True):
        print('\nBatch complete!')
        for v in status.get('verifications', []):
            if v['status'] == 'completed':
                title = v['result'].get('title', 'Untitled')
                confidence = v['result'].get('confidence', 0)
                print(f'  [{confidence}%] {title}')
            else:
                print(f'  [FAILED] Paper {v["batch_index"] + 1}: {v.get("error")}')
        break

    time.sleep(status.get('poll_interval_seconds', 5))

Batch Verification (JavaScript)

Professional+ only
const API_KEY = 'vs_live_your_api_key_here';
const BASE_URL = 'https://www.verifyscience.co.uk';

const headers = {
  'Authorization': `Bearer ${API_KEY}`,
  'Content-Type': 'application/json'
};

// Submit batch โ€” Professional: max 20 URLs, Enterprise: max 50
const urls = [
  'https://pubmed.ncbi.nlm.nih.gov/123456/',
  'https://www.nature.com/articles/example',
  'https://doi.org/10.1038/s41586-026-00001-1'
];

const submitBatch = async () => {
  const res = await fetch(`${BASE_URL}/api/verify-batch`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      csv_content: urls.join('\n'),
      method: 'url'
    })
  });

  const { batch_id, estimated_time_minutes } = await res.json();
  console.log(`Batch submitted: ${batch_id}`);
  console.log(`Estimated time: ${estimated_time_minutes} minutes`);

  // Poll until complete
  while (true) {
    const statusRes = await fetch(
      `${BASE_URL}/api/verify-batch-status?batch_id=${batch_id}&include_details=true`,
      { headers }
    );
    const status = await statusRes.json();

    console.log(`Progress: ${status.progress_percent}% ` +
      `(${status.completed_papers}/${status.total_papers})`);

    if (!status.should_poll) {
      console.log('Batch complete!');
      for (const v of status.verifications || []) {
        if (v.status === 'completed') {
          console.log(`  [${v.result.confidence}%] ${v.result.title}`);
        } else {
          console.log(`  [FAILED] Paper ${v.batch_index + 1}: ${v.error}`);
        }
      }
      break;
    }

    await new Promise(r => setTimeout(r, (status.poll_interval_seconds || 5) * 1000));
  }
};

submitBatch();

Need Help?

Have questions or need assistance integrating the VerifyScience API? We're here to help!