@@ -98,6 +98,202 @@ the entire registry, or a CSV diff between two schemas.
9898
9999---
100100
101+ ## API Reference
102+
103+ ** Base URL:** ` https://sensein.group/NeuroGhost `
104+
105+ The registry exposes two kinds of endpoints:
106+
107+ | Type | Transport | Auth | Status |
108+ | ------| -----------| ------| --------|
109+ | Read (schemas, alignments, provenance) | Static JSON via GitHub Pages | None | ✅ Live |
110+ | Transform (field mapping between schemas) | Serverless function (planned) | None | 🔜 Planned |
111+
112+ CORS is open on all endpoints. No API key required.
113+
114+ ---
115+
116+ ### ` GET /data/registry.json `
117+
118+ Returns the full registry at the current version: all sources, classes,
119+ properties, and pre-computed cross-schema alignments.
120+
121+ ``` bash
122+ curl https://sensein.group/NeuroGhost/data/registry.json
123+ ```
124+
125+ ** Response**
126+ ``` json
127+ {
128+ "registry_version" : " 1.7.0" ,
129+ "generated_at" : " 2026-07-23T12:40:24Z" ,
130+ "sources" : [
131+ { "label" : " bbqs" , "version" : " 1.0.0" , "class_count" : 29 },
132+ { "label" : " bids" , "version" : " 1.9.0" , "class_count" : 1 },
133+ { "label" : " dandi" , "version" : " 0.6.8" , "class_count" : 20 },
134+ { "label" : " nwb" , "version" : " 2.7.0" , "class_count" : 53 }
135+ ],
136+ "classes" : [
137+ {
138+ "uid" : " 8003dcad-..." ,
139+ "iri" : " https://registry.sensein.io/obj/Subject" ,
140+ "name" : " Subject" ,
141+ "definition" : " A research participant." ,
142+ "abstract" : false ,
143+ "source" : " bbqs" ,
144+ "properties" : [
145+ {
146+ "uid" : " 807f8fec-..." ,
147+ "name" : " age" ,
148+ "definition" : " Age in years." ,
149+ "datatype" : " xsd:integer" ,
150+ "multivalued" : false ,
151+ "required" : false ,
152+ "source" : " bbqs"
153+ }
154+ ],
155+ "alignments" : [
156+ {
157+ "target_uid" : " f4f8e4a4-..." ,
158+ "target_name" : " Participant" ,
159+ "target_source" : " bids" ,
160+ "distance" : 0.12 ,
161+ "method" : " composite" ,
162+ "scores" : { "iri" : 0.0 , "name" : 0.08 , "desc" : 0.19 , "slot" : 0.0 }
163+ }
164+ ]
165+ }
166+ ]
167+ }
168+ ```
169+
170+ ` distance ` ranges from ** 0.0** (identical) to ** 1.0** (unrelated).
171+
172+ ---
173+
174+ ### ` GET /data/versions/{version}.json `
175+
176+ Frozen snapshot of the registry at a specific version. Snapshots never change.
177+
178+ ``` bash
179+ curl https://sensein.group/NeuroGhost/data/versions/1.2.0.json
180+ ```
181+
182+ Same shape as ` registry.json ` . To list available versions, check the
183+ ` registry_version ` field of the live registry and the ` data/versions/ `
184+ directory.
185+
186+ ---
187+
188+ ### ` GET /data/provenance.json `
189+
190+ Changelog — every schema ingestion: who submitted it, when, and which registry
191+ version it produced.
192+
193+ ``` bash
194+ curl https://sensein.group/NeuroGhost/data/provenance.json
195+ ```
196+
197+ ---
198+
199+ ### Client-side filtering
200+
201+ There are no server-side query parameters (static files). Filter in your
202+ client after fetching:
203+
204+ ``` js
205+ const reg = await fetch (" https://sensein.group/NeuroGhost/data/registry.json" )
206+ .then (r => r .json ());
207+
208+ // All classes from one schema
209+ const bbqs = reg .classes .filter (c => c .source === " bbqs" );
210+
211+ // Close alignments across any two schemas (distance < 0.35)
212+ const pairs = reg .classes .flatMap (c =>
213+ c .alignments
214+ .filter (a => a .distance < 0.35 )
215+ .map (a => ({ from: ` ${ c .source } /${ c .name } ` , to: ` ${ a .target_source } /${ a .target_name } ` , distance: a .distance }))
216+ );
217+ ```
218+
219+ ---
220+
221+ ### ` GET /api/transform ` — field mapping * (planned)*
222+
223+ Returns the computed field-to-field mapping between two schemas, derived from
224+ the alignment graph. No data is sent — this is purely a schema-level lookup.
225+
226+ ```
227+ GET /api/transform?from=bbqs&to=bids
228+ ```
229+
230+ ** Planned response**
231+ ``` json
232+ {
233+ "from" : " bbqs" ,
234+ "to" : " bids" ,
235+ "mappings" : [
236+ {
237+ "from_class" : " Subject" ,
238+ "to_class" : " Participant" ,
239+ "distance" : 0.12 ,
240+ "field_mappings" : [
241+ { "from_field" : " age" , "to_field" : " age" , "confidence" : 0.97 },
242+ { "from_field" : " species" , "to_field" : " species" , "confidence" : 0.91 },
243+ { "from_field" : " subject_id" , "to_field" : " participant_id" ,"confidence" : 0.85 }
244+ ]
245+ }
246+ ]
247+ }
248+ ```
249+
250+ Because the alignment data is already in ` registry.json ` , this endpoint can be
251+ pre-computed at export time and served as a static file — no compute layer
252+ needed.
253+
254+ ---
255+
256+ ### ` POST /api/transform ` — data transform * (planned)*
257+
258+ Send a dataset in one schema's format; receive it mapped to another. Unlike the
259+ GET above, this requires a live compute layer (a serverless function that reads
260+ the field-mapping and rewrites the payload).
261+
262+ ``` bash
263+ curl -X POST https://sensein.group/NeuroGhost/api/transform \
264+ -H " Content-Type: application/json" \
265+ -d ' {
266+ "from": "bbqs",
267+ "to": "bids",
268+ "data": {
269+ "subject_id": "sub-01",
270+ "age": 24,
271+ "species": "Homo sapiens"
272+ }
273+ }'
274+ ```
275+
276+ ** Planned response**
277+ ``` json
278+ {
279+ "from" : " bbqs" ,
280+ "to" : " bids" ,
281+ "result" : {
282+ "participant_id" : " sub-01" ,
283+ "age" : 24 ,
284+ "species" : " Homo sapiens"
285+ },
286+ "unmapped_fields" : [],
287+ "warnings" : []
288+ }
289+ ```
290+
291+ This will be implemented as a lightweight serverless function (Cloudflare Worker
292+ or equivalent) that reads the static registry alignment map and applies field
293+ renaming. Not yet live.
294+
295+ ---
296+
101297## Adding your own schema
102298
103299The easiest way, no setup required:
0 commit comments