# isitcredible.com — API Documentation

The isitcredible.com API allows you to submit academic texts for automated peer review and retrieve results programmatically. Jobs are charged against your account balance. Top up your balance from your [account page](https://isitcredible.com/account).

**Base URL:** `https://isitcredible.com/api/v1`

---

## Authentication

Generate an API key from your [account page](https://isitcredible.com/account). Include it as a Bearer token in every request:

```
Authorization: Bearer iic_your_api_key_here
```

Keys require a verified email address. They are stored as one-way hashes — if you lose a key, revoke it and generate a new one.

---

## Report Options

Each job is configured with boolean flags. At least one of `do_report` or `do_code` must be set.

| Flag | Price | Description |
|------|-------|-------------|
| `do_report` | $5.00 | The full simulated peer review report: methodological critique, identified issues, a reference check of the paper's bibliography, and directions for future research. Default `true`. |
| `do_math` | +$5.00 | A deep audit of the paper's mathematics: derivations, proofs, and reported numbers are checked and, where possible, recomputed. Requires `do_report`. |
| `do_copyedit` | +$2.00 | An editorial note advising how to respond to the review, and a proofreading pass. Requires `do_report`. |
| `do_code` | $3.50 + $0.03/page | A Data Editor review of a replication package supplied via `code_files`. Priced per compiled code page; data and output files are excluded automatically and not billed. The code is read, not executed. May be ordered alone or alongside a report. |

**Length-based pricing.** The report-side prices above cover a main text (plus supplements) of up to 50 pages. Above that, the report-side total scales by 1% per additional page — so a 100-page submission costs 1.5× the flat price. The code charge is independent of main-text length. If your balance is insufficient, the `402` error states the exact price for your submission.

**Legacy modes.** The former `mode` parameter is still accepted: `standard` maps to `do_report`, `extended` to `do_report` + `do_copyedit`, and `inspect_code=true` to `do_code`.

Prices may change. Registered account holders will be notified by email before any change takes effect.

---

## Endpoints

### GET /api/v1/credits

Return current account balance.

**Response:**
```json
{"balance_cents": 1500, "balance_usd": 15.0}
```

---

### GET /api/v1/jobs

List your last 50 jobs.

**Response:**
```json
[
  {
    "uuid": "a1b2c3d4",
    "status": "completed",
    "mode": "standard",
    "title": "On the Origins of...",
    "authors": "Smith, J. et al.",
    "audit_date": "2026-03-06T14:22:00"
  }
]
```

---

### GET /api/v1/jobs/{job_id}

Get status and metadata for a job. When `status` is `completed` or `published`, a `report_url` field is included.

**Terminal statuses:** `completed`, `published`, `failed`, `suspended`

**Response:**
```json
{
  "uuid": "a1b2c3d4",
  "status": "completed",
  "mode": "standard",
  "title": "On the Origins of...",
  "authors": "Smith, J. et al.",
  "discipline": "Economics",
  "audit_date": "2026-03-06T14:22:00",
  "report_url": "https://isitcredible.com/api/v1/jobs/a1b2c3d4/report"
}
```

---

### GET /api/v1/jobs/{job_id}/report

Download the finished PDF or TXT report.

Accepts an optional query parameter `format` (default: `pdf`). Set to `txt` for plain text.

Returns the report as `application/pdf` or `text/plain`. Returns `425 Too Early` if the report is not yet ready — poll `GET /api/v1/jobs/{job_id}` until status is `completed`.

---

### POST /api/v1/jobs

Submit a document for analysis. Accepts `multipart/form-data`.

**Parameters:**

| Parameter | | Description |
|-----------|---|-------------|
| `main_file` | required | The document to review, as a **PDF**. Max 200 MB, 1,000 pages (main text plus supplements). Must not be encrypted. |
| `supp_files` | optional | Supplementary PDFs (online appendices, supplemental material). May be repeated. Pages count toward the page limit and length-based pricing. |
| `do_report`, `do_math`, `do_copyedit`, `do_code` | optional | Booleans selecting the report options above. Default: `do_report=true`, all others `false`. |
| `code_files` | optional | The replication package for `do_code`. May be repeated; up to 10 GB total. Data and output files are filtered out automatically — only code, readmes, and documentation are reviewed and billed. |
| `user_note` | optional | Context for the reviewer, e.g. *"This is a draft chapter on Victorian economic history."* |
| `webhook_url` | optional | URL to receive a POST when the job completes, as an alternative to polling. |
| `mode` | optional | Legacy: `standard` or `extended` (see Report Options). |

**Response (202 Accepted):**
```json
{
  "job_id": "a1b2c3d4",
  "status": "processing",
  "mode": "standard",
  "message": "Job submitted. Poll GET /api/v1/jobs/a1b2c3d4 for status."
}
```

---

## Error Reference

| Code | Meaning |
|------|---------|
| `401` | Missing or invalid API key. |
| `402` | Insufficient balance — the error message states the exact price for your submission. Top up at your [account page](https://isitcredible.com/account). |
| `403` | Email address not verified. Log in to resend the verification link. |
| `404` | Job not found, or does not belong to your account. |
| `400` | Invalid input — file too large, word/page limit exceeded, unsupported file type, encrypted PDF, or invalid flag combination. |
| `425` | Report not ready yet. Keep polling. |
| `500` | Server error. |

---

## Examples

### curl

```bash
# Check balance
curl https://isitcredible.com/api/v1/credits \
     -H "Authorization: Bearer iic_your_key"

# Submit a PDF for the standard report
curl -X POST https://isitcredible.com/api/v1/jobs \
     -H "Authorization: Bearer iic_your_key" \
     -F "main_file=@paper.pdf" \
     -F "user_note=This is a draft journal article in economics."

# Report + math audit, with a supplementary appendix
curl -X POST https://isitcredible.com/api/v1/jobs \
     -H "Authorization: Bearer iic_your_key" \
     -F "main_file=@paper.pdf" \
     -F "supp_files=@appendix.pdf" \
     -F "do_math=true"

# Report + code review of a replication package
curl -X POST https://isitcredible.com/api/v1/jobs \
     -H "Authorization: Bearer iic_your_key" \
     -F "main_file=@paper.pdf" \
     -F "do_code=true" \
     -F "code_files=@analysis.do" \
     -F "code_files=@build_data.R" \
     -F "code_files=@README.md"

# Poll for status
curl https://isitcredible.com/api/v1/jobs/a1b2c3d4 \
     -H "Authorization: Bearer iic_your_key"

# Download report (once status is 'completed')
curl -OJ "https://isitcredible.com/api/v1/jobs/a1b2c3d4/report?format=txt" \
     -H "Authorization: Bearer iic_your_key"
```

### Python

```python
import requests, time

API_KEY = "iic_your_key"
BASE    = "https://isitcredible.com/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# Submit with a math audit
with open("paper.pdf", "rb") as f:
    r = requests.post(
        f"{BASE}/jobs",
        headers=HEADERS,
        files={"main_file": f},
        data={"do_math": "true", "user_note": "Draft economics paper."}
    )
r.raise_for_status()
job_id = r.json()["job_id"]

# Submit with a code review
with open("paper.pdf", "rb") as f, \
     open("analysis.do", "rb") as c1, \
     open("README.md", "rb") as c2:
    r = requests.post(
        f"{BASE}/jobs",
        headers=HEADERS,
        files=[
            ("main_file",  ("paper.pdf",   f,  "application/pdf")),
            ("code_files", ("analysis.do", c1, "text/plain")),
            ("code_files", ("README.md",   c2, "text/plain")),
        ],
        data={"do_code": "true"}
    )
r.raise_for_status()
job_id = r.json()["job_id"]

# Poll until complete (jobs typically take 20–60 minutes)
while True:
    job = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS).json()
    print(f"Status: {job['status']}")
    if job["status"] in ("completed", "published"):
        break
    if job["status"] in ("failed", "suspended"):
        raise RuntimeError(f"Job {job['status']}")
    time.sleep(60)

# Download PDF
report = requests.get(f"{BASE}/jobs/{job_id}/report", headers=HEADERS)
report.raise_for_status()
with open("report.pdf", "wb") as f:
    f.write(report.content)
```

---

## Python SDK

A higher-level client is available via pip:

```bash
pip install isitcredible
```

```python
from isitcredible import Client, JobTimeoutError

client = Client("iic_your_api_key")

# Standard review
report = client.analyze("paper.pdf")
report.save("review.pdf")

# Review with math audit and code review
report = client.analyze(
    "paper.pdf",
    do_math=True,
    do_code=True,
    code_files=["analysis.do", "README.md"],
)
report.save("review.pdf")

# Handle timeouts — the job keeps running on the server
try:
    report = client.analyze("paper.pdf", timeout=3600)
except JobTimeoutError as e:
    print(f"Still running. Resume with: client.wait('{e.job_id}')")

# Webhook management
client.create_webhook("https://yourapp.com/webhook")
hooks = client.list_webhooks()
```

The SDK handles polling, retries, downloading, and webhook management automatically, and accepts the same `do_math` / `do_copyedit` / `do_code` options as the HTTP API, e.g. `client.analyze("paper.pdf", do_math=True)`.

---

*isitcredible.com — automated peer review*
