Skip to content

API Reference

Complete reference for the Kanoniv REST API.

Quick Start

Install the Python SDK and create a client:

bash
pip install kanoniv[cloud]
python
from kanoniv.client import KanonivClient

client = KanonivClient(
    api_key="kn_...",
    base_url="https://api.kanoniv.com",
)

# Resolve an identity
result = client.resolve(system="Stripe", external_id="cus_123")
print(result["canonical_id"])

Base URL

https://api.kanoniv.com/v1

All API endpoints are prefixed with /v1.

Authentication

All API requests require an API key. Keys are prefixed with kn_ and scoped per tenant.

python
from kanoniv.client import KanonivClient

client = KanonivClient(api_key="kn_...", base_url="https://api.kanoniv.com")
bash
curl https://api.kanoniv.com/v1/entities \
  -H "X-API-Key: kn_..."

See Authentication for details on creating keys, scopes, and security best practices.

Response Format

All responses use a consistent envelope:

json
{
  "data": { ... },
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2026-02-05T10:00:00Z"
  }
}

Error responses:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid email format",
    "details": { "field": "email" }
  },
  "meta": {
    "request_id": "req_abc123"
  }
}

SDK Exception Mapping

The Python SDK maps HTTP status codes to typed exceptions:

python
from kanoniv import (
    KanonivError,        # Base -- catch all
    ValidationError,     # 400
    AuthenticationError, # 401
    ForbiddenError,      # 403
    NotFoundError,       # 404
    ConflictError,       # 409
    RateLimitError,      # 429
    ServerError,         # 5xx
)
ExceptionHTTP StatusDescription
ValidationError400Bad request body or query parameters
AuthenticationError401Invalid or missing credentials
ForbiddenError403Insufficient permissions or wrong role
NotFoundError404Resource does not exist
ConflictError409Resource conflict (e.g., duplicate name)
RateLimitError429Too many requests; respect Retry-After
ServerError5xxServer-side error; retry with backoff
python
try:
    entity = client.entities.get("nonexistent-uuid")
except NotFoundError:
    print("Entity not found")
except RateLimitError as e:
    print(f"Rate limited -- retry after {e.retry_after}s")
except KanonivError as e:
    print(f"API error {e.status_code}: {e}")

HTTP Status Codes

CodeMeaning
200Success
201Created
204No Content (successful delete)
400Bad Request (validation error)
401Unauthorized (invalid/missing auth)
403Forbidden (insufficient permissions)
404Not Found
409Conflict
429Rate Limited
500Internal Server Error

Rate Limits

TierLimit
Authenticated (per tenant)100 req/min
Unauthenticated (per IP)20 req/min

Rate limit headers are included on every response:

http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1707134400

When rate limited, the response includes a Retry-After header. The Python SDK respects this automatically with its built-in retry logic.

Endpoints

Auth

Resolution

Entities

Identity Specs

Reconciliation

Jobs

Observability

Preview

Rules

Sources

Overrides

Autodetect

Ingest

Feedback

Audit

Settings

Billing

Admin

The identity and delegation layer for AI agents.