{
  "openapi": "3.1.0",
  "info": {
    "title": "Sciync Public API",
    "version": "1.0.0",
    "summary": "AI-lab-friendly ground truth from the Sciync scientific consensus graph",
    "description": "The Sciync public API surfaces the Kernel (claim) / Paper / Project\nprimitives with reputation-weighted consensus, streaming Bayesian\nposteriors, and a grounded RAG endpoint for LLM vendors.\n\n### Design principles\n\n- **No hallucination.** Every field is either true or `null`. A claim\n  with zero positions returns `consensus: null`; a grounding call with\n  no match returns `{matched: false, nearestCandidates: [...]}` — we\n  never invent numbers or pretend the nearest claim matches.\n- **Provenance on every response.** Every payload carries an\n  `apiVersion`, `generatedAt`, `citationUrl`, `rateLimitRemaining`,\n  `disclaimer`, and `license` so consumers can attribute correctly.\n- **Open by default.** CORS `*`, rate-limited per IP, no auth\n  required. AI labs: build freely.\n- **License.** CC-BY-4.0 with attribution; not medical advice.\n\n### Endpoints\n\n- `POST /api/v1/ground` — flagship RAG endpoint. Given a claim or\n  claimId, returns the matched Kernel's posterior + evidence stream +\n  consensus.\n- `GET /api/v1/claim/:id` — public read of a single Kernel with\n  posterior + consensus + source fields.\n- `GET /api/v1/search` — hybrid RRF + ZeroEntropy-reranked search\n  over the Kernel corpus.\n- `POST /api/v1/ai-claim` — ingest a candidate claim an AI model\n  produced; returns a ticket for extraction.\n- `GET /api/v1/health` — v1 health probe with dependency checks.\n\n### Rate limits\n\n- `/api/v1/ground`: 60 / min / IP\n- `/api/v1/claim/:id`, `/api/v1/search`, `/api/v1/health`: 300 / min / IP\n- `/api/v1/ai-claim`: 30 / hour / IP\n\nHigher limits will be available via API keys once the key-issuing\nconsole ships (v0.45+).",
    "contact": {
      "name": "Sciync",
      "url": "https://sciync.com",
      "email": "hq@sciync.com"
    },
    "license": {
      "name": "CC-BY-4.0 (with attribution; not medical advice)",
      "url": "https://creativecommons.org/licenses/by/4.0/"
    }
  },
  "servers": [
    {
      "url": "https://sciync.com",
      "description": "Production"
    },
    {
      "url": "http://localhost:3000",
      "description": "Local development"
    }
  ],
  "tags": [
    {
      "name": "grounding",
      "description": "Retrieve Sciync ground truth for AI outputs"
    },
    {
      "name": "claims",
      "description": "Read individual Kernels (claims)"
    },
    {
      "name": "search",
      "description": "Discover Kernels matching a query"
    },
    {
      "name": "intake",
      "description": "Submit AI-generated candidates for grounding"
    },
    {
      "name": "ops",
      "description": "Operational probes"
    }
  ],
  "paths": {
    "/api/v1/ground": {
      "post": {
        "tags": [
          "grounding"
        ],
        "summary": "Ground an AI-generated claim against Sciync consensus",
        "description": "Given a claim text (preferred) OR a claimId, return the matched Kernel, its posterior, reputation-weighted consensus, and evidence stream — or `{matched: false}` when no claim meets the similarity threshold.",
        "operationId": "ground",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroundRequest"
              },
              "examples": {
                "textQuery": {
                  "summary": "Query by claim text",
                  "value": {
                    "claim": "Thrombectomy improves 90-day mRS in large-vessel-occlusion stroke vs IV tPA alone",
                    "domain": "neurointerventional",
                    "maxEvidence": 10,
                    "minSimilarity": 0.7
                  }
                },
                "byId": {
                  "summary": "Direct claimId lookup",
                  "value": {
                    "claimId": "clm_mrclean_primary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Grounded response (matched or unmatched)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroundResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed; see `error: invalid_input`"
          },
          "404": {
            "description": "claimId provided but not found"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/api/v1/claim/{id}": {
      "get": {
        "tags": [
          "claims"
        ],
        "summary": "Read a single Kernel",
        "operationId": "getClaim",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{6,64}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Kernel found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimReadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed id"
          },
          "404": {
            "description": "Not found"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "tags": [
          "search"
        ],
        "summary": "Hybrid search across the Kernel corpus",
        "operationId": "search",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 25,
              "default": 10
            }
          },
          {
            "in": "query",
            "name": "domain",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            }
          },
          {
            "in": "query",
            "name": "temporalState",
            "schema": {
              "type": "string",
              "enum": [
                "HISTORICAL",
                "CURRENT",
                "FUTURE"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked hits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/api/v1/ai-claim": {
      "post": {
        "tags": [
          "intake"
        ],
        "summary": "Submit an AI-generated candidate claim for grounding",
        "operationId": "submitAiClaim",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AiClaimRequest"
              },
              "examples": {
                "chatbotReply": {
                  "summary": "Chatbot-generated claim from a clinical Q&A",
                  "value": {
                    "candidateText": "GLP-1 agonists reduce MACE in T2D patients with established CVD",
                    "sourceUrl": "https://example.com/chat/abc123",
                    "sourceKind": "chatbot_reply",
                    "producerModel": "claude-sonnet-4-6",
                    "domain": "cardiology"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Ticket queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiClaimResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "tags": [
          "ops"
        ],
        "summary": "Health probe with dependency checks",
        "operationId": "health",
        "responses": {
          "200": {
            "description": "Service healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          },
          "503": {
            "description": "One or more dependencies failing"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Provenance": {
        "type": "object",
        "required": [
          "apiVersion",
          "generatedAt",
          "citationUrl",
          "rateLimitRemaining",
          "disclaimer",
          "license"
        ],
        "properties": {
          "apiVersion": {
            "type": "string",
            "enum": [
              "v1"
            ]
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "citationUrl": {
            "type": "string",
            "format": "uri"
          },
          "rateLimitRemaining": {
            "type": "integer",
            "minimum": 0
          },
          "disclaimer": {
            "type": "string"
          },
          "license": {
            "type": "string"
          }
        }
      },
      "GroundRequest": {
        "type": "object",
        "properties": {
          "claim": {
            "type": "string",
            "minLength": 10,
            "maxLength": 1000
          },
          "claimId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{6,64}$"
          },
          "domain": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          },
          "maxEvidence": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50,
            "default": 10
          },
          "minSimilarity": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 0.7
          }
        }
      },
      "GroundMatch": {
        "type": "object",
        "required": [
          "claimId",
          "text",
          "temporalState",
          "domainTags",
          "similarity",
          "method"
        ],
        "properties": {
          "claimId": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "temporalState": {
            "type": "string",
            "enum": [
              "HISTORICAL",
              "CURRENT",
              "FUTURE"
            ]
          },
          "domainTags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "similarity": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "method": {
            "type": "string",
            "enum": [
              "exact_id",
              "semantic_search"
            ]
          }
        }
      },
      "Posterior": {
        "type": "object",
        "required": [
          "mean",
          "ci95",
          "snapshotAt",
          "evidenceCount"
        ],
        "properties": {
          "mean": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "ci95": {
            "type": "array",
            "items": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "minItems": 2,
            "maxItems": 2
          },
          "snapshotAt": {
            "type": "string",
            "format": "date-time"
          },
          "evidenceCount": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "Consensus": {
        "type": "object",
        "required": [
          "calibrationWeightedCredence",
          "contributorsN",
          "domainRestrictedN"
        ],
        "properties": {
          "calibrationWeightedCredence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "supportPct": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "contestPct": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "neutralPct": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "contributorsN": {
            "type": "integer",
            "minimum": 0
          },
          "domainRestrictedN": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "EvidenceEvent": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "direction",
          "likelihoodRatio",
          "summary",
          "source",
          "observedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "support",
              "contest",
              "neutral"
            ]
          },
          "likelihoodRatio": {
            "type": "number",
            "minimum": 0
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plain-English auto-summary. Null until v0.44.1 backfill populates."
          },
          "source": {
            "type": "object",
            "required": [
              "kind",
              "identifier"
            ],
            "properties": {
              "kind": {
                "type": "string"
              },
              "identifier": {
                "type": "string"
              },
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "NearestCandidate": {
        "type": "object",
        "required": [
          "claimId",
          "text",
          "similarity"
        ],
        "properties": {
          "claimId": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "similarity": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "GroundResponse": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "ok",
              "matched",
              "match",
              "evidence",
              "nearestCandidates",
              "provenance"
            ],
            "properties": {
              "ok": {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              "matched": {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              "match": {
                "$ref": "#/components/schemas/GroundMatch"
              },
              "posterior": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Posterior"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "consensus": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Consensus"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "evidence": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EvidenceEvent"
                }
              },
              "nearestCandidates": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/NearestCandidate"
                }
              },
              "provenance": {
                "$ref": "#/components/schemas/Provenance"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "ok",
              "matched",
              "reason",
              "nearestCandidates",
              "provenance"
            ],
            "properties": {
              "ok": {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              "matched": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "reason": {
                "type": "string",
                "enum": [
                  "no_claim_matched",
                  "query_too_short",
                  "corpus_empty"
                ]
              },
              "nearestCandidates": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/NearestCandidate"
                }
              },
              "provenance": {
                "$ref": "#/components/schemas/Provenance"
              }
            }
          }
        ]
      },
      "ClaimReadResponse": {
        "type": "object",
        "required": [
          "ok",
          "claim",
          "source",
          "attribution",
          "provenance"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "claim": {
            "type": "object",
            "required": [
              "id",
              "text",
              "temporalState",
              "domainTags",
              "status",
              "createdAt"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "text": {
                "type": "string"
              },
              "temporalState": {
                "type": "string",
                "enum": [
                  "HISTORICAL",
                  "CURRENT",
                  "FUTURE"
                ]
              },
              "domainTags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "status": {
                "type": "string"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "posterior": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Posterior"
              },
              {
                "type": "null"
              }
            ]
          },
          "consensus": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Consensus"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "type": "object",
            "required": [
              "pmid",
              "doi",
              "nctNumber",
              "title",
              "journal",
              "year",
              "isRetracted"
            ],
            "properties": {
              "pmid": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "doi": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "nctNumber": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "journal": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "year": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "isRetracted": {
                "type": "boolean"
              }
            }
          },
          "attribution": {
            "type": "object",
            "required": [
              "claimUrl",
              "embedUrl",
              "signalUrl"
            ],
            "properties": {
              "claimUrl": {
                "type": "string",
                "format": "uri"
              },
              "embedUrl": {
                "type": "string",
                "format": "uri"
              },
              "signalUrl": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "provenance": {
            "$ref": "#/components/schemas/Provenance"
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "ok",
          "query",
          "hits",
          "semanticUsed",
          "rerankUsed",
          "provenance"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "query": {
            "type": "string"
          },
          "hits": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "claimId",
                "text",
                "temporalState",
                "score",
                "sources",
                "claimUrl"
              ],
              "properties": {
                "claimId": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "temporalState": {
                  "type": "string",
                  "enum": [
                    "HISTORICAL",
                    "CURRENT",
                    "FUTURE"
                  ]
                },
                "domainTags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "score": {
                  "type": "number"
                },
                "rerankedScore": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "similarity": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 1
                },
                "sources": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "keyword",
                      "semantic"
                    ]
                  }
                },
                "claimUrl": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "semanticUsed": {
            "type": "boolean"
          },
          "rerankUsed": {
            "oneOf": [
              {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              {
                "type": "string",
                "enum": [
                  "zeroentropy",
                  "voyage"
                ]
              }
            ]
          },
          "provenance": {
            "$ref": "#/components/schemas/Provenance"
          }
        }
      },
      "AiClaimRequest": {
        "type": "object",
        "required": [
          "candidateText",
          "sourceUrl",
          "sourceKind"
        ],
        "properties": {
          "candidateText": {
            "type": "string",
            "minLength": 10,
            "maxLength": 500
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2000
          },
          "sourceKind": {
            "type": "string",
            "enum": [
              "chatbot_reply",
              "research_paper",
              "dataset_card",
              "preprint",
              "blog_post",
              "other"
            ]
          },
          "producerModel": {
            "type": "string",
            "maxLength": 200
          },
          "domain": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          }
        }
      },
      "AiClaimResponse": {
        "type": "object",
        "required": [
          "ok",
          "ticketId",
          "status",
          "provenance"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "ticketId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "grounding_failed"
            ]
          },
          "eta": {
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "lowerMs",
                  "upperMs"
                ],
                "properties": {
                  "lowerMs": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "upperMs": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "rejectionReason": {
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "grounding_substring_missing",
                  "candidate_too_similar_to_existing",
                  "producer_model_disallowed"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "provenance": {
            "$ref": "#/components/schemas/Provenance"
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "ok",
          "version",
          "region",
          "uptimeMs",
          "checks",
          "provenance"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "version": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "uptimeMs": {
            "type": "integer",
            "minimum": 0
          },
          "checks": {
            "type": "object",
            "required": [
              "database",
              "rateLimit"
            ],
            "properties": {
              "database": {
                "type": "string",
                "enum": [
                  "ok",
                  "degraded",
                  "failed"
                ]
              },
              "rateLimit": {
                "type": "string",
                "enum": [
                  "ok",
                  "degraded",
                  "failed"
                ]
              }
            }
          },
          "provenance": {
            "$ref": "#/components/schemas/Provenance"
          }
        }
      }
    }
  }
}