Integrate proofed.ai into your applications. Submit documents for AI-powered proofreading, receive structured corrections, and wire up webhooks for completion events.
All API requests require a Bearer token in the Authorization header. Generate API keys from your Settings page after logging in.
Authorization: Bearer your-api-token
https://proofed.ai/api/v1
Every document moves through a series of statuses. Once submitted, our AI proofreading engine reads the document, identifies issues, and returns structured corrections.
pendingprocessingcompletedfailedcancelledTypical processing time: 30 seconds to 5 minutes depending on document length. Larger documents use an agentic reading mode and may take up to 30 minutes.
/api/v1/documents
Upload a file for proofreading. Requires multipart/form-data. Consumes one token from your balance.
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | The document file (max 50MB). Supported: pdf, docx, pptx, html, htm, txt, rtf, odt. For DOCX files with track changes, insertions are accepted and deletions discarded — we read the "final" version. PPTX is ingest-only: findings are returned as JSON and no annotated output file is produced. |
language |
string | No | Language code. Supported: en, en-GB, en-US, es, fr, de, it, pt. Default: en |
webhook_url |
string | No | URL to receive a POST when processing completes (success or failure). See Webhooks. |
curl -X POST https://proofed.ai/api/v1/documents \
-H "Authorization: Bearer your-api-token" \
-F "file=@report.pdf" \
-F "language=en" \
-F "webhook_url=https://your-app.com/webhook"
{
"data": {
"uuid": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"filename": "report.pdf",
"file_type": "pdf",
"file_size": 102400,
"language": "en",
"status": "pending",
"source": "api",
"correction_count": null,
"webhook_url": "https://your-app.com/webhook",
"submitted_at": null,
"completed_at": null,
"created_at": "2026-04-16T12:00:00+00:00"
}
}
/api/v1/documents
Returns a paginated list of your documents, newest first. 20 per page.
curl https://proofed.ai/api/v1/documents \
-H "Authorization: Bearer your-api-token"
/api/v1/documents/{uuid}
Returns document details. The full corrections array is included on this endpoint but omitted from the list endpoint.
{
"data": {
"uuid": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"filename": "report.pdf",
"file_type": "pdf",
"file_size": 102400,
"language": "en",
"status": "completed",
"source": "api",
"correction_count": 5,
"corrections_data": [
{
"type": "spelling",
"original": "achivements",
"corrected": "achievements",
"context": "Misspelling",
"page": 3
}
],
"webhook_url": "https://your-app.com/webhook",
"submitted_at": "2026-04-16T12:00:05+00:00",
"completed_at": "2026-04-16T12:00:42+00:00",
"created_at": "2026-04-16T12:00:00+00:00"
}
}
/api/v1/documents/{uuid}/cancel
Cancel a pending or processing document. Completed, failed, or already-cancelled documents cannot be cancelled (returns 422).
Cancellation is cooperative — if the AI is mid-call, it finishes that step and stops at the next turn boundary.
{
"message": "Document cancelled."
}
| Field | Type | Description |
|---|---|---|
uuid |
string | Stable document identifier. Use this to reference documents in other API calls. |
filename |
string | Original filename as uploaded. |
file_type |
string | Lowercase extension, e.g. pdf, docx. |
file_size |
integer | Size in bytes. |
language |
string | Language code. |
status |
string | One of pending, processing, completed, failed, cancelled. |
source |
string | Where the document came from: api, web, email. |
correction_count |
integer | Number of corrections found. null while pending/processing. |
corrections_data |
array | Array of correction objects (only on the Get Document endpoint). See Correction Shape. |
webhook_url |
string|null | Webhook delivery target, if one was provided. |
submitted_at |
ISO8601|null | When the document was submitted to the AI provider. |
completed_at |
ISO8601|null | When processing completed (success or failure). |
created_at |
ISO8601 | When the document was uploaded. |
Each entry in corrections_data follows this shape. The AI produces both replacement corrections (with a suggested fix) and comments (judgment calls flagged for a human editor to review).
| Field | Type | Description |
|---|---|---|
type |
string | Category: spelling, grammar, punctuation, style, consistency, clarity, tone, word_choice, formatting, or other. |
original |
string | The text as it appears in the document. |
corrected |
string | The suggested replacement. For comments, this may be the comment text. |
context |
string | Short rationale explaining why this is an issue. |
page |
integer|null | Page number (when known). |
If you provide a webhook_url when submitting a document, we will send a POST request to that URL when processing reaches a terminal state (completed or failed).
{
"event": "document.completed",
"document": {
"uuid": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"filename": "report.pdf",
"status": "completed",
"correction_count": 5
},
"timestamp": "2026-04-16T12:00:42+00:00"
}
The event field is document.{status}, e.g. document.completed or document.failed. Webhook delivery is retried up to 3 times with a 30-second delay between attempts. Any non-2xx response is treated as a failure and retried.
To fetch the full corrections, call the Get Document endpoint using the uuid from the payload.
If you cannot receive webhooks, poll the Get Document endpoint. We recommend a 15-second interval while status is pending or processing. Documents typically complete within 1–5 minutes.
while document.status in ("pending", "processing"):
sleep(15)
document = get_document(uuid)
if document.status == "completed":
process_corrections(document.corrections_data)
else:
handle_failure(document.status)
Proofed.ai also offers an editor quality review feature: upload an original document and an editor's version, and the AI assesses the editor's work against a baseline proofread. The output is a structured feedback report with a score and categorised findings.
Admin-only — not currently available via the public API.
This feature is available to admin users through the proofed.ai web interface. Public API access is on the roadmap — contact support if you have a use case.
Admin users can submit reviews at /admin/reviews/submit in the proofed.ai web app. Users with the George permission can submit at /reviews/submit. DOCX files with track changes are fully supported — we read the "final accepted" version of the editor's work.
Reviewer Feedback (internal codename "Huxley") compares a reviewer's final copy against the editor's final copy, infers why the reviewer made each change by matching it to the style guide, and returns rule-grouped feedback the reviewer can scan, adjust, and send to the editor. Designed to save reviewers time when giving constructive feedback.
Requires the Huxley permission on your account.
Admins grant this per-user. Without it, all reviewer-feedback endpoints return 403.
Feedback jobs move through pending → processing → completed / failed / cancelled, the same states as documents. Typical runtime: 2–6 minutes depending on document length and number of differences.
/api/v1/reviewer-feedback
Upload the editor's final copy and the reviewer's final copy. multipart/form-data. Both files should be the final versions — no track changes.
| Field | Type | Required | Description |
|---|---|---|---|
editor_file |
file | Yes | The editor's final copy. Max 50MB. Supported: pdf, docx, pptx, html, htm, txt, rtf, odt. |
reviewer_file |
file | Yes | The reviewer's final copy. Same constraints. |
language |
string | No | Language code. Supported: en, en-GB, en-US, es, fr, de, it, pt. Default: en |
style_guide_url |
string | No | Optional Stylus style-guide URL. Huxley uses it to map reviewer changes to named rules. Without one, findings are grouped by theme. |
webhook_url |
string | No | URL to POST when the job reaches a terminal state. See Reviewer Feedback Webhooks. |
order_id |
string | No | Your reference for the order this feedback relates to. Max 255 chars. Echoed back in responses and webhooks. |
job_id |
string | No | Your reference for the job this feedback relates to. Max 255 chars. Echoed back in responses and webhooks. |
curl -X POST https://proofed.ai/api/v1/reviewer-feedback \
-H "Authorization: Bearer your-api-token" \
-F "editor_file=@editor-final.docx" \
-F "reviewer_file=@reviewer-final.docx" \
-F "language=en" \
-F "style_guide_url=https://stylus.proofedapps.com/api/style-guides/abc-123" \
-F "webhook_url=https://your-app.com/webhook" \
-F "order_id=ORD-2026-0417" \
-F "job_id=JOB-9812"
{
"data": {
"uuid": "7c2a1d5e-3f4b-4c6d-8e9f-0a1b2c3d4e5f",
"editor_filename": "editor-final.docx",
"reviewer_filename": "reviewer-final.docx",
"language": "en",
"status": "pending",
"style_guide_url": "https://stylus.proofedapps.com/api/style-guides/abc-123",
"webhook_url": "https://your-app.com/webhook",
"order_id": "ORD-2026-0417",
"job_id": "JOB-9812",
"narrative": null,
"finding_count": null,
"diff_count": null,
"report_available": false,
"submitted_at": null,
"completed_at": null,
"created_at": "2026-04-17T15:00:00+00:00"
}
}
/api/v1/reviewer-feedback
Paginated list of your reviewer-feedback jobs, newest first. 20 per page.
curl https://proofed.ai/api/v1/reviewer-feedback \
-H "Authorization: Bearer your-api-token"
/api/v1/reviewer-feedback/{uuid}
Returns the full feedback draft, including the rule-grouped findings, summary, and reviewer-only tone notes. On in-progress jobs, findings/summary are null and narrative describes the current step.
{
"data": {
"uuid": "7c2a1d5e-3f4b-4c6d-8e9f-0a1b2c3d4e5f",
"editor_filename": "editor-final.docx",
"reviewer_filename": "reviewer-final.docx",
"language": "en",
"status": "completed",
"style_guide_url": "https://stylus.proofedapps.com/api/style-guides/abc-123",
"webhook_url": "https://your-app.com/webhook",
"order_id": "ORD-2026-0417",
"job_id": "JOB-9812",
"narrative": null,
"finding_count": 3,
"diff_count": 14,
"summary": "Three recurring themes across your edit...",
"tone_notes": "Keep it constructive — the editor caught most of the heavy lifting.",
"findings": [
{
"rule_slug": "currency-abbreviations",
"rule_name": "Currency in Billions",
"rule_description": "Abbreviate as bn.",
"summary": "Use bn for currency in the billions.",
"examples": [
{ "paragraph": "14", "from": "$4 billion", "to": "$4bn" }
]
}
],
"report_available": true,
"submitted_at": "2026-04-17T15:00:05+00:00",
"completed_at": "2026-04-17T15:03:42+00:00",
"created_at": "2026-04-17T15:00:00+00:00"
}
}
| Field | Type | Description |
|---|---|---|
rule_slug |
string | Machine-readable identifier for the rule or theme. |
rule_name |
string | Human-readable rule name (from the style guide if one was provided). |
rule_description |
string | The rule description from the style guide. |
summary |
string | One-sentence feedback the reviewer can send to the editor. |
examples |
array | Concrete examples showing paragraph number, original text, and the reviewer's change. |
/api/v1/reviewer-feedback/{uuid}/cancel
Cancel a pending or processing job. Terminal jobs return 403.
{
"message": "Reviewer feedback cancelled."
}
/api/v1/reviewer-feedback/{uuid}/report
Returns the generated DOCX feedback report (application/vnd.openxmlformats-officedocument.wordprocessingml.document). Available once status is completed — returns 404 otherwise. The filename is derived from the reviewer file, suffixed with -huxley-feedback.docx.
curl https://proofed.ai/api/v1/reviewer-feedback/{uuid}/report \
-H "Authorization: Bearer your-api-token" \
-o feedback.docx
If you provide a webhook_url on submit, we POST to it when the job reaches a terminal state. Retried up to 3 times with 30-second backoff.
{
"event": "reviewer-feedback.completed",
"reviewer_feedback": {
"uuid": "7c2a1d5e-3f4b-4c6d-8e9f-0a1b2c3d4e5f",
"editor_filename": "editor-final.docx",
"reviewer_filename": "reviewer-final.docx",
"status": "completed",
"order_id": "ORD-2026-0417",
"job_id": "JOB-9812",
"finding_count": 3,
"diff_count": 14
},
"timestamp": "2026-04-17T15:03:42+00:00"
}
event is reviewer-feedback.{status}, e.g. reviewer-feedback.completed or reviewer-feedback.failed. To fetch findings, call Get Reviewer Feedback with the uuid.
| Code | Description |
|---|---|
401 |
Unauthorized — invalid or missing API token |
402 |
Payment Required — insufficient tokens. Top up to submit more documents. |
403 |
Forbidden — you do not have access to this resource |
404 |
Not Found — the resource does not exist |
422 |
Unprocessable Entity — validation errors or invalid state transition (e.g. cancelling a completed document) |
429 |
Too Many Requests — rate limit exceeded |
$client = new \GuzzleHttp\Client();
$response = $client->post('https://proofed.ai/api/v1/documents', [
'headers' => [
'Authorization' => 'Bearer ' . $apiToken,
],
'multipart' => [
[
'name' => 'file',
'contents' => fopen('/path/to/report.pdf', 'r'),
'filename' => 'report.pdf',
],
[
'name' => 'language',
'contents' => 'en',
],
],
]);
$document = json_decode($response->getBody(), true)['data'];
const form = new FormData();
form.append('file', fs.createReadStream('./report.pdf'));
form.append('language', 'en');
const response = await fetch('https://proofed.ai/api/v1/documents', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`,
},
body: form,
});
const { data } = await response.json();
import requests
response = requests.post(
'https://proofed.ai/api/v1/documents',
headers={'Authorization': f'Bearer {api_token}'},
files={'file': open('report.pdf', 'rb')},
data={'language': 'en'},
)
document = response.json()['data']