# Use the Citation API Use workspace scoped API keys, durable jobs and prepaid credits to work with documents, sources, writing, Check and files. ## Connect to the API Use https://citation.co/api/v1 for API v1. The existing automation API at /api/automation/v1, MCP and CLI keep their own contracts and credentials. 1. Open API in settings. Select one workspace and the permissions your application needs. 2. Create a key and copy its secret immediately. Store it on your server. The secret is only shown when created or rotated. 3. Send Authorization: Bearer with the key. Call /me to verify the workspace, expiry and permissions. Verify your key ```bash export CITATION_API_BASE=https://citation.co/api/v1 curl "$CITATION_API_BASE/me" \ -H "Authorization: Bearer $CITATION_API_KEY" ``` - [Open API settings](/settings/api) - [Download OpenAPI 3.1](/openapi.json) ## Permissions and access Keys belong to one workspace and expire after 1 to 90 days. Rotation invalidates the previous secret while retaining the connection and its request history. Revocation stops future access. Membership and document roles are checked again when work starts, before changes are saved and before files are downloaded. | Scope | Use | | --- | --- | | documents:read | Read documents and history | | documents:write | Create, update, trash, restore and apply edits | | sources:read | Read sources, resolve new sources and format references | | sources:write | Save and update source records | | exports:read | Export and download document files | | ai:write | Use the Write tools | | checks:write | Start Check and review findings | | files:write | Upload and import files | | sharing:read | Read document access | | sharing:write | Manage document guests, invitations and public links | | comments:read | Read comments | | comments:write | Add and resolve comments | | webhooks:write | Manage webhook subscriptions and deliveries | Document operations require documents:read. Source and paid document operations also need sources:read. Applying edits requires documents:write. Only a document owner can manage sharing. An editor can resolve their own comments, and an owner can resolve any comment. API permissions never grant a broader workspace role. ## Documents, sources and citations | Method | Path | Purpose | | --- | --- | --- | | GET, POST | /documents | List, search or create | | GET, PATCH, DELETE | /documents/{id} | Read, update or move to trash | | POST | /documents/{id}/restore | Restore from trash | | GET | /documents/{id}/history | Read version history | | GET, POST | /documents/{id}/sources | Read or save source records | | GET, PATCH | /documents/{id}/sources/{source_id} | Read or update a source | | POST | /documents/{id}/citations | Insert a citation at an editor position | | GET | /documents/{id}/bibliography | Render saved references | | GET | /documents/{id}/citation-check | Inspect citation links | | GET, PATCH | /documents/{id}/writing-context | Read or save a brief, outline, style and document memory | Create a document ```bash curl "$CITATION_API_BASE/documents" \ -H "Authorization: Bearer $CITATION_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $REQUEST_ID" \ -d '{"title":"Reading notes","text":"A draft to review.","style":"apa"}' ``` Read the document before editing. Send its version with PATCH. Use content for Citation editor JSON to preserve marks and citation nodes. Sending text replaces rich content. Change style through the same version checked update. Source updates use the source version returned by its read endpoint. Existing source records are not removed by document edits. List endpoints return items, has_more and next_cursor. Send next_cursor as after with the same query. The default limit is 20 and the maximum is 50. Document text is returned in pages of up to 20000 characters with next_offset. Bibliography pages use offset and snapshot_id, which detects changed documents or sources. ## Durable jobs and safe application | POST path | Operation | Credits | | --- | --- | --- | | /write | Write using Citation standard model selection | 1 | | /sources/resolve | Find sources by DOI, ISBN, URL or text query | 1 | | /imports | Import a draft or PDF source | 1 | | /exports | Export a document or bibliography | 1 | | /checks | Review up to 5000 words | 5 | Paid operations require max_credits. The API rejects a request when its fixed price exceeds that ceiling. An accepted operation returns HTTP 202 with job_id, status and credits. Poll GET /jobs/{job_id} until status is succeeded, failed or cancelled. POST /jobs/{job_id}/cancel requests cancellation. A running provider call may finish before cancellation takes effect. Request a writing proposal ```json { "document_id": "DOCUMENT_ID", "version": 3, "intent": "rewrite", "message": "Improve clarity and preserve the evidence.", "selection": "The exact passage to revise.", "source_ids": [], "apply": false, "max_credits": 1 } ``` Write supports brief, outline, section, sources, synthesis, argument, style, rewrite, memory, feedback and completion. Source based writing needs selected saved sources with readable excerpts or linked text. Section writing needs a saved outline. AI accepts up to 10000 document words and 12 selected sources. Generated output is limited to 2000 words. Limits are rejected explicitly. Write and Check return proposals by default. Set apply to true with the starting document version to request supported edits in the same job. result.application reports applied, no_changes, conflict, proposed or not_applied. A version conflict preserves the generated proposal and does not incur a second charge. You can apply a completed writing proposal through POST /jobs/{job_id}/apply with the current version. Check accepts up to 5000 words and 20 saved sources. GET /jobs/{job_id}/review returns progress and findings. PATCH /jobs/{job_id}/findings/{finding_id} accepts decision: apply or dismiss and a document version. Web similarity findings, changed evidence and suggestions that change meaning require manual review. Sources are never added automatically. Public web similarity does not establish originality across every private or published collection. Inspect the Check run status, checked_words and source coverage as well as the job status. A partial Check can contain valid results while some text, sources or web checks remain unavailable. Valid partial results use the fixed Check price. An entirely failed review releases its credits. Provider safety limits are separate from product allowances and can delay or limit a review. ## Credits and payments Credit purchases are currently unavailable. The package price is 100 credits for $10 USD. Operations that use credits require an existing balance. Credits are whole numbers, belong to the account and are shared across its API keys. Purchased credits never expire. There is no API subscription or automatic refill. Free and Pro product allowances are not used for API operations. GET /pricing returns the current fixed tariff. GET /balance returns balance, reserved and available. GET /ledger returns purchase, reserve, spend, release, refund and dispute movements. Basic document reads and edits, source records and citation formatting are free. Rate, data size and storage limits still apply. Credits are reserved atomically when a job is accepted. A valid result settles the charge. A valid empty source search is a completed operation. A job that fails or is cancelled before producing a result releases its reservation. A valid proposal remains chargeable when it cannot be applied. Retrying the same operation does not charge again. When credit purchases are available, API settings opens Stripe Checkout. Verified payment events add credits once. The return page cannot add credit. Refunds and disputes adjust the related purchase; spent credits can leave a negative balance that must be covered before another paid job starts. ## Files and storage Upload DOCX, TXT or PDF bytes to POST /files with Content-Type: application/octet-stream, X-File-Name (URL encoded), X-Content-SHA256 and Idempotency-Key. The SHA256 is the lowercase hexadecimal digest of the file. Import uploads are limited to 4 MB. Send the returned id as file_id to /imports. DOCX and TXT create drafts using the existing document parser and validation. PDF imports return source metadata and warnings for review. Exports accept docx, pdf, txt, bibtex or ris, a document_id, its version and max_credits. Bibliography formats require saved sources. Export uses one consistent document and source snapshot. The completed job returns file_id and a download_url. Download with the same authorization header. Files are private and the current workspace and document access are checked again. The existing account storage limit applies to uploads and generated files. DELETE /files/{file_id} removes a file and releases its storage. ## Sharing and comments Use /documents/{id}/sharing to read access or set a public link with enabled: true or false. POST /documents/{id}/invitations with email and role creates a private invitation URL. The API returns the URL for your application to deliver; it does not send an email automatically. DELETE the invitation ID to revoke it. PATCH /documents/{id}/members changes an existing document guest to editor, viewer or remove. Workspace membership is outside API v1. Read or add comments at /documents/{id}/comments. POST /documents/{id}/comments/{comment_id}/resolve resolves an allowed comment. Keep comment bodies below 10000 characters. ## Retries, errors and limits Every mutation requires Idempotency-Key. Reuse the same key and identical method, path, parameters and body after an uncertain result. Changed input returns 409. A key rotation preserves this history. Generate a new idempotency key for a new intended operation. Error response ```json { "error": { "code": "VERSION_CONFLICT", "message": "The document changed. Read its current version before applying changes.", "retryable": false, "request_id": "REQUEST_UUID" } } ``` | Status | Action | | --- | --- | | 400, 415, 422 | Correct the request or unsupported content. | | 401, 403, 404 | Verify the key, permissions and current access. | | 402 | Add API credits. | | 409 | Read current data and resolve the conflict. | | 413 | Reduce the document or file size. | | 429 | Wait for Retry-After seconds. | | 408, 502, 503 | Retry only when retryable is true, using the same idempotency key. | Each response carries X-Request-ID. Limits are 120 requests per key per minute and 300 per account. Each account can run two paid jobs and queue 20. Keep a bounded retry budget. The clients retry at most twice by default, preserve mutation keys and do not silently submit extra paid jobs. The shared editor permits up to 10000 documents per workspace, 1000 sources per document and 2000 editor mutations per key per day. Editor changes and export snapshots support up to 100000 text characters and 1 MB of editor JSON. Citation formatting and exports support up to 200 saved sources. Reading editor JSON is limited to 200 KB; use include_content: false and text pagination for larger reads. Buying credits does not raise these data limits. ## Events and webhooks GET /events returns document.created, document.updated, source.created, source.updated and job status events. Store the cursor only after your downstream action succeeds. Payloads contain identifiers, not document text. POST /webhooks accepts a public HTTPS url and an events array. Copy the returned secret at creation. Private addresses and redirects are blocked. GET /webhooks/{id}/deliveries shows attempts and response status. Failed deliveries retry with increasing delay, up to six attempts. Receivers must deduplicate X-Citation-Event-ID. Verify X-Citation-Signature against HMAC SHA256(secret, timestamp + "." + rawBody). The header uses v1= followed by the hexadecimal digest. Read timestamp from X-Citation-Timestamp, reject timestamps outside a short tolerance, compare signatures in constant time, then parse the body. Return a successful status only after recording the event. ## TypeScript and Python clients The repository includes packages/citation-api and packages/citation-python. Both use types generated from the same validation schemas and provide safe retries, pagination, file upload, downloads and job polling. Packages have not been published to a registry. The export examples below require an existing API credit balance. TypeScript workflow ```typescript const api = new Citation(process.env.CITATION_API_KEY, { baseUrl: "https://citation.co/api/v1" }); const draft = await api.createDocument({title: "Reading notes", text: "A draft."}); const job = await api.exportDocument({ document_id: draft.document_id, version: draft.version, format: "docx", max_credits: 1 }); const result = await api.wait(job.job_id); const bytes = await api.download(result.result.file_id); ``` Python workflow ```python api = Citation(api_key, "https://citation.co/api/v1") draft = api.create_document({"title": "Reading notes", "text": "A draft."}) job = api.export_document({ "document_id": draft["document_id"], "version": draft["version"], "format": "docx", "max_credits": 1 }) result = api.wait(job["job_id"]) content = api.download(result["result"]["file_id"]) ``` The examples/research files in each package demonstrate document creation, a saved source, citation insertion, AI revision, Check and export. Set CITATION_API_KEY and CITATION_API_BASE before running them. Keep returned job IDs after a client timeout so you can resume polling.