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.