Skip to content

Developers

Two endpoints. An afternoon. No SDK.

JSON over HTTP with one header. Send documents, ask questions, get answers with citations that resolve. Nothing to adopt and nothing to keep in sync with our releases.

  • REST API
  • 69 MCP tools
  • scoped keys
  • idempotent ingest

Quickstart

Four steps to a cited answer.

All of it on the free tier, with no card.

  1. Create an organisation

    Sign up and you get an organisation with one workspace on the free tier. No card, and no tier decision to make yet.

    the first workspace is always RAG

  2. Issue a key

    In the workspace settings, create an API key. It starts with ingest and search, which is all this quickstart needs; add the ontology or workspace scopes for the routes that ask for them. Copy it — the plaintext is shown once.

    default scopes: ingest · search

  3. POST a document

    Send text with your own identifier as the key. Every workspace already has a default source, so there is nothing to configure first.

    POST /v1/ingest

  4. Ask a question

    You get ranked passages, a cited answer, and the timings behind it. On the free tier that is search over your content; on the graph tier the search also reaches across documents and returns the connections it used.

    POST /v1/search

POST /v1/ingest
curl -X POST https://api.graas.ai/v1/ingest \
  -H "x-api-key: $GRAAS_KEY" \
  -H "content-type: application/json" \
  -d '{
    "sourceSlug": "billing",
    "externalId": "account-4471",
    "title": "Account 4471 — Team Annual",
    "textContent": "Plan: Team Annual. Seats: 240.
                    SSO entitlement: false. Renews: 2027-03-01."
  }'

# 202 Accepted
# { "documentId": "...", "externalId": "account-4471",
#   "status": "extracting", "chunksCreated": 1,
#   "statusUrl": "/v1/ingest/.../status" }
POST /v1/search
curl -X POST https://api.graas.ai/v1/search \
  -H "x-api-key: $GRAAS_KEY" \
  -H "content-type: application/json" \
  -d '{ "query": "does onboarding reduce churn?" }'

The customer API

What you can call with an API key.

The full API also covers the console, tenancy, billing and platform-admin surfaces. These are the routes an integration uses.

Ingest

Push documents. Idempotent on your own identifier, so retries are safe.

  • POST/v1/ingestOne document. 200 indexed on the RAG tier; 202 extracting plus a status URL on the graph tier.
  • POST/v1/ingest/batchMany at once, up to 500 per request.
  • GET/v1/ingest/:id/statusPipeline phase, timings, failure reason.
  • DELETE/v1/ingest/:externalIdRemoves the document and drops its support for every fact it asserted.

Search

Ranked passages, a cited answer, the graph evidence, and per-step timings.

  • POST/v1/searchThe main call. Optional prior turns, never stored.
  • POST/v1/search/streamThe same, as server-sent events.
  • POST/v1/search/testDiagnostics: everything a search reached, and how long each part of it took.

Sources

Integration connections. Every document belongs to exactly one.

  • GET/v1/sourcesList. Every workspace is seeded with a default.
  • POST/v1/sourcesCreate, with an integration type that steers extraction.
  • GET/v1/sources/:sourceIdOne source, with its document count.
  • PATCH/v1/sources/:sourceIdRename, or pause.
  • DELETE/v1/sources/:sourceIdRefused while the source still holds documents.

Ontology and reconciliation

Read your vocabulary, curate a draft of it and its rules, apply the draft, and follow each apply.

  • GET/v1/ontologyWhich version runs, and the open draft.
  • GET/v1/ontology/versions/active/termsThe active vocabulary: entity types and predicates.
  • POST/v1/ontology/versionsFork a draft from the active version.
  • POST/v1/ontology/versions/draft/termsAdd an entity type or a predicate to the draft.
  • PATCH/v1/ontology/versions/draft/terms/:termIdRename a term, keeping its old name as an alias, or describe it.
  • PUT/v1/ontology/versions/draft/terms/:termId/mergeFold one term into another. Nothing stored is rewritten, so it can be undone.
  • POST/v1/ontology/versions/draft/axiomsAdd a rule to the draft: a directive, a constraint the graph is checked against, or an inference.
  • PATCH/v1/ontology/versions/draft/axioms/:axiomIdChange a rule, or archive it and withdraw what it derived.
  • POST/v1/ontology/versions/active/axiom-evaluationsCheck the active version’s rules against the graph, and get every warning back.
  • POST/v1/ontology/applicationsApply the draft, or go back to the live vocabulary. Send the draft’s revision and a retry is safe.
  • GET/v1/ontology/applicationsEach apply, newest first, and how its rebuild went.
  • GET/v1/reconciliation/runsFolding runs: when they ran, what they merged.

Graph

The entities and relations extraction found, shaped to draw as they stand. On the graph tier.

  • GET/v1/graphThe most connected entities and the relations between them, in one call.
  • GET/v1/graph/entitiesFind an entity by name or alias, or list the ones nothing connects to.
  • GET/v1/graph/entities/:entityIdOne entity, its relations, and the documents behind each.
  • GET/v1/graph/entities/:entityId/neighborhoodThe graph around one entity, ready to draw.
  • GET/v1/graph/entity-typesThe types your entities read as, with counts.

