Verified claims, with the evidence attached
Every verdict this API returns carries the engine version that produced it and a fingerprint anyone can re-derive, and the error rate behind those verdicts is published rather than asserted. That is the whole pitch: you can check what we tell you without asking us.
Open, no key required
Reads over records that are already public. Nothing here needs an account and nothing here is metered. The ones marked browser send Access-Control-Allow-Origin and can be called from a page; the rest are server-side only, and saying which is which is the point of this page.
get/api/ledger.jsonbrowserThe published error rateThe Kaimen Ledger as data: what the committed corpus of judged mistakes holds, what the capture tier holds, finding-level precision (or the typed reason there is no rate yet), and the claims this evidence cannot currently support. Public, unauthenticated, cross-origin. Refusals are typed rather than implied: `capture.available: false` carries a reason and is never rendered as zero, and `precision.reported: false` means no rate was computed rather than a rate of zero.
curl -s "https://alpha1science.com/api/ledger.json"get/api/audit/verifyFetch a published record by idThe canonical record for a published review, including the fingerprint that makes it citable. Public: a grade nobody outside can fetch is a grade nobody outside can check.
curl -s "https://alpha1science.com/api/audit/verify?id=<id>"post/api/audit/verifyTamper-check a recordRe-derives the credential from the stored review and reports whether the supplied fingerprint matches. This is the endpoint behind "verify this grade yourself": the answer does not depend on trusting the caller, and `expected_fingerprint` comes back either way.
curl -s -X POST "https://alpha1science.com/api/audit/verify" \
-H "content-type: application/json" \
-d '{"record":{"record_id":"<record id>","fingerprint":"<the fingerprint you hold>"}}'get/api/rigor/summarybrowserLook up a review by DOIWhether a DOI has a published review, and its verdict, so another surface can show "this paper was reviewed" without re-implementing the verdict logic. Answers `{ found: false }` rather than 404 for an unreviewed DOI: absence of a review is a fact about our coverage, not an error in the request.
curl -s "https://alpha1science.com/api/rigor/summary?doi=<doi>"get/api/rigor/feedList published reviewsThe most recent published reviews as compact summaries (~1KB each). `include=result` returns the full analysis instead and is capped at a handful of rows, because one analysis is roughly 150KB. Uncached deliberately: unpublishing a record has to be instant, and a CDN entry a route handler created cannot be purged when it is.
curl -s "https://alpha1science.com/api/rigor/feed"Keyed, and metered when you are billed
Running the engine costs real compute, so these need a service key. Pass it as x-api-key, or as Authorization: Bearer. A key looks like kaimen_<prefix>_<secret>; we store its digest and the prefix, never the key, so it can be revoked but never recovered - if you lose one, ask for a new one rather than for that one. To get the first: write to editorial@alpha1science.com and say what you are integrating.
- QuotasPer key, in two windows: a per-minute one and a per-day one. Both are calendar windows in UTC, so a
429tells you WHICH is spent -rate_limitedclears within the minute,quota_exceededclears at 00:00 UTC - andRetry-Afteris the exact number of seconds rather than a worst case. - MeteringEvery call is recorded against its key when it is ADMITTED, with the route, the outcome, the latency and the engine version that served it. A run that fails after four minutes of model calls cost the same as one that succeeded, so it counts the same - a limit that refunded it would be one you could evade by failing.
- ScopesEach key carries the scopes it was issued with, and an endpoint names the one it needs. Asking for a scope you were not given is
insufficient_scope, which is a 403 and not a 401: your credential is fine and the answer is a wider key, not a re-read of your config.
post/api/v1/reviewRun a reviewRuns the engine over a manuscript and returns the verdict synchronously. Supply `text` or an `identifier` (DOI / PMCID / arXiv id / URL) to resolve. The response carries the engine version that produced it, the resolved review-agent version, and token / latency / cost telemetry, so a caller can compare versions or budget without a second request. Long-running: expect up to five minutes.
curl -s -X POST "https://alpha1science.com/api/v1/review" \
-H "x-api-key: $KAIMEN_API_KEY" \
-H "content-type: application/json" \
-d '{"identifier":"10.1234/example"}'get/api/v1/versionsList review-agent versionsThe version ids POST /api/v1/review will accept, so a caller can pin one rather than guess. Takes the same `review` scope as the endpoint it describes: a key that could list the versions but not use them would be a credential nobody wants.
curl -s "https://alpha1science.com/api/v1/versions" \
-H "x-api-key: $KAIMEN_API_KEY"What a refusal means, and what it does not
Every endpoint here distinguishes we looked and there is nothing from we could not look, because a consumer that cannot tell them apart will read our silence as a clean bill of health. Branch on the field, not on the status code - the statuses collide where it matters and the fields do not.
Every refusal from a keyed endpoint carries a code beside its error: service_disabled, unauthorized, key_revoked, insufficient_scope, rate_limited, quota_exceeded, at_capacity, invalid_body, internal_error, missing_input, unusable_text, not_found, full_text_unavailable, unknown_version. Codes are additive and are never re-used for a different meaning, so switch on them and keep a default branch. The error string is for a human reading a terminal and may be reworded; the code will not be.
found: falseNo review exists for that identifier. A fact about our coverage, not an error in your request - which is why it is a 200.available: falseA tier of the ledger could not be read. It carries the reason. It is never a count of zero, and you must not render it as one.reported: falseNo rate was computed - usually because too few findings have been judged to divide by. The counts come with it; the percentage does not.rate_limitedThe per-minute window for this key is spent.Retry-Afteris exact and small - back off and continue.quota_exceededThe same 429, and a different wait: the day’s allowance is spent and resets at 00:00 UTC. Stop retrying and ask for a larger quota.key_revokedThe key is real and was retired, or the account behind it is suspended. Notunauthorized: your config is correct and only a new key fixes it.insufficient_scopeThe key does not carry the scope this endpoint needs. Ask for one that does; the message names the scope.at_capacityThis instance is running as many reviews at once as it will. Transient, and not about your request - retry after the interval.service_disabledThe same 503, and the opposite instruction: this deployment has no service API enabled, so retrying will never help. Write to us.
Store the engine version with the verdict
Every response that carries a verdict carries the version of Kaimen Rigor that produced it. The same paper can hold different verdicts from two versions without either being wrong, so a verdict you have stored without its version is one neither of us can reproduce later. Keep the pair, and cite the pair.
A published record’s fingerprint is re-derivable from the record itself: post it back to /api/audit/verify from your server and compare. That check does not depend on trusting us, which is the property it exists to have. It sends no CORS header, so it is not callable from a page yet.