Skip to main content
Developers

Knowledge Graph API

Query the entities and relationships extracted from your document corpus — people, organisations, projects, amounts, dates.

Knowledge Graph API

The Knowledge Graph is a derived layer: entities and relationships extracted automatically from your tenant's documents. The API exposes it for analytics, integrations, and custom dashboards.

Available under

/api/v1/knowledge-graph/* — requires the knowledge-graph:read scope (Business+ plans).

Querying entities

curl "https://yourtenant.papyrus.io/api/v1/knowledge-graph/entities?type=Organisation&limit=20" \
  -H "Authorization: Bearer $KEY" -H "X-Tenant-Id: $TENANT"

Response:

{
  "success": true,
  "data": {
    "entities": [
      {
        "id": "ent_acme_ltd",
        "type": "Organisation",
        "canonicalName": "Acme Ltd",
        "aliases": ["Acme Limited", "ACME LTD"],
        "metadata": {
          "kraPin": "P051234567A",
          "registeredAddress": "..."
        },
        "documentCount": 47,
        "firstSeen": "2024-08-12",
        "lastSeen": "2026-05-10"
      }
    ],
    "totalCount": 1247
  }
}

Entity types

Type Examples
Person Jane Doe, Counsel for X
Organisation Acme Ltd, KCB Bank
Project Project Orion, FY26 Q2 Rollout
Location Mombasa, Kibera
Amount KES 1,250,000
DateRange 2026-01-01 to 2026-06-30
Reference Tender 2026-001, Invoice INV-12345

Querying relationships

curl "https://yourtenant.papyrus.io/api/v1/knowledge-graph/relationships?\
fromEntityId=ent_acme_ltd&\
relationshipType=ContractParty" \
  -H "Authorization: Bearer $KEY" -H "X-Tenant-Id: $TENANT"

Response:

{
  "success": true,
  "data": {
    "relationships": [
      {
        "id": "rel_8a3b9c2d",
        "fromEntityId": "ent_acme_ltd",
        "toEntityId": "ent_contract_2025_q4_msa",
        "type": "ContractParty",
        "metadata": {
          "role": "Supplier",
          "effectiveDate": "2025-10-01"
        },
        "sourceDocuments": ["doc_abc123", "doc_def456"],
        "confidence": 0.96
      }
    ]
  }
}

Traversing the graph

# Get an entity and 1 hop of its relationships
curl "https://yourtenant.papyrus.io/api/v1/knowledge-graph/entities/ent_acme_ltd/neighbors?depth=1" \
  -H "Authorization: Bearer $KEY" -H "X-Tenant-Id: $TENANT"

For multi-hop traversal (depth > 2), expect higher latency. The API caps depth at 4 to prevent runaway queries.

Example: counterparty exposure

async function getCounterpartyExposure(counterpartyId: string) {
  const url = new URL(`/api/v1/knowledge-graph/entities/${counterpartyId}/relationships`,
                       'https://yourtenant.papyrus.io');
  url.searchParams.set('type', 'ContractParty');

  const res = await fetch(url, { headers });
  const { data } = await res.json();

  const contractIds = data.relationships.map(r => r.toEntityId);
  // Fetch contract documents
  const contracts = await Promise.all(contractIds.map(id =>
    fetch(`/api/v1/documents/${id}`, { headers }).then(r => r.json())
  ));

  return contracts.reduce((total, c) =>
    total + (c.data.extractedFields.totalValue || 0), 0);
}

Entity disambiguation

The graph automatically merges aliases. “Acme Ltd”, “Acme Limited”, and “ACME LTD” all resolve to ent_acme_ltd. The merging algorithm uses:

  • String similarity (Jaro-Winkler)
  • KRA PIN match (if available)
  • Document co-occurrence patterns

If you disagree with a merge, the Admin → Knowledge Graph UI lets you split or merge manually. Manual decisions stick across re-indexing.

Performance

  • Entity lookups: P50 25ms, P95 80ms
  • Relationship queries: P50 80ms, P95 250ms
  • Multi-hop traversal (depth 2): P50 200ms, P95 800ms
  • Multi-hop traversal (depth 4): P50 1.5s, P95 6s

RBAC

The graph is RBAC-aware. An API key with limited document scope sees entities and relationships only from documents within that scope. Cross-scope traversal is prevented at retrieval time.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.