Workspace

The workspace at a glance, and the decisions its graph still has waiting.

  • GET/v1/health/corpusHow usable the graph is, as a score and what it is made of. On the graph tier.
  • GET/v1/metricsWhat the workspace holds, and a week of documents and searches per day.
  • GET/v1/reconciliation/candidatesPairs of entities queued for folding and not yet decided.

Documents and search history

What the workspace holds, how each document was processed, and what people asked of it.

  • GET/v1/documentsEvery document with where it is in processing, and a count per status.
  • GET/v1/documents/:documentIdOne document, with what each step of processing cost.
  • GET/v1/documents/:documentId/chunksThe chunks search matches against, in order, beside how many ingest recorded.
  • POST/v1/documents/:documentId/extractionsProcess a failed document again, from what was stored.
  • GET/v1/searchesThe questions asked and how each went. They are your users’ words, so it needs the workspace:read scope.
  • GET/v1/searches/:searchIdOne search: what it cited, what each step took, the answer it gave.

Response shape

Everything the pipeline learned, in the payload.

POST /v1/search — response
{
  "results": [
    { "documentId": "...", "externalId": "account-4471",
      "title": "Account 4471 — Team Annual",
      "integrationType": "salesforce",     // which system it came from
      "score": 0.0263,
      "chunk": "Plan: Team Annual. Seats: 240. SSO entitlement: false.",
      "summary": null,
      "metadata": { "accountUrl": "https://crm.example/4471" } }
  ],
  "answer": {
    "text": "Not on your current plan — account 4471 is on Team Annual [1]...",
    "citations": [
      { "marker": 1, "documentId": "...", "externalId": "account-4471",
        "title": "Account 4471 — Team Annual" }
    ],
    "tokensIn": 3184, "tokensOut": 96, "generationMs": 890
  },
  "graphContext": {
    "facts": ["Team Annual —excludes→ SAML SSO (confidence 0.93, 2 sources)"],
    "resolvedFromQuery": ["SSO"],
    "expandedEntities": ["SAML SSO", "Team Annual", "Business"]
  },
  "metadata": {
    "mode": "graph", "retrievalPath": "fused", "graphExpansion": true,
    "searchTimeMs": 661, "vectorSearchMs": 142, "graphTraversalMs": 187,
    "entitiesResolved": 1, "entitiesExpanded": 3
  }
}

Authentication

One header, scoped keys.

Keys belong to a workspace and carry the scopes they were issued with — ingest, search, and for governance ontology:read, ontology:write (to fork and edit a draft) and ontology:publish (to apply it). Issue and rotate them yourself; the plaintext is shown once at creation and never retrievable afterwards. A key used outside its scope gets a 403 that names the scope it lacked rather than a generic denial.

Errors

Predictable shapes.

  • 400BAD_REQUESTThe request did not match the schema. `data.issues` names the field.
  • 401INVALID_API_KEYA key we did not issue, or one revoked or rotated.
  • 403INSUFFICIENT_SCOPEThe key lacks the scope the route needs; `data.required` names it.
  • 403TIER_RESTRICTEDA graph-tier route on a workspace that is on the RAG tier.
  • 404DOCUMENT_NOT_FOUNDNo document with that id in this workspace.
  • 413PAYLOAD_TOO_LARGEThe request body is above the size limit. Split it on a meaningful boundary.
  • 429QUOTA_EXCEEDEDAbove your plan's search rate or quota; `data` names the limit. Retry with backoff.

Model Context Protocol

69 tools, and a rule that keeps them honest.

An MCP client connects, authorises once as a person, and from then on works in one workspace at the access level that person chose — never with more than their own access.

