API

This is a list of the endpoints in the site. It includes both those that would be adequately described as API endpoints, as well as internal endpoints that are used for the UI. They are automatically created from the CLOS methods, hence the format: it follow's Snooze's approach, and so&OPTIONAL arguments are URI path components, and &KEY arguments are URL query parameters

Licensing

Database content (entity records, claims, sources) is CC-BY-SA-4.0 ; the ontology, SHACL shapes, and JSON-LD context are CC0-1.0 . The maker separately reserves the EU sui generis database right and TDM rights under DSM Art. 4 for the database tier - see Licensing for the full notice, including the research-use carve-out under DSM Art. 3. Attribution (short form; see Licensing for the standard and academic forms): Martialis (https://martial.is), CC BY-SA 4.0.

Every response carries a Link: rel="license" header and a tdm-reservation header; /.well-known/tdmrep.json states the reservation machine-readably per rule, and /api/info restates it in the API's own terms.

Infrastructure endpoints

Served by plain Hunchentoot dispatchers rather than Snooze resources, so they don't appear in the generated table below.

Method Path Type Description
GET /data.ttl text/turtle Full RDF export of the database (dcat:Dataset with license/rights triples).
GET /context.jsonld application/ld+json The JSON-LD @context every entity document references.
GET /sitemap.xml application/xml Crawler sitemap, generated live from the database.
GET /ontology[.ttl|/...] text/html or text/turtle Ontology/OWL documentation, content-negotiated. CC0-1.0, unreserved for TDM.
GET /vocab[.ttl|/...] text/html or text/turtle SKOS controlled vocabularies, content-negotiated. CC0-1.0, unreserved for TDM.
GET /llms.txt text/plain Orientation layer for AI agents, proxied from martialis-db.
GET /robots.txt text/plain Crawler policy, including the Content-Signal TDM preference.
GET /.well-known/tdmrep.json application/json Machine-readable TDM reservation (W3C TDMRep).
GET /api/graph application/json SPARQL-backed graph slice: nodes/edges around a center entity.
GET /api/info application/json Graph counts plus licence/rights/attribution metadata.
GET /api/node application/json Outgoing/incoming triples for one node (?id=).
GET /api/predicates application/json Every predicate in the graph, most-used first.
GET /api/type-counts application/json Entity counts per rdf:type.
GET /api/types application/json Every rdf:type present in the graph.
Application routes
Method Path Type Args Description
get /about text/html
get /agent text/turtle (&optional slug)
get /agent application/json (&optional slug)
get /agent application/ld+json (&optional slug)
get /agent text/html (&optional slug) A minimal page for SLUG: name, title and affiliation.
get /api-doc text/html List every Snooze route (verb, path, content-type, args, docstring) in a web page.
get /auth-callback text/html (&key code) Exchange the auth code for tokens, verify, set the session cookie. CODE and the error params are read off the request, not Snooze's &key arg.
post /auth-delete-account application/x-www-form-urlencoded Permanently delete the current user's Supabase account and sign them out. Irreversible; the /settings UI gates this behind an in-page confirmation step before submitting.
get /auth-email text/html (&key sent) SENT is read off the query string, not Snooze's &key arg.
post /auth-email application/x-www-form-urlencoded (&key sent) Request a magic-link sign-in/registration email. Register and sign-in are the same flow. SENT is unused here (POST never receives it) but CLOS requires every method's lambda list to be congruent.
get /auth-login text/html (&key provider) Begin the OAuth dance: stash a fresh PKCE verifier in a cookie and redirect to Supabase's /authorize endpoint. PROVIDER is read off the query string, not Snooze's &key arg.
get /auth-logout text/html Clear the session cookie and redirect home.
get /bookmarks text/html
get /countries text/html (&optional code) The country page for CODE, the list of every country otherwise.
post /db-webhook application/json
post /db-webhook application/json
get /discussions text/html
get /entity text/turtle (&optional id)
get /entity application/json (&optional id)
get /entity application/ld+json (&optional id)
get /entity text/html (&optional id) Redirect to ID's real page with a 303 (correct Linked Data dereferencing). A claim goes to its record's page, anchored at the claim.
get /events text/turtle (&optional id)
get /events application/json (&optional id)
get /events application/ld+json (&optional id)
get /events text/html (&optional id) Event page for ID, the list of every event otherwise.
get /graph text/html (&optional entity &key generations all contextual) Render the graph page. See file header for URL semantics.
get /home text/html
get /lang text/html (&key code) Set the UI language cookie to CODE and redirect back.
get /licensing application/ld+json
get /licensing application/json
get /licensing text/html
get /mapping text/html (&optional id)
get /model text/html
get /og image/svg+xml (&optional kind id) The unrasterized SVG, regenerated on every request so template edits show up on reload.
get /og image/png (&optional kind id) The rasterized card - see SERVE-OG-CARD-FILE for the shared headers.
get /og-p image/svg+xml (&optional public-id) The unrasterized SVG: the design/debugging entry point, never cached.
get /og-p image/png (&optional public-id) The rasterized profile card (PROFILE-SOCIAL-CARD's og:image). Uses the shared cache/lock/semaphore machinery (ENSURE-OG-CARD-FOR).
get /og-path image/svg+xml (&optional from to) The unrasterized SVG, regenerated on every request.
get /og-path image/png (&optional from to) The rasterized card - see SERVE-OG-CARD-FILE for the shared headers.
get /og-site image/svg+xml (&optional name) The unrasterized SVG, regenerated on every request.
get /og-site image/png (&optional name) The rasterized site card - see SERVE-OG-CARD-FILE for the shared headers.
get /ontology text/turtle (&optional section subsection) The ontology, SHACL and alignment Turtle documents. Snooze strips a .ttl suffix and matches this route (db/rdf.lisp registers the extension), so /ontology.ttl, /ontology/shapes/quality.ttl and the alignment import all resolve here.
get /ontology text/html (&optional section subsection) The /ontology, /ontology/shapes and /ontology/shapes/<role> documentation pages. The shapes graphs have no page of their own: each 302s to its anchored card on /model.
get /orgs text/turtle (&optional id)
get /orgs application/json (&optional id)
get /orgs application/ld+json (&optional id)
get /orgs text/html (&optional id) Organization page for ID, the list of every organization otherwise.
get /p text/html (&optional public-id)
get /path text/html (&optional from to &key all)
get /persons text/turtle (&optional id)
get /persons application/json (&optional id)
get /persons application/ld+json (&optional id)
get /persons text/html (&optional id) Person page for ID, the list of every person otherwise.
get /places text/turtle (&optional id)
get /places application/json (&optional id)
get /places application/ld+json (&optional id)
get /places text/html (&optional id) Place page for ID, the list of every place otherwise.
get /privacy text/html
get /profile text/html
get /ranking-methodology text/html
get /rankings text/html
get /reload text/html Trigger a manual reload. Off unless MARTIALIS_ENABLE_RELOAD is set (a restart applies a new database), and then it needs a login.
get /settings text/html
get /sources text/turtle (&optional id)
get /sources application/json (&optional id)
get /sources application/ld+json (&optional id)
get /sources text/html (&optional id) Source page for ID, the list of every source otherwise.
get /sparql application/sparql-results+json (&key query &allow-other-keys) The endpoint *SPARQL-QUERY-ENDPOINT* points the explorer at. Gated as the page route; a 404 (not a redirect) when not visible, since this is a data API. &ALLOW-OTHER-KEYS keeps the lambda list congruent with the resource's.
get /sparql text/html (&key query &allow-other-keys) QUERY is declared only so Snooze accepts ?query=...; it is read client-side, never server-side. &ALLOW-OTHER-KEYS lets ?center= through.
post /sparql application/sparql-results+json (&key query &allow-other-keys) Same as the GET route; POST allows queries too long for a URL query string. &ALLOW-OTHER-KEYS for the same lambda-list-congruence reason.
get /style-graph text/html (&optional entity &key generations)
get /styles text/turtle (&optional id)
get /styles application/json (&optional id)
get /styles application/ld+json (&optional id)
get /styles text/html (&optional id) Style page for ID, the list of every style otherwise.
get /stylesheet text/css (&optional id)
get /support text/html
get /timeline text/html (&optional focus)
post /ui-bookmark-toggle application/json (&key datastar id list) Flip bookmark ID for the signed-in user and patch the button into its new state. Adding is checked before the RPC - ID must name a database record and the cap must not be reached - though ADD_BOOKMARK (sql/migrations/0020_bookmarks.sql) re-checks its own looser ceiling. Removing needs no such check: it is scoped to the caller's own rows by RLS, and a row whose entity has left the database must stay removable.
get /ui-graph-contextual text/html (&key datastar)
get /ui-graph-expand application/json (s &key contextual)
get /ui-graph-expand application/json (p &key contextual)
get /ui-graph-focus text/html (s &key datastar (graph-kind graph))
get /ui-graph-focus text/html (p &key datastar graph-kind)
get /ui-graph-help text/html (&key datastar)
get /ui-graph-reset text/html (&key datastar)
get /ui-listing text/html (&key datastar (kind persons)) Re-render the filtered/sorted listing fragment for KIND. Validates KIND before opening the SSE stream, since an error raised inside WITH-SSE can no longer become a clean HTTP status.
get /ui-live text/html (&key datastar topics)
get /ui-path text/html (&key datastar swap)
post /ui-path application/json (&key datastar swap)
post /ui-profile-claim application/json (&key datastar) Validate the claim request, then hand it to the mail worker. Every check is server-side: the button's disabled attribute is a courtesy. The person must resolve in the local corpus (a claim about an id that does not exist is never useful), the evidence must say something, the email must be usable, and the account must not have asked a moment ago.
post /ui-profile-claim-release application/json (&key datastar) Clear the caller's own confirmation (RELEASE-OWN-IDENTITY-CLAIM), then reload so the section shows the request form again. The checkbox is checked here too: the button's disabled attribute is a courtesy.
post /ui-profile-handle application/json (&key datastar) Claim the caller's permanent /@handle, exactly once. Set-once, never-reuse, and the reserved list are enforced in Postgres - by CLAIM-USER-SLUG's RPC plus a guard trigger on profiles.slug and profiles.public_id (sql/migrations/0006_profile_handles.sql) - not here, so they hold even against a direct PATCH or RPC call that bypasses this route.
post /ui-profile-link application/json (&key datastar) Add the picked person as a new lineage claim, then patch the whole claims block with the fresh list. Two checks before the RPC, both of which the UI already implies but neither of which it can be trusted to enforce: the target must resolve to a real database person (GET-PERSON-BY-ID is a local lookup - the picker only ever offers these, but a direct POST can name anything), and the caller's own cap must not already be reached. ADD-PROFILE-LINK (sql/migrations/0007_profile_links_limit.sql) re-checks its own looser abuse ceiling underneath; this is the user-facing 5.
post /ui-profile-publish application/json (&key datastar) Publish or unpublish. A Datastar boolean signal is T when checked and :FALSE (not NIL) when unchecked, so normalise before saving.
post /ui-profile-save application/json (&key datastar) Display name and bio only. PHOTO-URL is never accepted: the photo always follows the OAuth avatar. Length is checked here, before the write, so an over-long value gets a sentence naming the limit instead of the DB constraint error (which UPDATE-USER-PROFILE would collapse into the generic 'Couldn't save'). The CHECK constraints are the real backstop.
post /ui-profile-set-style application/json (&key datastar) Set STYLE-ID on the claim named by PROFILE.STYLETARGETID - set by that card's own "Add/Change style" button before the (page-level, shared) style picker's commit - then patch the whole claims block and close the picker.
post /ui-profile-unlink application/json (&key datastar) Remove one claim - PROFILE.ACTIONTARGET, set by that card's own button just before this POST (RENDER-PROFILE-LINK-CARD) - then patch the whole claims block with the fresh list.
post /ui-profile-unset-style application/json (&key datastar) Clear the style on the claim named by PROFILE.ACTIONTARGET, then patch the whole claims block.
get /ui-search text/html (&key datastar (mode navigate)) Search every kind in +SEARCH-KINDS+ by name, or run a registered picker (see REGISTER-PICKER) when MODE names one.
post /ui-settings-focus application/json (&key datastar)
post /ui-settings-locale application/json (&key datastar)
post /ui-settings-marketing application/json (&key datastar) Save or withdraw the newsletter opt-in (GDPR Art. 7(3): withdrawing must be as easy as giving consent). A Datastar boolean is T when checked and :FALSE (not NIL) when unchecked, so normalise before saving. Report success only when UPSERT-USER-SETTING actually succeeds.
get /ui-show-all text/html (&key datastar)
get /ui-style-graph-help text/html (&key datastar)
get /ui-style-graph-reset text/html (&key datastar)
post /ui-suggestion-save application/json (&key datastar)
get /ui-timeline text/html (&key datastar) Re-lay out #timeline-track for the zoom, lanes and kind signals, update the status, then scroll back to the axis position the view was centred on (tl.x). The selected entry is pinned, so it survives every zoom.
get /vocab text/turtle (&optional scheme concept) The vocabularies file, or one scheme's slice. A concept or collection IRI resolves to the scheme document containing it.
get /vocab text/html (&optional scheme concept) The /vocab index, a /vocab/<scheme> page, or the scheme page a /vocab/<scheme>/<concept> IRI names (302 to the concept's anchor).