Indexer API
The Cabdell indexer reads the contract’s events from the Algorand blockchain, fetches and checks the content from IPFS, and serves what it knows as a read-only JSON API. The web app is built on it, and anyone can use it. It is a cache: everything it returns can be rebuilt from the chain and IPFS (see Verify without trusting cabdell.press and Run an indexer).
The routes below come from projects/indexer/src/api.ts, the code that answers them. Terms such as CID, round and
address are explained in the Glossary.
Base URLs
Section titled “Base URLs”One indexer runs per network, each with its own database and its own base URL, the indexerApi of the network in
spec/networks.json. Data of different networks is never mixed.
| Network | Base URL |
|---|---|
| TestNet | https://api.cabdell.press/testnet |
| MainNet | not open yet; its base URL will be the indexerApi of the mainnet entry once it opens |
| LocalNet (your machine) | http://localhost:3000 |
curl https://api.cabdell.press/testnet/statusConventions
Section titled “Conventions”-
Methods:
GETandHEAD.OPTIONSanswers 204 for browsers; any other method answers 405. -
Responses are JSON (
application/json; charset=utf-8), withAccess-Control-Allow-Origin: *. Public answers that change little may be cached:/fields,/journals,/withheldand/citeanswerCache-Control: public, max-age=30,/status10 seconds, the feed, article pages (with theircomments,reviews,citations,jury,settleable) and/search/*15 seconds, each with a weakETag(If-None-Matchanswers 304). Everything per address or per viewer,/names,/activity,/notifications,/healthand every error answerCache-Control: no-store. -
Envelope. Every response, errors included, starts with
networkandappId. Check them: they tell you which network and which application the data belongs to.{ "network": "testnet", "appId": 773893388, "...": "the route's own fields" } -
Addresses are 58-character Algorand addresses. CIDs are base32 text (
bafybei...for articles,bafkrei...for reviews and comments). Times are Unix seconds (block time). -
Field ids are numbers (
771); some lists addhex(0x0303). Parameters calledfieldaccept either form. -
typeandstatusaccept names or numbers. Types:article,notes,amendment,dataset,replication. Statuses:preprint,under_review,final,disputed,retracted(status 3,final, is shown in the app as “closed version”). -
Boolean parameters accept
1,true,yes,onand0,false,no,off. -
List parameters of the search routes may be repeated or comma-separated:
field=0x0303&field=0x0501orfield=0x0303,0x0501.
Errors and status codes
Section titled “Errors and status codes”| Code | When | Body |
|---|---|---|
| 200 | success | the route’s fields |
| 400 | a parameter is invalid (the message names it); an ORCID iD with a wrong check character; a wildcard or regular expression that takes too long | {"network", "appId", "error"} |
| 404 | unknown route; article or list not found | same |
| 405 | a method other than GET, HEAD or OPTIONS | same |
| 500 | an unexpected failure ("internal error"; the indexer logs it) |
same |
| 503 | /health when ingestion has stalled; searches with wildcards or regular expressions when their shared time budget is used up |
same |
curl -i "https://api.cabdell.press/testnet/articles?sort=top"# HTTP/1.1 400 ...# {"network":"testnet","appId":773893388,"error":"sort must be score or new"}Limits and pagination
Section titled “Limits and pagination”The indexer applies no per-client rate limit. Lists are paged with limit and offset, or with a cursor where noted:
| Route | Paging | Default | Range |
|---|---|---|---|
/articles |
limit, offset |
20, 0 | limit 1 to 100, offset up to 1 000 000 |
/search/articles, /search/posts, /search/people |
limit, offset |
20, 0 | limit 1 to 100, offset up to 100 000 |
/search/suggest |
limit |
5 | 1 to 10 |
/articles/:id/citations, /users/:address/citations, /users/:address/lists/:id |
limit, offset |
50, 0 | limit 1 to 100 |
/users/:address/following, /followers |
limit, offset |
100, 0 | limit 1 to 1 000 |
/users/:address/notifications |
limit |
50 | 1 to 100 |
/users/:address/feed, /activity |
limit, before (Unix seconds: items older than it) |
50 | limit 1 to 100 |
/notifications |
after (a notification id), limit |
0, 200 | limit 1 to 500 |
/cite |
ids |
1 to 1 000 ids |
Search text (q) is cut to 500 characters. Wildcards and regular expressions run on the indexer’s only thread, so they
have their own limits: at most 5 per query and 200 characters each; each search may spend 2 seconds on them (then 400,
“make it more specific”), and all searches together 20 seconds per minute (then 503, “busy”).
Health and status
Section titled “Health and status”GET /health
Section titled “GET /health”What an uptime monitor reads. 200 while ingestion works:
{ "network": "testnet", "appId": 773893388, "ok": true, "last_ingest_seconds_ago": 2 }503 when no ingestion poll has succeeded for ARIADNE_STALL_SECONDS (300 by default): the Algorand node is
unreachable, a round contradicts the protocol rules, or events are missing (see
Ingestion and contract v4). The error says how long and why.
GET /status
Section titled “GET /status”The state of the database:
| Field | Meaning |
|---|---|
genesis_id, genesis_hash |
the chain the database was built from |
schema_version |
the database schema (18) |
watermark |
the last round ingested |
event_seq |
the event_seq of the last contract event ingested (D-163) |
governance |
the current governance address, from the events |
pending_governance |
the address proposed by governance that has not accepted yet, or null (D-163) |
counts |
rows: events, articles, reviews, comments, fields, content, pinned, pin_failures, identities, orcid_verified, dois, dois_verified, follows, search_articles, search_posts, post_texts, sealed_articles, qualified_reviews, coauthor_checks |
Articles
Section titled “Articles”GET /articles
Section titled “GET /articles”The ranked feed.
| Parameter | Meaning |
|---|---|
field |
articles whose primary or secondary field is this one |
type |
name or number |
status |
name or number; without it, retracted articles are left out |
sort |
score (default) or new |
limit, offset |
paging |
Returns { total, articles: [...] }. Each article in a list has these fields:
| Field | Meaning |
|---|---|
article_id, asa_id |
the article number and its Algorand asset |
author |
the submitting wallet |
primary_field, secondary_field |
field ids (0 = none) |
article_type, type |
the type as a number and as a name |
parent_article |
the amended article, or 0 |
amendment_by_author |
for an amendment, whether its submitter is an author of the amended article (false: a third-party note, not the article’s own amendment); null for other types (D-162) |
status, status_name, status_before_dispute |
the status as a number and as a name |
version, cid, prev_cid |
the current version and its CID; prev_cid is null for version 1 |
created_at, updated_at |
Unix seconds |
vote_total, vote_count |
the sum of the (damped) vote weights and the number of votes |
author_count, invited_count |
accepted authors; declared co-authors |
claimed |
the author claimed the asset |
dispute_round, round_flag_weight |
the flag round and its weight so far |
flag_threshold |
the weight of flags that disputes the article: always 30 (D-163) |
flag_bond |
the bond a flag on the article deposits now, in microAlgo: 1 000 000, doubled per clearance by governance while the last one is less than 365 days old (at most 16 000 000) |
round_started_at |
the time of the first flag of the current round; null while the round has no flag |
round_lapses_at |
round_started_at + 30 days while the round has flags and the article is not disputed: the round lapses then; null otherwise |
disputed_at |
when the current dispute started; null unless the article is disputed now |
retract_after |
disputed_at + 14 days: governance may retract from then; null unless disputed |
dispute_expires_at |
disputed_at + 60 days: anyone may end the dispute from then; null unless disputed |
clearances, cleared_at |
how many disputes about the article governance cleared (counted up to 4; an expiry does not count), and when the last one was (null when none) |
score |
the ranking score, vote_total / (age_days + 2) ^ 0.8, computed at query time |
seal |
sealed, in_review, changes_requested, suspended or none (see below) |
warnings |
disputed, retracted, and content:<status> when the content is not valid |
content |
validation_status, title, abstract, keywords |
curl "https://api.cabdell.press/testnet/articles?field=0x0303&sort=new&limit=5"GET /articles/:id
Section titled “GET /articles/:id”One article: { article: {...} } with every list field above, plus:
| Field | Content |
|---|---|
authors[] |
submitter first, then co-authors by address: address, role (submitter or coauthor), inert (true for an address nobody can sign for, the zero address or the application’s: never a person; D-162), accepted, invited_at, accepted_at, claimed_total, entitled, claimable (null until the co-author confirms), orcid (only a verified iD: id, given_names, family_name, name) |
dois[] |
version (0 = every version), doi, url, status (verified, unlinked, missing, invalid, declared or pending), declared_by, declared_by_submitter, declared_at, checked_at, verified_at, conflicts[] (doi, declared_by, declared_at: other authors’ declarations of another DOI for the version). The DOI shown is the submitter’s, else the latest co-author’s (D-162); since contract v4 only the submitter can declare one (D-163) |
duplicate_of[] |
its CIDs or DOIs that another article used first, which therefore cite that article, not this one (D-162): kind (cid or doi), version, cid, doi, article_id (whose it is); empty when none |
citations |
cited_by, cites, and thread (the article’s Thread Score: percentile, external_citations, cohort, cohort_size; null for amendments and retracted articles) |
seal_detail |
the Peer-reviewed seal in detail (see below) |
journals[] |
the overlay journals that selected it (D-139): owner, list_id, name, added_at, added_by, volume, volume_title, accepted and accepted_at (the submitter accepted the selection; only then is it the article’s journal elsewhere), declined (D-162) |
cites_retracted[] |
the Cabdell articles it cites that were retracted (D-140): article_id, title, retracted_at |
versions[] |
version, cid, prev_cid, ts |
reviews[] |
article_id, review_seq, reviewer, cid, recommendation (1 to 4), created_at, useful_total |
comments[] |
the comment tree: article_id, comment_seq, author, cid, reply_to, root_seq, depth, created_at, vote_total, reply_count, resolved, resolved_at, mentions[], replies[] |
votes[] |
the article’s votes, oldest first (D-163): voter, weight (the damped weight that counted), raw_weight (the voter’s weight before damping), n (the damping divisor: weight = raw_weight ÷ n, rounded down), ts |
flags |
threshold (30, as flag_threshold), bond (the bond in force now, as flag_bond), dispute_round, round_flag_weight, current_round[] (flagger, reason, weight, ts), total_flags |
disputes[] |
dispute_round, outcome (the contract’s code: 1 cleared, 2 retracted, 3 expired), new_status, ts, resolved_by, reasons_cid |
content_record |
cid, available, validation_status, fetched_at, last_checked_at, size_bytes, notice |
curl https://api.cabdell.press/testnet/articles/1GET /articles/:id/comments?root=
Section titled “GET /articles/:id/comments?root=”One thread: the comment root (required) and every reply under it, ordered by depth, then by creation time. Returns
{ article_id, root, comments: [...] }.
GET /articles/:id/citations
Section titled “GET /articles/:id/citations”| Parameter | Meaning |
|---|---|
direction |
cited_by (default): the Cabdell articles that cite it, newest first, retracted ones left out; cites: those it cites |
limit, offset |
paging |
Returns { article_id, direction, total, articles }; each article has the list fields plus citation_kind: amends,
note (an “amendment” by someone who is not an author of the article, D-162), link, doi or cid.
GET /articles/:id/viewer/:address
Section titled “GET /articles/:id/viewer/:address”What one address has done on one article, so that an interface offers only the actions still possible: voted_article,
review_votes[] and comment_votes[] (the numbers voted), reviewed, flagged and reputation (in the article’s
primary field). D-163:
| Field | Meaning |
|---|---|
flagged |
whether the address has flagged in the round a flag would count in now: false once the current round has lapsed, since the next flag opens a new round |
reputation_since |
when the address’s reputation record in the article’s primary field was created (Unix seconds); null without one |
can_flag_from |
from when that record is old enough to flag (30 days after reputation_since); null without a record. The 10 reputation are needed as well |
GET /articles/:id/seal-check/:address
Section titled “GET /articles/:id/seal-check/:address”Would a review by this address count toward the article’s seal if it were written now (D-137)? The same checks as
the seal, except the text, which is not written yet: favourable and unfavourable give, for each kind of
recommendation, {reason, detail, via} (reason null: it counts; reciprocity concerns favourable reviews only);
min_words is the length the text needs; openalex_checked says whether every reviewer-author pair has been looked up
on OpenAlex (when false, that check happens after the review is published); rule is the rule version. 404 for an
article that does not exist.
curl -s https://api.cabdell.press/testnet/articles/1/seal-check/ADDRESSDisputes, flags and bonds
Section titled “Disputes, flags and bonds”The routes behind an article’s dispute page and the settlement of bonds (D-151, D-158, D-163). The rules are in
Flags, disputes and governance. A round’s outcome is one of:
| Outcome | Meaning |
|---|---|
pending |
the current round, while it can still become a dispute, or is one |
lapsed |
the round ended without becoming a dispute; the current round shows lapsed once 30 days have passed since its first flag without a dispute |
cleared |
governance cleared the dispute |
retracted |
the article was retracted during the dispute, by governance or by its submitter |
expired |
nobody resolved the dispute within 60 days and someone ended it (not a clearance) |
GET /articles/:id/jury
Section titled “GET /articles/:id/jury”{ article_id, cases: [...], flags: { threshold, bond, rounds: [...] } }: the jury cases of the article’s disputes,
newest first, and every round of flags, oldest first. flags.threshold is 30 and flags.bond the bond a flag
deposits now (1 000 000 microAlgo, doubled per recent clearance by governance).
Each round of flags.rounds[]:
| Field | Meaning |
|---|---|
round, dispute_round |
the round’s number |
outcome |
see the table above |
weight, total_weight |
the total weight of the round’s flags |
disputed |
whether the round became a dispute |
started_at |
the time of the round’s first flag |
disputed_at |
when the round became a dispute; null if it did not |
resolved_at |
when the dispute ended; null while it has not |
resolved_by |
who ended it: governance, the submitter (own retraction) or whoever expired it; null while it has not |
reasons_cid |
the CID (CIDv1 text) of governance’s published reasons; null for an expiry, an own retraction, or while unresolved |
flags[] |
each flag: dispute_round, flagger, reason (1 to 4), weight, ts, note (what the flagger wrote, or null), hidden_note (true when the flag has a note that is withheld because the round lapsed; note is then null, and the flag still counted), bond (the bond it deposited), created_at, settled, bond_to (who received the bond or part of it; null until settled), retained (microAlgo the application kept; null until settled), settled_at, settleable (the round is over and the flag is not settled yet: anyone may settle it now) |
Each case of cases[] gives the jury: round, attempt, status, scope, the moments opened_at, drawn_at,
replace_at (also replace_silent_from) and deadline (also answers_until), the draw (seed_round, seed, the
frozen pool eligible with its SHA-256 pool_hash, and pool, the drawn order), seats_total, quorum, age_days,
seats[] (each with answer_by and state), the round’s flags, answers and tally (empty and null while the
jury sits, answers_hidden true), outcome, fallback, decided_at, resolution, resolved_at and overdue.
Since D-163 a case also gives resolved_by and reasons_cid (null until the dispute is resolved) and retract_after,
from when governance may retract (14 days after the dispute started). A verdict to retract is overdue only 7 days
after the later of the verdict and retract_after. When resolution compares the end of the dispute with the jury’s
outcome, an expiry counts as cleared and the submitter’s own retraction as retracted. How juries work is explained in
Juries for disputes.
GET /articles/:id/settleable
Section titled “GET /articles/:id/settleable”What anyone may settle now on the article: { article_id, settleable: [...] }, each with round, flagger,
outcome, bond, bond_to_if_settled (where the bond, or half of it, would go: the flagger after a retraction or a
lapse, the submitter after a clearance, the zero address after an expiry), paid_if_settled (what would go to that
address) and retained_if_settled (what the application would keep). An interface uses it to offer the settlement of
bonds that flaggers lost, which the submitter, or anyone, may send.
curl https://api.cabdell.press/testnet/articles/1/settleableGET /users/:address/flags
Section titled “GET /users/:address/flags”Every flag of the address, newest first: { flags: [...] }, each with article_id, title, round, weight,
reason, bond, created_at, outcome, settled, bond_to, retained, settled_at and settleable. An interface
uses it so that a flagger can reclaim the bonds that come back to them.
GET /users/:address/jury
Section titled “GET /users/:address/jury”The seats the address holds in juries that sit now, soonest first: { address, seats: [...] }, each with the article,
the round and attempt, answer_by, deadline and the article’s title.
The Peer-reviewed seal in the API
Section titled “The Peer-reviewed seal in the API”The seal is computed by the indexer from the chain, IPFS, ORCID and OpenAlex (D-131). See The Peer-reviewed seal for the rules.
| Where | Field | Values |
|---|---|---|
| every article in a list | seal |
sealed (at least 2 favourable reviews that count, more than the unfavourable ones), changes_requested (at least 2 unfavourable, at least as many as the favourable), in_review (some review counts), suspended (sealed but disputed), none (no review counts, or retracted) |
GET /articles/:id |
seal_detail |
null when the article has no review; otherwise state, state (also awaiting_orcid: enough reviews, an author without a verified ORCID iD), rule (the rule version, 6), required (2), favourable, unfavourable, sealed_since, reviewed_version (the version current at the latest review that counts), authors_without_orcid[], reviews[] |
seal_detail.reviews[] |
review_seq, reviewer, recommendation, counted, reason (the first rule the review fails: author, orcid, expertise, expertise-authors, expertise-young, expertise-granters, conflict-orcid, conflict-coauthor, conflict-openalex, conflict-institution, conflict-support, text-unread, short, reciprocal, duplicate-orcid; null when it counts), detail (for expertise-* the reputation that counts or the number of people it came from; for conflict-support the author; for duplicate-orcid the review that counted first), via (reputation or openalex: how the reviewer showed expertise) |
|
GET /users/:address |
seals |
sealed_articles, qualified_reviews |
GET /users/:address, each of reviews[] |
counted, not_counted_reason |
whether that review counts toward a seal, and why not; counted is null while it has not been judged |
GET /search/articles |
sealed filter, sealed facet |
articles that hold the seal |
People
Section titled “People”GET /users/:address
Section titled “GET /users/:address”{ user: {...} }, the profile derived from the chain:
| Field | Content |
|---|---|
identity.orcid |
null, or id, status, declared_at, checked_at, verified_at, retrying, and only while verified: given_names, family_name, name, public (what the record shows to everyone: websites, countries, affiliations; never an e-mail address), citations (OpenAlex counts). D-164: id is null until the iD is verified (anyone can declare anyone’s iD) |
follows |
followers, following |
list_count |
public lists |
objections |
D-164: thread, jury, reputation_display (booleans): what the address objects to (see Privacy and permanence); hidden_by_objection is true when one of them hides a figure |
ariadne_citations |
received, self, cited_articles, thread (score, articles; the person’s Thread Score). With an objection to thread: thread is null and hidden_by_objection true |
seals |
sealed_articles, qualified_reviews |
publications[] |
as submitter and as co-author: article_id, role, accepted, status, status_name, fields, article_type, title, validation_status, cid, published_at, vote_total, seal, entitled, claimed_total, claimable, claimable_today (what a claim would grant now, under the daily cap), cap_left_today (what the cap of its primary field leaves today), claim_allowed (claimable_today above 0) |
claimable_total |
reputation the address can claim today, over all its articles, within the daily cap of each field (D-162) |
claimable_total_all |
the same whatever the daily cap |
reviews[], comments[] |
with the article’s title; reviews also carry counted and not_counted_reason |
reputation[] |
per field: field_id, hex, name, rep, updated_at, cap_day, cap_today, cap_left_today, by_source (D-162: article_votes, useful_reviews, comment_votes, resolutions, the reputation each source gave) |
reputation_by_source |
the same sums over every field |
| (D-164) | with an objection to reputation_display: reputation and reputation_by_source are null, reputation_hidden_by_objection is true, and the timeline leaves out the reputation changes |
timeline[] |
the address’s own events, newest first, at most 200; its votes (voted_article, voted_review, voted_comment) carry amount, the damped weight that counted, with raw_weight and n; its flagged entries carry hidden_note true when their note is withheld because the round lapsed (D-163) |
withheld |
D-164: only when this service withholds the person’s data: the statement of reasons (see What this service withholds); identity is then {orcid: null} |
curl https://api.cabdell.press/testnet/users/YOUR_ADDRESSGET /users/:address/notifications
Section titled “GET /users/:address/notifications”| Parameter | Meaning |
|---|---|
unread |
1 or true: unread only |
limit |
1 to 100, default 50 |
Returns { address, unread, notifications: [...] }, newest first; each has id, kind, article_id,
comment_seq, actor, ts, read and the article’s title. Kinds: reply, mention, comment_on_my_article,
review_on_my_article, comment_resolved, coauthor_invite, followed and the others listed in the indexer’s
README. The API is read-only: the web app keeps read marks in the browser. A notification keeps its id for good,
even when the indexer rebuilds its tables (D-162).
Contract v4 (D-163) adds these kinds and fields:
| Kind | To | actor |
data |
|---|---|---|---|
flag_settled |
the flagger, and the bond’s recipient (nobody else when the whole bond was kept) | '' |
round, outcome, bond (what went to bond_to), bond_to, retained, flagger |
dispute_expired |
the confirmed authors and the round’s flaggers | whoever ended the dispute | outcome (expired), to (the status restored), resolved_by, reasons_cid (null) |
governance_proposed |
the current and the proposed governance | '' |
proposed, governance |
dispute_resolved (existing) |
as before | governance, or the submitter for their own retraction | gains reasons_cid and resolved_by |
D-162 (limits): a follow, a mention or a journal’s note from an address with no reputation and no verified ORCID iD,
and anything beyond 20 notifications from one sender to one recipient in a day, is folded into one digest entry per
day, whose data has day, count, kinds, senders, new_accounts and over_limit. folded=1 lists the folded
notifications themselves.
D-164 adds the kind withheld: to the people concerned by something this service withholds (an article’s confirmed
authors, a review’s or comment’s author, a list’s or journal’s owner, a flagger, a juror, the person), once per case,
unless the case says not to. actor is ''; it links like the record (article_id, review_seq, comment_seq,
round, journal); data has kind (what was withheld), id (the case), ground and redress (how to contest it).
GET /names?address=
Section titled “GET /names?address=”The names to show for up to 50 addresses (repeated or comma-separated): { names: {<address>: <name or null>}, hidden: [...] }. A name is the verified ORCID record’s (its published name, else its given and family names); null without a
verified iD. D-164: hidden lists the addresses whose names and pictures this service no longer shows (their name is
null, and the web app shows neither their NFD name nor their avatar).
GET /users/:address/following and /followers
Section titled “GET /users/:address/following and /followers”Active on-chain follows, newest first: { address, total, following: [...] } or { address, total, followers: [...] }.
GET /users/:address/feed
Section titled “GET /users/:address/feed”Publications, confirmed co-authorships, reviews and comments of everyone the address follows, newest first:
{ address, activity: [...] }, each item with kind (published, coauthored, reviewed, commented), actor,
article_id, seq, reply_to, ts, title. Page backwards with before.
GET /activity?address=
Section titled “GET /activity?address=”The same activity for up to 50 addresses given as repeated parameters (address=A&address=B): { activity: [...] }.
GET /users/:address/citations
Section titled “GET /users/:address/citations”The citations the address’s articles received from Cabdell articles, newest citing article first:
{ address, total, citations: [...] }, each with citing (article_id, title, author, created_at, type),
cited (article_id, title), kind and self (the address also wrote the citing article).
GET /orcid/:id
Section titled “GET /orcid/:id”The addresses whose declaration of this ORCID iD is verified: { orcid, addresses: [...] }. 400 when the check
character is wrong.
Lists and bibliographies
Section titled “Lists and bibliographies”GET /users/:address/lists
Section titled “GET /users/:address/lists”Public lists, newest change first: { address, lists: [...] }, each with owner (D-164), list_id, name, about,
created_at, updated_at, count and preview (the last three articles added). With article=<id>, each list also says whether it
holds that article (contains).
GET /users/:address/lists/:id
Section titled “GET /users/:address/lists/:id”One public list (list: owner, list_id, name, about, created_at, updated_at, count, journal, and for a
journal policy and editors[]: address, accepted, invited_at, accepted_at) and its articles, last added first,
each with the list fields, added_at, added_by (who selected it) and volume. A journal’s list also gives
volume (the open one) and volumes[] (open one first: volume, title, opened_at, closed_at, count, editors,
the board kept when it closed); volume=<n> returns that volume’s articles only (D-141). 404 when the address has no
such list.
GET /journals
Section titled “GET /journals”Every overlay journal (D-139), the most articles first: { journals: [...] } with owner, list_id, name, about,
policy, created_at, updated_at, count, editors (accepted editors, the founder included) and volumes.
GET /users/:address/journals
Section titled “GET /users/:address/journals”The journals the address founded, edits or is invited to: { address, journals: [...] } with owner, list_id,
name and role (founder, editor or invited); with article=<id>, contains says whether each holds it.
Journal notes use the list prefix (ariadne/lists/<appId>:) with these operations, besides those of lists: the
founder’s {"op":"journal","list":"<id>","policy":"…"} (or "off":true), {"op":"invite"|"dismiss","list":"<id>", "editors":[…]} (at most 10 per operation, 30 editors in all); an invited editor’s {"op":"editor","journal":"<OWNER>/<id>", "accept":true|false}; the founder’s or an accepted editor’s {"op":"select"|"unselect","journal":"<OWNER>/<id>", "articles":[…]}; the founder’s {"op":"volume","list":"<id>","title":"…"} opens the next volume (closing the open one,
which must not be empty) and {"op":"volume","list":"<id>","title":"…","current":true} renames the open one (D-141).
The same notes carry an address’s objection to profiling (D-164, GDPR art. 21), for itself only:
{"op":"objection","to":["thread","jury","reputation_display"],"on":true} (one to three of these items; "on":false
withdraws the objection; for each item the latest note stands). thread hides the address’s Thread Score,
reputation_display its reputation figures (profile and people search), and jury keeps the person (every address of
their verified iD) out of every jury pool and draw from then on. A note with anything else changes nothing. The note is
public, like every note.
GET /cite
Section titled “GET /cite”What a bibliography needs of each article: ?ids=1,2,3 (1 to 1 000 ids) or ?owner=<address>&list=<id> (a whole
public list). Returns { articles: [...] } in the order asked, unknown ids left out; each with article_id, title,
type, status_name, version, published, cid, authors[] (address, orcid) and dois[] (version, doi,
status).
Search
Section titled “Search”Full-text search over articles, reviews and comments, and people (D-120, D-121). See Search for the query syntax as readers use it.
Query syntax: words (all required), "a phrase", -word, OR, prefix*, the parts title:, abstract:, keyword:,
body:, author: (a name or an address) and field:, and exact lookups doi: (or a bare DOI), cid: and #12.
Wildcards inside a word (wom?n, *ology) and regular expressions between slashes (/memor(y|ies)/, title:/^sleep/,
-/x/) are tested on the texts without accents, case ignored. Highlighted words come between the characters U+0002 and
U+0003, never as HTML.
GET /search/articles
Section titled “GET /search/articles”| Parameter | Meaning |
|---|---|
q |
the query |
field |
fields (primary or secondary, unless primary_only=true) |
primary_only |
match field against the primary field only |
area |
areas (the high byte of a field id, 1 to 6), matched against the primary or secondary field |
type |
types |
status |
statuses; retracted articles are left out unless chosen; all for every status |
author |
an address (submitter or accepted co-author) |
submitter_only |
author must be the submitter |
reviewer, commenter |
an address that reviewed or commented on the article |
followed_by |
articles by people this address follows |
orcid |
an author’s verified ORCID iD |
published_from, published_to |
publication date (YYYY, YYYY-MM or YYYY-MM-DD, UTC; _to inclusive) |
updated_from, updated_to |
the article’s updated_at, same format: the last call that changed its on-chain record (a version, a status change, an article vote, a review, a comment, a flag…) |
min_votes, min_voters |
minimum vote weight, minimum number of votes |
min_reviews, max_reviews |
number of reviews |
recommendation |
recommendations received (names or 1 to 4) |
min_comments |
number of comments |
has_doi, doi_verified |
a DOI that is verified, cannot be checked (declared) or is not checked yet (never one whose record does not point back); a verified DOI |
orcid_verified |
at least one author with a verified ORCID iD |
sealed |
holds the Peer-reviewed seal |
language, license |
from the front-matter |
valid_only |
content checked as valid |
revised |
has more than one version |
amends |
amendments of this article number |
has_amendments |
has been amended |
keyword |
keywords |
sort |
relevance (default with a query), score (default without), new, old, votes, reviews, comments, updated, cited (most cited on Cabdell) |
limit, offset |
paging |
Returns query (how the query was read: terms, doi, cid, article_id, authors, notes, sort), total,
articles (the list fields plus review_count, comment_count, cited_by, authors, doi and match, the
highlighted passages) and facets. Each facet counts its options under every other filter in use: fields, areas,
types, statuses, years, languages, licenses, recommendations, has_doi, doi_verified, orcid_verified,
revised, sealed, unreviewed, reviewed, valid, has_amendments.
curl "https://api.cabdell.press/testnet/search/articles?q=sleep&field=0x0303&sealed=true&sort=new"GET /search/posts
Section titled “GET /search/posts”Reviews and comments by their text.
| Parameter | Meaning |
|---|---|
q |
the query |
kind |
review, comment |
recommendation |
for reviews (names or 1 to 4) |
field |
the article’s primary or secondary field |
author |
an address |
article |
an article number |
from, to |
dates, same format as above |
sort |
relevance (default with a query), new (default without), old, votes |
Returns query, total, posts (kind, article_id, seq, author, author_name, reply_to_review,
recommendation, created_at, votes, reply_to, article_title, article_status, primary_field,
text_available, excerpt) and facets.
GET /search/people
Section titled “GET /search/people”| Parameter | Meaning |
|---|---|
q |
a verified ORCID name, an ORCID iD or the start of an address |
role |
author, reviewer, commenter |
field |
reputation in this field |
orcid_verified |
only people with a verified ORCID iD |
address |
specific addresses |
sort |
relevance (default with a query), reputation (default without), publications, reviews, recent |
Returns { total, people, notes }. D-164: a person who objects to the display of their reputation has reputation and
field_reputation null and hidden_by_objection true, and sorts as having none.
GET /search/suggest
Section titled “GET /search/suggest”Suggestions while typing: { articles, keywords, fields, people } for q, at most limit (1 to 10, default 5) of
each.
Fields
Section titled “Fields”GET /fields
Section titled “GET /fields”The registered fields, { fields: [...] }, each with field_id, name, hex and articles (articles that are not
retracted, under this field as primary or secondary). See Fields.
What this service withholds
Section titled “What this service withholds”Cabdell stops showing something on its own service only on these grounds (D-164): order (a court or an authority),
notice (a substantiated notice of manifestly illegal content), terms (spam, malware, phishing), data_protection
(a request about one’s own data), copyright, csam (child sexual abuse material), terrorist, other. See
Privacy and permanence. The record on the blockchain is
unchanged; the API leaves out what is withheld and gives, in its place, a statement of reasons:
{ "id": "W-7", "ground": "notice", "reason": "notice", "basis": "…the facts and the rule, in a sentence…", "date": "2026-10-08", "scope": "this service", "redress": "To contest this decision, write to the operator (…) quoting W-7, in English or Spanish. You may also take it to the courts.", "decided_at": 1791417600, "published_at": 1791417600 }reason repeats ground (older clients read it); decided_at and published_at are Unix seconds (00:00 UTC of the
decision and of its publication in the transparency report). Child sexual abuse material is shown with the ground
other and a neutral basis, so that a record’s page never points to such material.
| What is withheld | What the API leaves out | Where the statement of reasons is |
|---|---|---|
| an article | its title, abstract, keywords, snippets and every CID of its versions (wherever the article appears: feed, search, lists, profiles, notifications) | withheld on the article |
| a review or a comment | its text, excerpt and CID | withheld on the review or comment |
| a list or a journal | its name, about, policy (and its volumes’ titles) |
withheld on the list or journal (also inside a notification’s journal) |
| a journal volume | its title |
withheld on the volume; volume_withheld beside a volume_title |
| a flag’s note | note |
note_withheld on the flag (and on the flagger’s flagged timeline entry) |
| a juror’s reasons | reasons |
reasons_withheld on the answer |
| a person (an address) | their names and ORCID data everywhere (identity: {orcid: null}; orcid, name null in authors, seats, pools, people) |
withheld on their profile; /names lists them in hidden |
| a raw CID | that CID wherever it would appear | (none) |
Search never finds what is withheld by its text, and the indexer purges its own copies of the texts.
GET /withheld
Section titled “GET /withheld”The transparency report: { entries: [...], counts: [...] }.
entries: the cases published by now (theirpublished_athas come), newest first, each withid,kind(article,review,comment,list,journal,volume,flag_note,verdict,address,cid),app(the application, or null for the current one), the record (article,seq,owner,list,volume,round,flagger,juror; null when they do not apply),publishedand the statement of reasons. Never a CID or a person’s address. Cases of the groundscsam,terroristanddata_protectionare not listed one by one.counts: every published case counted bymonth(YYYY-MMof the decision),groundandkind:{ month, ground, kind, n }, newest month first.
curl https://api.cabdell.press/testnet/withheldNotifications for push senders
Section titled “Notifications for push senders”GET /notifications?after=
Section titled “GET /notifications?after=”Every address’s notifications created after the id after, oldest first, with latest (the highest id so far). The
web server’s Web Push sender polls this route, one request per network. Notifications are public data already.
curl "https://api.cabdell.press/testnet/notifications?after=0&limit=10"Ingestion and contract v4
Section titled “Ingestion and contract v4”The indexer serves contract v4 only: at start it compares the application’s program with the one it was built for and
refuses any other (D-162), so an indexer of this version cannot read an application of an earlier contract. Every
contract event carries event_seq, a number that the contract gives its events from 1 without gaps; the indexer stores
it. If the next event it reads does not follow the last one it stored, events were missed (for example, a public
endpoint answered from an Algorand indexer that was behind): the poll fails with “missing events” and the watermark
does not move, so the next poll reads the same rounds again. /status gives the last event_seq ingested. See
Run an indexer.