The rule: a tool exists if and only if the published documentation exposes that endpoint, and it requires exactly the scope and tier that endpoint requires. It is enforced by the build in both directions — an undocumented tool fails CI, and so does a documented endpoint with no tool.

  • readLook. Search, and read the graph, the ontology, the documents, sources and filter attributes, and the search history. Changes nothing.search · ontology:read · workspace:read
  • read-writeLook and add content. Everything read can do, plus ingest and managing sources and filter attributes.+ ingest
  • fullGovern. Everything above, plus drafting the ontology and its rules. Applying a draft stays with a person.+ ontology:write · ontology:publish
  • search_knowledgeAsk a question and get the cited answer.search
  • search_diagnosticsThe same question, with the per-step trace.search
  • list_searchesPast searches: what was asked, and how it went.workspace:read
  • get_searchOne past search and the answer it gave.workspace:read
  • list_search_runsThe diagnostic runs kept for a search.workspace:read
  • ingest_documentPush one document.ingest
  • ingest_documentsPush a batch.ingest
  • get_document_statusWhere a document is in the pipeline.ingest
  • delete_documentRemove a document by external identifier.ingest
  • list_documentsThe documents, and where each one is in processing.workspace:read
  • get_documentOne document and what processing it cost.workspace:read
  • list_document_chunksWhat the search index holds for a document.workspace:read
  • retry_documentProcess a failed document again.ingest
  • list_sourcesThe workspace's integration connections.search
  • create_sourceAdd a connection.ingest
  • update_sourceRename or pause a source.ingest
  • delete_sourceRemove an empty connection.ingest
  • get_workspace_metricsThe workspace at a glance.workspace:read
  • get_corpus_healthHow healthy the knowledge graph is, scored.workspace:readgraph tier
  • list_reconciliation_runsFolding runs: when they ran, what they merged.searchgraph tier
  • list_reconciliation_candidatesEntity pairs waiting to be decided.searchgraph tier
  • list_ontology_termsEntity types and predicates in a version — the active one by default.searchgraph tier
  • get_graphA drawable slice of the knowledge graph.searchgraph tier
  • list_graph_entitiesEntities in the graph, searchable by name.searchgraph tier
  • list_entity_typesThe entity types the graph holds, with counts.searchgraph tier
  • get_graph_entityOne entity, its relations and where they came from.searchgraph tier
  • get_graph_neighborhoodThe graph around one entity, ready to draw.searchgraph tier
  • get_filter_attributesThe attributes documents can be filtered on.search
  • set_filter_attributesDeclare those attributes.ingest
  • get_ontologyWhich version runs, and the open draft.ontology:readgraph tier
  • list_ontology_versionsEvery version of the ontology.ontology:readgraph tier
  • get_ontology_versionOne version, with the revision its edits take.ontology:readgraph tier
  • get_ontology_version_changesWhat a version changed against its parent.ontology:readgraph tier
  • get_ontology_version_impactWhat applying a version would hide.ontology:readgraph tier
  • get_ontology_driftTerms extraction learned since the version froze.ontology:readgraph tier
  • get_ontology_termOne term, as a version names it.ontology:readgraph tier
  • get_ontology_term_merge_impactWhat merging two draft terms would do.ontology:readgraph tier
  • list_ontology_applicationsEach apply, and how its rebuild went.ontology:readgraph tier
  • get_ontology_applicationOne apply, followed to the end.ontology:readgraph tier
  • create_ontology_draftFork an editable draft.ontology:writegraph tier
  • delete_ontology_draftDiscard the draft.ontology:writegraph tier
  • add_ontology_termAdd a type or a predicate to the draft.ontology:writegraph tier
  • update_ontology_termRename, describe or alias a draft term.ontology:writegraph tier
  • remove_ontology_termRemove a term from the draft.ontology:writegraph tier
  • merge_ontology_termsFold one draft term into another.ontology:writegraph tier
  • unmerge_ontology_termUndo a merge in the draft.ontology:writegraph tier
  • list_axiomsThe rules on a version.ontology:readgraph tier
  • get_axiomOne rule, archived or not.ontology:readgraph tier
  • list_axiom_warningsWhere the graph breaks a constraint.ontology:readgraph tier
  • add_axiomAdd a rule to the draft.ontology:writegraph tier
  • update_axiomChange or archive a draft rule.ontology:writegraph tier
  • compile_axiomCompile a draft rule again.ontology:writegraph tier
  • update_axiom_warningResolve or ignore a warning.ontology:writegraph tier
  • list_contradiction_issuesWhere documents disagree or copy each other, highest priority first.contradictions:readgraph tier
  • get_contradiction_statsIssues counted by status, kind and finding.contradictions:readgraph tier
  • get_contradiction_estimateWhether detection is on, what is left and what it costs.contradictions:readgraph tier
  • list_contradiction_conflictsWhere documents answer one question differently.contradictions:readgraph tier
  • get_contradiction_conflictOne conflict and the statements behind it.contradictions:readgraph tier
  • list_contradiction_statement_referencesEvery page that makes one statement.contradictions:readgraph tier
  • list_contradiction_conflict_eventsA conflict’s history, decisions included.contradictions:readgraph tier
  • list_contradiction_duplicatesPassages copied across documents.contradictions:readgraph tier
  • get_contradiction_duplicateOne copied passage and its copies.contradictions:readgraph tier
  • list_contradiction_duplicate_eventsA duplicate’s history, decisions included.contradictions:readgraph tier
  • list_contradiction_rulesWhich documents win when sources disagree.contradictions:readgraph tier
  • get_contradiction_ruleOne authority rule.contradictions:readgraph tier
  • list_contradiction_checksQuestions checked for disagreements, and what each found.contradictions:readgraph tier
  • get_contradiction_checkOne targeted check and its issues.contradictions:readgraph tier
  • list_contradiction_topicsSaved questions, each with its last check.contradictions:readgraph tier
  • get_contradiction_topicOne saved topic and its last check.contradictions:readgraph tier

FAQ

Frequently asked

The integration questions, answered by someone who has read the code.

Get a key and POST a document.

The free tier is enough to evaluate the whole retrieval path end to end.

  • no card required
  • first workspace is free
  • one POST to ingest