Skip to content

Rules & Identity Specs API

Manage matching rules and identity spec versions.

Overview

MethodEndpointUse Case
List rulesGET /v1/rulesGet all active matching rules
Create rulePOST /v1/rulesCreate a new rule version
Rule historyGET /v1/rules/:name/historyView all versions of a rule
List specsGET /v1/identity/specsList uploaded identity spec versions
Upload specPOST /v1/identity/specsValidate and compile a new spec
Get specGET /v1/identity/specs/:versionGet a specific spec version

GET /v1/rules

List all active matching rules for your tenant. Returns the latest active version of each rule.

Request

python
import httpx

resp = httpx.get("https://api.kanoniv.com/v1/rules",
    headers={"X-API-Key": "kn_..."})
rules = resp.json()

for rule in rules:
    print(f"{rule['name']}: type={rule['rule_type']}, weight={rule['weight']}, v{rule['version']}")
bash
curl "https://api.kanoniv.com/v1/rules" \
  -H "X-API-Key: kn_..."

Response

Returns an array of MatchRule objects:

json
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "tenant_id": "t_abc123",
    "name": "email_exact",
    "rule_type": "exact",
    "version": 3,
    "config": {
      "field": "email",
      "case_sensitive": false
    },
    "weight": 1.0,
    "is_active": true,
    "created_at": "2026-02-01T10:00:00Z",
    "created_by": "660e8400-e29b-41d4-a716-446655440001"
  },
  {
    "id": "550e8400-e29b-41d4-a716-446655440002",
    "tenant_id": "t_abc123",
    "name": "name_fuzzy",
    "rule_type": "similarity",
    "version": 1,
    "config": {
      "field": "name",
      "algorithm": "jaro_winkler",
      "threshold": 0.85
    },
    "weight": 0.6,
    "is_active": true,
    "created_at": "2026-01-10T08:00:00Z",
    "created_by": null
  }
]

Response Fields

FieldTypeDescription
idUUIDRule ID
tenant_idUUIDTenant this rule belongs to
namestringRule identifier
rule_typestringRule type (e.g. "exact", "similarity", "composite")
versionintegerVersion number (auto-incremented per rule name)
configobjectRule-specific configuration (free-form JSON)
weightfloatScoring weight (0.0--1.0)
is_activebooleanWhether this version is the active one
created_attimestampWhen this version was created
created_byUUIDUser ID who created it (null if created by system)

POST /v1/rules

Create a new rule or a new version of an existing rule. If a rule with the same name already exists, a new version is created. If is_active is true, all other versions of the same rule name are deactivated.

Request Body

FieldTypeRequiredDescription
namestringYesRule identifier (1--100 characters)
rule_typestringYesRule type (1--50 characters)
configobjectYesRule-specific configuration (free-form JSON)
weightfloatYesScoring weight (0.0--1.0)
is_activebooleanYesWhether this version should be active

Request

python
import httpx

# Create an exact email match rule
resp = httpx.post("https://api.kanoniv.com/v1/rules",
    headers={"X-API-Key": "kn_...", "Content-Type": "application/json"},
    json={
        "name": "email_exact",
        "rule_type": "exact",
        "config": {"field": "email", "case_sensitive": False},
        "weight": 1.0,
        "is_active": True
    })
rule = resp.json()
print(f"Created rule {rule['name']} v{rule['version']}")
bash
curl -X POST "https://api.kanoniv.com/v1/rules" \
  -H "X-API-Key: kn_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "email_exact",
    "rule_type": "exact",
    "config": {
      "field": "email",
      "case_sensitive": false
    },
    "weight": 1.0,
    "is_active": true
  }'

Response

Returns 201 Created with the new MatchRule:

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "tenant_id": "t_abc123",
  "name": "email_exact",
  "rule_type": "exact",
  "version": 1,
  "config": {
    "field": "email",
    "case_sensitive": false
  },
  "weight": 1.0,
  "is_active": true,
  "created_at": "2026-02-05T10:00:00Z",
  "created_by": "660e8400-e29b-41d4-a716-446655440001"
}

