One header, JSON in, JSON out. The first two calls below use no credits, so a new key works at once. The same text for an AI agent: quickstart.md · OpenAPI JSON
1. Get a key
Create an account, open Settings, then API keys, press New API key and copy the saij_… token. It is shown once. Any account can create keys. Put it in your environment so it stays out of your files:
macOS / Linux
export SCIENCE_AI_API_KEY=saij_YOUR_KEY
Windows PowerShell
$env:SCIENCE_AI_API_KEY = "saij_YOUR_KEY"
2. Make a call
Prior-publication check
no credits
POST /api/prior-publication
Checks a title (and an abstract, if you send one) for an earlier publication or preprint across the scholarly indexes and our library. Returns: A status (for example preprint_found), a one-line message, the source and a link. Takes up to about 20 seconds. This endpoint also answers without a key, at lower per-IP limits; with a key the limits are per account.
curl
curl -sS -X POST https://scienceaijournal.com/api/prior-publication \
-H "Authorization: Bearer $SCIENCE_AI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Attention Is All You Need"}'
Python
import json, os, urllib.error, urllib.request
key = os.environ["SCIENCE_AI_API_KEY"]
req = urllib.request.Request(
"https://scienceaijournal.com/api/prior-publication",
data=json.dumps({"title":"Attention Is All You Need"}).encode(),
headers={
"Authorization": f"Bearer {key}",
"Content-Type": "application/json",
"User-Agent": "my-research-app/1.0", # the default Python-urllib agent is refused (403, error code 1010)
},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=120) as r:
print(r.status, json.dumps(json.load(r), indent=2)[:2000])
except urllib.error.HTTPError as e:
print(e.code, e.read().decode()[:2000]) # the body says why
JavaScript (Node 18+)
const res = await fetch("https://scienceaijournal.com/api/prior-publication", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SCIENCE_AI_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({"title":"Attention Is All You Need"}),
});
console.log(res.status, JSON.stringify(await res.json(), null, 2).slice(0, 2000));
Read first in the reply: status, message, source, link, confidence.
Literature search
no credits
POST /api/research-gaps
Searches the literature on a topic and returns the field overview and the closest papers. Returns: A field overview (paper counts, top venues, year range) and three paper lists: most cited, most recent and from our library. Takes about 5 to 10 seconds.
Read first in the reply: fieldOverview, mostCited, mostRecent, libraryPapers, queryUsed.
AI review, one reviewer agent
4 credits per call
POST /api/review/claude
Runs one specialist reviewer agent (here: methodology) on the manuscript text you send. Returns: Strict JSON: a score, a decision, strengths, concerns and questions for the authors. Takes about 20 to 60 seconds.
curl
curl -sS -X POST https://scienceaijournal.com/api/review/claude \
-H "Authorization: Bearer $SCIENCE_AI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"agentType":"methodology","prompt":"Review the methodology of this manuscript. Title: Soil microbial networks under grassland degradation. Methods: We sampled 36 plots along a degradation gradient, sequenced 16S rRNA amplicons and built co-occurrence networks with SparCC (threshold 0.6); network metrics were compared with a one-way ANOVA."}'
Python
import json, os, urllib.error, urllib.request
key = os.environ["SCIENCE_AI_API_KEY"]
req = urllib.request.Request(
"https://scienceaijournal.com/api/review/claude",
data=json.dumps({"agentType":"methodology","prompt":"Review the methodology of this manuscript. Title: Soil microbial networks under grassland degradation. Methods: We sampled 36 plots along a degradation gradient, sequenced 16S rRNA amplicons and built co-occurrence networks with SparCC (threshold 0.6); network metrics were compared with a one-way ANOVA."}).encode(),
headers={
"Authorization": f"Bearer {key}",
"Content-Type": "application/json",
"User-Agent": "my-research-app/1.0", # the default Python-urllib agent is refused (403, error code 1010)
},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=120) as r:
print(r.status, json.dumps(json.load(r), indent=2)[:2000])
except urllib.error.HTTPError as e:
print(e.code, e.read().decode()[:2000]) # the body says why
JavaScript (Node 18+)
const res = await fetch("https://scienceaijournal.com/api/review/claude", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SCIENCE_AI_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({"agentType":"methodology","prompt":"Review the methodology of this manuscript. Title: Soil microbial networks under grassland degradation. Methods: We sampled 36 plots along a degradation gradient, sequenced 16S rRNA amplicons and built co-occurrence networks with SparCC (threshold 0.6); network metrics were compared with a one-way ANOVA."}),
});
console.log(res.status, JSON.stringify(await res.json(), null, 2).slice(0, 2000));
Read first in the reply: score, verdict, summary, strengths, concerns.
3. Costs and limits
The prior-publication check and the literature search spend no credits. AI review costs 4 credits per agent call; a new account's 25 welcome credits cover 6 such calls. A refused call is never charged. Each key is limited to 60 calls a minute and 2000 a day. All endpoints, scopes and prices are on the API reference.
4. When a call fails
Status
What happened
What to do next
400
The body is not JSON or lacks a required field.
Send Content-Type: application/json and the required field (title, query or prompt). Nothing is charged.
401
No key, a mistyped key, a revoked key, or an endpoint that does not accept API keys yet.
Send "Authorization: Bearer saij_…" with a key from Settings, then API keys. The key starts with saij_ and is 27 characters long. Nothing is charged.
402
The account behind the key holds fewer credits than the call costs.
The reply names creditsAvailable and creditsNeeded. The prior-publication check and the literature search need no credits; credits for the paid calls are on the pricing page. Nothing is charged.
403
One of three. A JSON reply naming a scope: an organisation key that does not carry this endpoint's scope. The JSON reply "Automated access to this endpoint is not permitted." from the literature search: the key was not recognised (mistyped or revoked) and your client's User-Agent looks like a script, so the call was treated as an anonymous scraper. Or the plain text "error code: 1010": the network edge refused your HTTP client's default User-Agent (Python urllib, PycURL and libwww-perl are refused; curl, requests, httpx and fetch pass).
For "Automated access", check the key: copy it again from Settings, then API keys (it starts with saij_ and is 27 characters long). For 1010, send your own User-Agent header (any name, for example "my-research-app/1.0"). For a scope refusal, use a key whose scopes include the tool, or a personal key. Nothing is charged.
429
A rate limit: 60 calls a minute and 2000 a day per key; the prior-publication check allows 10 a minute and 60 an hour per account (5 and 20 per IP address without a key).
Wait the number of seconds in the Retry-After header, then send the same call again. Nothing is charged.
502
AI review only: the model call failed or the model declined.
That call's credits are refunded ("refunded": true in the reply). Send it again.
504
AI review only: the model call timed out.
That call's credits are refunded ("refunded": true in the reply). Send it again; a shorter text answers faster.
Using an AI assistant instead?
The MCP server gives Claude, Cursor, VS Code and Cline the same tools with the same key: one command or one click to install.