Verify citations programmatically.
Send one bibliographic reference, get back a structured verdict: verified, not_found or uncertain, with the authoritative metadata when a match exists. Call the REST API from your code, connect the remote MCP server to your LLM, or drop the no-code plugin into OJS.
Overview
Three ways to integrate citation verification.
CiteOrbit answers one question about a bibliographic reference: does a real published work match it? You send a single reference string, formatted or messy, and get back a verdict with the authoritative metadata (title, authors, year, DOI, venue, link) when a match exists.
REST API v1
One reference in, one synchronous JSON verdict out. For apps, editorial tools and pipelines.
MCP server
Connect Claude, ChatGPT desktop, IDEs or agent frameworks so the model verifies citations before presenting them.
OJS plugin
No-code reference and file checks inside Open Journal Systems, 3.3 to 3.5.
The headline use case is anti-hallucination: a chatbot or writing tool verifies citations before showing them to users, catching fabricated references such as fake papers or real-looking DOIs attached to nothing. CiteOrbit flags references that can't be matched to any real record in Crossref or OpenAlex. Note the limits: uncertain verdicts exist by design, and a sloppily formatted real reference can come back not_found.
Quickstart
From zero to a verified reference in three steps.
Request an API key
API keys are workspace-scoped and issued on request during the beta: email support@citeorbit.com to get access. Your key starts with cob_live_ and needs the references:write scope.
Set the base URL and auth header
All v1 requests go to https://app.citeorbit.com/api/v1 and carry your key as a bearer token. Every response is JSON with a stable envelope: { "code": "<machine_code>", ...fields }.
https://app.citeorbit.com/api/v1
Authorization: Bearer cob_live_xxxxxxxxxxxxxxxxVerify your first reference
POST one reference string and read the verdict:
curl -X POST https://app.citeorbit.com/api/v1/verify \
-H "Authorization: Bearer $CITEORBIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"reference": "Kahneman, D. (2011). Thinking, Fast and Slow. Farrar, Straus and Giroux."}'verified with the authoritative metadata, not_found, or uncertain.REST API v1
One endpoint: verify a single bibliographic reference, synchronously.
The /api/v1 path is a compatibility contract: response shapes will not change breakingly within v1, and breaking changes get /api/v2.
Verify a reference
references:writeExactly one reference per call (no batch in v1), 1 to 2000 characters. Formatted or messy text both work.
POST /api/v1/verify
Authorization: Bearer cob_live_...
Content-Type: application/json
{ "reference": "Vaswani, A., Shazeer, N., et al. (2017). Attention is all you need. Advances in Neural Information Processing Systems, 30." }{
"code": "ok",
"result": {
"rawText": "Vaswani, A., Shazeer, N., et al. (2017). Attention is all you need. ...",
"verdict": "verified",
"confidence": 0.9,
"matched": {
"title": "Attention Is All You Need",
"authors": ["Vaswani, A.", "Shazeer, N."],
"year": "2017",
"doi": "10.xxxx/xxxxx",
"venue": "Advances in Neural Information Processing Systems",
"url": "https://doi.org/10.xxxx/xxxxx"
},
"note": "Matched a record in Crossref. The metadata in \"matched\" is the authoritative version."
}
}Verdicts
| Verdict | Confidence | matched | What the caller should do |
|---|---|---|---|
verified | 0.9 | full metadata | A record in Crossref, OpenAlex, Semantic Scholar, or Google Scholar matches. Use matched as the authoritative citation data. |
not_found | 0.8 | null | No matching record: likely fabricated, or too obscure or new to verify. Do not present it as real without another source. |
uncertain | 0.6 | candidate metadata | Weak match: the work may exist but fields could not be confirmed. Verify manually. |
A fabricated reference comes back like this:
{
"code": "ok",
"result": {
"verdict": "not_found",
"confidence": 0.8,
"matched": null,
"note": "No matching record found in Crossref or OpenAlex — the reference may be fabricated, or too obscure/new to verify. Do not present it as a real work without another source."
}
}Errors
Failures return the envelope with a machine code and a human-readable message.
| HTTP | Code | When |
|---|---|---|
| 401 | invalid_api_key | Key missing, unknown, revoked, or expired. |
| 403 | insufficient_scope | Key lacks the references:write scope. |
| 422 | invalid_input | Missing or non-string reference, malformed JSON, empty, or over 2000 characters. The message says which. |
| 429 | rate_limited | Workspace burst limit hit. Retry after the Retry-After seconds (also in the retry_after field). |
| 429 | key_limit_reached | The key's daily, weekly, or monthly cap is exhausted. Retry-After provided. |
| 402 | insufficient_credits | Workspace out of credits. Only returned once metered pricing is enabled. |
| 500 | server_error | Verification pipeline failure. Safe to retry. |
Latency
Verification runs a full extraction and enrichment pipeline: a GROBID parse followed by Crossref, OpenAlex, Semantic Scholar and Google Scholar lookups. This is not an instant-autocomplete API.
verified(clean match): roughly 4 to 7 seconds.not_found: roughly 17 to 20 seconds. This is the slow path, every fallback source is exhausted before giving up.- Design your client with a 60 second timeout and a visible "checking…" state.
Rate limits and pricing
- 60 requests per minute per workspace (burst limit).
- Per-key usage caps: daily, weekly, or monthly, set on the key.
- Free during beta, fair-use limits apply. Published pricing is on the roadmap.
MCP server
Give your LLM the ability to verify citations before presenting them.
CiteOrbit is a remote MCP server: any MCP-capable client (Claude, ChatGPT desktop, IDEs, agent frameworks) can connect and let its model check that a cited work actually exists.
- Endpoint:
https://app.citeorbit.com/api/mcp - Transport: Streamable HTTP (the current MCP standard). Legacy SSE is intentionally not supported.
- Auth: the same API key, sent as
Authorization: Bearer cob_live_...
The verify_reference tool
The server exposes exactly one tool. Input: reference (string, 10 to 2000 characters), one full bibliographic reference, formatted or messy. Output: the same JSON verdict object as the REST endpoint. Parity is a design guarantee, the MCP tool never exceeds what the REST API can do.
Connect a client
Claude Code:
claude mcp add --transport http citeorbit https://app.citeorbit.com/api/mcp \
--header "Authorization: Bearer cob_live_..."Generic MCP client config:
{
"mcpServers": {
"citeorbit": {
"type": "http",
"url": "https://app.citeorbit.com/api/mcp",
"headers": { "Authorization": "Bearer cob_live_..." }
}
}
}Raw JSON-RPC sanity check:
curl -X POST https://app.citeorbit.com/api/mcp \
-H "Authorization: Bearer $CITEORBIT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'What's coming
On the roadmap for the public API.
Batch bibliography verification
Verify a whole reference list in one call. Today: call /verify once per reference (MCP clients can parallelize tool calls).
Chrome extension and MS Word add-in
Both will consume this same v1 API.
Async document checks
Whole-manuscript check endpoints under /api/v1/checks.
Published pricing
Free during beta, fair-use limits apply, until pricing is finalized.
OJS integration
For journals: no-code checks inside your editorial workflow.
Running Open Journal Systems? Install the CiteOrbit plugin and editors get one-click Validate with CiteOrbit actions on the References tab and on manuscript files: the report opens straight from OJS. The integration uses its own queued, batch-based API under /api/ojs/*, separate from API v1.
OJS 3.3
stable-3_3_0OJS 3.4
stable-3_4_0OJS 3.5
stable-3_5_0Install the plugin
Download the release for your OJS version and upload it under Settings, then Website, then Plugins, then Upload a new plugin.
Enable CiteOrbit Reference Checking, open its settings, and paste your cob_live_ API key.
Open any submission, then Validate with CiteOrbit on the References tab or a manuscript file.
OJS API: scopes
Authenticate every request with Authorization: Bearer <key>. Keys are workspace-scoped and carry one or both permissions:
| Scope | Grants |
|---|---|
references:write | Verify a reference (POST /api/v1/verify) and submit OJS reference-list checks (/api/ojs/reference-checks) |
files:write | Submit OJS manuscript file checks (/api/ojs/file-checks). Not used by API v1. |
Check references
references:writeSend up to 100 raw citation strings (for example, the references a manuscript system already has on file). The check runs asynchronously and returns a report_id you can poll or link to. Checks spend credits from the workspace the API key belongs to.
| Field | Type | Description | |
|---|---|---|---|
references | array | required | 1 to 100 items, each { position, raw, citation_id? } |
article_title | string | optional | Title of the paper being checked |
citation_style | string | optional | e.g. apa-7, vancouver, ieee (defaults to apa-7) |
journal_abbreviation | string | optional | Shown on the report |
submission_id | number | optional | Your system's submission id, echoed back |
# verify three references
curl -X POST https://app.citeorbit.com/api/ojs/reference-checks \
-H "Authorization: Bearer cob_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"article_title": "On the verification of citations",
"citation_style": "apa-7",
"references": [
{ "position": 1, "raw": "Smith, J. (2021). A study of things. Journal of Things, 4(2), 11-20." },
{ "position": 2, "raw": "Doe, A. (2019). Another paper. Press." }
]
}'{
"code": "queued",
"report_id": "chk_a1b2c3",
"message": "References sent to CiteOrbit."
}/check-references/by-check/<report_id> on https://app.citeorbit.com to view the report.Check a file
files:writeMultipart upload. Accepts DOCX, DOC, or ODT (PDF is not supported for file checks).
curl -X POST https://app.citeorbit.com/api/ojs/file-checks \
-H "Authorization: Bearer cob_live_xxxxxxxxxxxxxxxx" \
-F "file=@manuscript.docx" \
-F "citation_style=apa-7" \
-F "journal_abbreviation=J. Things"Get a check's result
Poll until status is completed.
{
"status": "completed",
"score": 92,
"summary": {
"total": 24,
"verified": 22,
"issues": 2
}
}OJS API: limits
- Per-key cap: each key has a configurable daily, weekly, or monthly check limit.
- Rate limit: bursts are throttled per workspace; throttled calls return
rate_limitedwith aRetry-Afterheader. - Expiry: keys can be given an expiry date and revoked anytime.
- Max 100 references per reference check.
OJS API: error codes
These apply to /api/ojs/* endpoints only (API v1 errors are documented above).
| Code | Meaning |
|---|---|
invalid_api_key | Key missing, malformed, or revoked. |
insufficient_scope | Key lacks the scope for this endpoint. |
insufficient_credits | Workspace is out of credits (response includes topup_url). |
no_references | No references in the request body. |
too_many_references | More than 100 references in one check. |
unsupported_file / invalid_file_content | File type or contents not a supported document. |
file_too_large | Uploaded file exceeds the size limit. |
rate_limited | Too many requests, retry after the Retry-After seconds. |
key_limit_reached | Key hit its daily / weekly / monthly cap. |
concurrent_limit | Another check is already running for this workspace. |
server_error | CiteOrbit could not process the request. |
Support
We are happy to help you integrate.
To request API access during the beta, or for any question about the API, MCP server, or OJS plugin, email support@citeorbit.com or open an issue on the plugin's GitHub repository. For workspace, billing and credit questions, see your account dashboard.