Validation

ConstraintError
name empty or > 100 charsRule name must be 1-100 characters
rule_type empty or > 50 charsRule type must be 1-50 characters
weight outside 0.0--1.0Weight must be between 0.0 and 1.0

GET /v1/rules/:name/history

View all versions of a rule, ordered by version number. Useful for auditing rule changes over time.

Path Parameters

ParameterTypeRequiredDescription
namestringYesRule name

Request

python
import httpx

resp = httpx.get("https://api.kanoniv.com/v1/rules/email_exact/history",
    headers={"X-API-Key": "kn_..."})
history = resp.json()

for version in history:
    status = "active" if version["is_active"] else "inactive"
    print(f"v{version['version']}: weight={version['weight']}, {status}")
bash
curl "https://api.kanoniv.com/v1/rules/email_exact/history" \
  -H "X-API-Key: kn_..."

Response

Returns an array of all MatchRule versions for the given name:

json
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440003",
    "tenant_id": "t_abc123",
    "name": "email_exact",
    "rule_type": "exact",
    "version": 3,
    "config": {
      "field": "email",
      "case_sensitive": false
    },
    "weight": 1.0,
    "is_active": true,
    "created_at": "2026-02-01T10:00:00Z",
    "created_by": "660e8400-e29b-41d4-a716-446655440001"
  },
  {
    "id": "550e8400-e29b-41d4-a716-446655440002",
    "tenant_id": "t_abc123",
    "name": "email_exact",
    "rule_type": "exact",
    "version": 2,
    "config": {
      "field": "email",
      "case_sensitive": true
    },
    "weight": 0.9,
    "is_active": false,
    "created_at": "2026-01-20T14:00:00Z",
    "created_by": "660e8400-e29b-41d4-a716-446655440001"
  }
]

GET /v1/identity/specs

List all uploaded identity spec versions for your tenant. Optionally filter by metadata tag.

Query Parameters

ParameterTypeRequiredDescription
tagstringNoFilter specs by metadata tag

Request

python
import httpx

resp = httpx.get("https://api.kanoniv.com/v1/identity/specs",
    headers={"X-API-Key": "kn_..."})
specs = resp.json()

for spec in specs:
    print(f"{spec['identity_version']} (hash: {spec['plan_hash'][:12]}...)")
bash
curl "https://api.kanoniv.com/v1/identity/specs" \
  -H "X-API-Key: kn_..."

# Filter by tag
curl "https://api.kanoniv.com/v1/identity/specs?tag=production" \
  -H "X-API-Key: kn_..."

Response

Returns an array of spec summaries:

json
[
  {
    "identity_version": "customer-v3",
    "plan_hash": "a1b2c3d4e5f6...",
    "created_at": "2026-02-01T10:00:00Z",
    "metadata": {
      "name": "Customer Identity Resolution",
      "description": "Production customer matching spec",
      "owner": "data-team",
      "tags": ["production", "customer"]
    }
  },
  {
    "identity_version": "customer-v2",
    "plan_hash": "f6e5d4c3b2a1...",
    "created_at": "2026-01-15T08:00:00Z",
    "metadata": null
  }
]

Response Fields

FieldTypeDescription
identity_versionstringVersion identifier from the spec YAML
plan_hashstringSHA-256 hash of the compiled plan
created_atstringISO 8601 timestamp
metadataobjectOptional metadata from the spec (null if not provided)
metadata.namestringSpec display name
metadata.descriptionstringHuman-readable description
metadata.ownerstringTeam or person responsible
metadata.tagsarrayTags for filtering and organization

POST /v1/identity/specs

Upload and validate an identity spec (YAML). Optionally compiles it to an execution plan and persists it.

Request Body

FieldTypeRequiredDefaultDescription
raw_yamlstringYesN/AThe identity spec as a YAML string (max 1 MB)
compilebooleanNofalseIf true, compile and persist the plan

Request

python
import httpx

spec_yaml = """
identity_version: customer-v3
entity: customer

sources:
  crm:
    adapter: postgres
    table: customers
  billing:
    adapter: postgres
    table: billing_accounts

rules:
  - exact:
      field: email
      weight: 1.0

decision:
  thresholds:
    match: 0.85
    review: 0.70

survivorship:
  default_strategy: most_recent
"""

resp = httpx.post("https://api.kanoniv.com/v1/identity/specs",
    headers={"X-API-Key": "kn_...", "Content-Type": "application/json"},
    json={"raw_yaml": spec_yaml, "compile": True})
result = resp.json()

if result["valid"]:
    print(f"Spec compiled! Hash: {result['plan_hash']}")
else:
    print(f"Errors: {result['errors']}")
bash
curl -X POST "https://api.kanoniv.com/v1/identity/specs" \
  -H "X-API-Key: kn_..." \
  -H "Content-Type: application/json" \
  -d '{
    "raw_yaml": "identity_version: customer-v3\nentity: customer\n...",
    "compile": true
  }'

Response

json
{
  "valid": true,
  "warnings": [
    "Source 'crm' has no freshness config -- staleness detection will be skipped"
  ],
  "errors": [],
  "plan_hash": "a1b2c3d4e5f6..."
}

Response Fields

FieldTypeDescription
validbooleanWhether the spec passed validation
warningsarrayNon-fatal validation warnings
errorsarrayValidation or tier-gating errors (empty if valid)
plan_hashstringSHA-256 hash of compiled plan (null if compile was false or validation failed)

Tier-Gated Features

Cloud-only features (exclusions, scoring, compliance, freshness, hierarchy, audit config) are validated against your tenant's tier. If your spec uses features above your tier, validation will fail with specific tier-gating errors.


GET /v1/identity/specs/:version

Get a specific spec version, including the raw YAML and compiled execution plan.

Path Parameters

ParameterTypeRequiredDescription
versionstringYesIdentity version string (e.g., "customer-v3")

Request

python
import httpx

resp = httpx.get("https://api.kanoniv.com/v1/identity/specs/customer-v3",
    headers={"X-API-Key": "kn_..."})
detail = resp.json()

print(f"Version: {detail['identity_version']}")
print(f"Hash: {detail['plan_hash']}")
print(f"Entity: {detail['compiled_plan']['entity']}")
print(f"Sources: {len(detail['compiled_plan']['sources'])}")
bash
curl "https://api.kanoniv.com/v1/identity/specs/customer-v3" \
  -H "X-API-Key: kn_..."

Response

json
{
  "identity_version": "customer-v3",
  "plan_hash": "a1b2c3d4e5f6...",
  "raw_yaml": "identity_version: customer-v3\nentity: customer\n...",
  "compiled_plan": {
    "entity": "customer",
    "plan_hash": "a1b2c3d4e5f6...",
    "identity_version": "customer-v3",
    "sources": [...],
    "blocking": {...},
    "match_graph": {...},
    "survivorship": {...},
    "decision": {...},
    "reference_identifiers": [...],
    "relations": [...]
  },
  "created_at": "2026-02-01T10:00:00Z",
  "metadata": {
    "name": "Customer Identity Resolution",
    "description": "Production customer matching spec",
    "owner": "data-team",
    "tags": ["production", "customer"]
  }
}

Response Fields

FieldTypeDescription
identity_versionstringVersion identifier
plan_hashstringSHA-256 hash of the compiled plan
raw_yamlstringOriginal YAML as uploaded
compiled_planobjectThe full compiled IdentityPlan (see Spec Reference)
created_atstringISO 8601 timestamp
metadataobjectOptional metadata (null if not present in the spec)

Returns 404 if the spec version does not exist for your tenant.

See Also

  • Rule Versioning — How rule versions work, testing before activating, rollback patterns
  • Spec Versioningidentity_version, plan_hash, and diffing specs

The identity and delegation layer for AI agents.