Skip to content

Integration API Reference

import { Tabs, TabItem } from ‘@astrojs/starlight/components’;

Integration API overview

The Klarify Integration API provides read-only access to your organization’s process data, enabling you to integrate Klarify information into external systems, dashboards, and analytics tools. This API is designed for safe, secure data access without the ability to modify your organization’s content.

What the API enables

Data retrieval capabilities:

  • Access all procedures, processes, subprocesses, and tasks from your organization
  • Retrieve metadata including ownership, status, and modification dates
  • Export process information for business intelligence and reporting
  • Integrate with external workflow management and project tracking systems

Common integration scenarios:

  • Business intelligence dashboards showing process performance and compliance status
  • Project management tools that need current process information for planning
  • Training systems that reference current organizational procedures
  • Compliance monitoring tools that track process updates and versions

Read-only access to organizational data

Security and access control:

  • Read-only permissions prevent accidental modification of your process documentation
  • Organization-scoped access - API keys only access data from your organization
  • Secure authentication through access keys rather than username/password
  • Activity logging for all API access for audit and security monitoring

Data scope: The API provides access to all published content that would be visible to a user with appropriate permissions in your organization, including:

  • Process models and their associated metadata
  • Global task documentation and details
  • Organizational structure information relevant to processes
  • Process relationships and dependencies

Generating your access key

  1. Log into Klarify with administrator privileges
  2. Navigate to Settings from your profile menu
  3. Select Integrations from the settings sidebar
  4. Locate the API Key section on the integrations page

Click Generate key

Key generation process:

  1. Click “Generate Key” button in the API Key section
  2. Copy the generated key immediately - it’s displayed only once
  3. Store securely in your password manager or secure key storage system
  4. Test the key with a simple API call to verify functionality

Key characteristics:

  • Unique to your organization - Each organization has a distinct key
  • Long random string - Cryptographically secure and difficult to guess
  • No expiration - Keys remain valid until manually regenerated
  • Immediate activation - Keys are ready for use immediately after generation

Important: Key regeneration invalidates previous key

Critical security behavior: When you regenerate an API key, the previous key stops working immediately. This security feature ensures that if a key is compromised, regenerating it instantly revokes all access using the old key.

Before regenerating:

  • Identify all systems currently using the API key
  • Plan coordinated updates to minimize service disruption
  • Prepare update procedures for all integration points
  • Consider maintenance windows for key rotation

After regenerating:

  • Update all integrations with the new key as quickly as possible
  • Test all integration points to ensure they’re working with the new key
  • Monitor for errors from systems that might still be using the old key
  • Document the change for audit and maintenance records

API endpoint reference

Base URL: https://integration.klarify.biz

All API requests use this base URL with specific endpoints for different data types and operations.

Request format:

GET https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&additional_parameters

Response format: All responses are returned in JSON format with consistent structure for easy parsing and integration.

GET /api/procedures

Endpoint purpose: Returns a paginated list of all procedures, processes, subprocesses, and tasks in your organization. This is currently the primary endpoint for accessing Klarify data programmatically.

Endpoint URL:

GET https://integration.klarify.biz/api/procedures

Query parameters

access_key (required) - Your organization API key

Parameter details:

  • Type: String
  • Required: Yes
  • Description: The organization API key generated from Settings > Integrations
  • Security: Must be kept confidential and secure

Usage example:

?access_key=your-32-character-api-key-here

Error responses:

  • HTTP 404: “invalid access_key” - The provided key doesn’t exist or is inactive
  • HTTP 500: “missing required access_key” - The parameter wasn’t included in the request

page (optional) - Zero-based pagination, defaults to 0

Parameter details:

  • Type: Integer
  • Required: No
  • Default: 0
  • Description: Zero-based page number for pagination (0 = first page, 1 = second page, etc.)

Usage examples:

?page=0 # First page of results
?page=1 # Second page of results
?page=5 # Sixth page of results

Pagination logic:

  • Page 0 returns items 0 through (pageSize-1)
  • Page 1 returns items pageSize through (2*pageSize-1)
  • Continue until all items are retrieved

Parameter details:

  • Type: Integer
  • Required: No
  • Default: 100
  • Recommended maximum: 100
  • Description: Number of items to return per page

Usage examples:

?pageSize=25 # Small pages for quick response
?pageSize=50 # Medium pages for balanced performance
?pageSize=100 # Large pages for efficient bulk retrieval

Performance considerations:

  • Smaller page sizes (25-50) provide faster individual responses
  • Larger page sizes (up to 100) reduce total number of requests needed
  • Page sizes over 100 may cause timeouts and are not recommended
  • Very small pages (under 10) create unnecessary request overhead

sort (optional) - Format: ‘field,direction’ e.g. ‘updated_at,desc’

Parameter details:

  • Type: String
  • Required: No
  • Format: ‘field_name,direction’
  • Available directions: ‘asc’ (ascending), ‘desc’ (descending)

Sortable fields:

  • updated_at - When the item was last modified
  • name - Alphabetical sorting by item name
  • created_at - When the item was originally created
  • status - Current publication status

Usage examples:

?sort=updated_at,desc # Most recently updated first
?sort=name,asc # Alphabetical order A-Z
?sort=created_at,asc # Oldest items first
?sort=status,desc # Published items first

last_updated_at (optional) - ISO 8601 timestamp for incremental sync

Parameter details:

  • Type: String (ISO 8601 timestamp)
  • Required: No
  • Format: YYYY-MM-DDTHH:mm:ssZ
  • Description: Filter to only items modified after this timestamp

Incremental sync strategy:

# Initial sync - get all items
?pageSize=100
# Subsequent syncs - only get items modified since last sync
?last_updated_at=2024-01-15T10:30:00Z&pageSize=100

Usage examples:

?last_updated_at=2024-01-15T09:00:00Z # Items updated since 9 AM on Jan 15
?last_updated_at=2024-01-01T00:00:00Z # Items updated since start of year

Benefits of incremental sync:

  • Reduced bandwidth - Only transfer changed data
  • Faster processing - Fewer items to process per request
  • Efficient polling - Regular updates without full data transfer
  • Lower server load - Smaller requests put less load on both systems

Response structure

data array - List of procedure objects

The response contains a data array with procedure objects and additional metadata for pagination:

{
"data": [
{
"id": "12345",
"name": "Customer Onboarding Process",
"status": "published",
"owner": "John Smith",
"performer": "Customer Service Team",
"updated_at": "2024-01-15T14:30:00Z",
"url": "https://yourorg.klarify.me/process/12345",
"lanes": ["Customer Service", "Account Management"],
"called_within": [],
"called_from": ["Sales Pipeline Process"]
}
],
"hasNext": true,
"totalCount": 1247
}

hasNext boolean - Indicates more pages available

hasNext field:

  • true - More pages of data are available, continue pagination
  • false - This is the last page, no more data to retrieve

Pagination loop example:

let page = 0;
let hasNext = true;
while (hasNext) {
const response = await fetch(
`https://integration.klarify.biz/api/procedures?access_key=${key}&page=${page}&pageSize=100`
);
const data = await response.json();
// Process data.data array
processItems(data.data);
// Check if more pages exist
hasNext = data.hasNext;
page++;
}

Procedure object fields: id, name, status, owner, performer, updated_at, url, lanes, called_within, called_from

Field descriptions:

id (string): Unique identifier for the procedure

  • Example: “12345” or “proc_abc123def”
  • Use for tracking and referencing specific procedures
  • Stable across updates (doesn’t change when content is modified)

name (string): Display name of the procedure

  • Example: “Customer Onboarding Process”
  • Human-readable title shown in Klarify interface
  • May change when procedures are updated or renamed

status (string): Current publication state

  • Values: “published”, “draft”, “archived”
  • Only published items are typically included in API responses
  • Useful for filtering or conditional processing

owner (string): Person responsible for the procedure

  • Example: “John Smith” or “jane.doe@company.com
  • May be name or email depending on organization setup
  • Person with ultimate accountability for procedure accuracy

performer (string): Role or team that executes the procedure

  • Example: “Customer Service Team” or “Sales Representatives”
  • May be individual role or team name
  • Indicates who actually carries out the work described

lanes (array): Process roles involved in execution

  • Example: [“Customer Service”, “Account Management”, “IT Support”]
  • Represents different organizational roles or departments
  • Useful for understanding cross-functional processes

updated_at (string): ISO 8601 timestamp of last modification

  • Example: “2024-01-15T14:30:00Z”
  • Useful for incremental sync and change tracking
  • Updates when any aspect of the procedure changes

url (string): Direct link to view the procedure in Klarify

called_within (array): Procedures that include this one as a sub-process

  • Example: [“Master Sales Process”, “Customer Lifecycle”]
  • Shows where this procedure is referenced or embedded
  • Helps understand procedure relationships and dependencies

called_from (array): Related or prerequisite procedures

  • Example: [“Lead Qualification”, “Initial Contact Process”]
  • Shows procedures that typically happen before this one
  • Useful for understanding process flows and sequences

Example requests

Basic request with pagination

Simple data retrieval:

Terminal window
# Get first page of procedures
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&pageSize=50"
# Get specific page
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&page=2&pageSize=50"

Processing paginated results:

import requests
import json
def get_all_procedures(api_key):
base_url = "https://integration.klarify.biz/api/procedures"
all_procedures = []
page = 0
while True:
response = requests.get(base_url, params={
'access_key': api_key,
'page': page,
'pageSize': 100
})
if response.status_code == 200:
data = response.json()
all_procedures.extend(data['data'])
if not data.get('hasNext', False):
break
page += 1
else:
print(f"Error: {response.status_code} - {response.text}")
break
return all_procedures

Incremental sync using last_updated_at

Efficient ongoing synchronization:

Terminal window
# Initial sync - get all current procedures
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&pageSize=100&sort=updated_at,desc"
# Daily sync - only get items modified in last 24 hours
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&last_updated_at=2024-01-14T09:00:00Z&pageSize=100"

Incremental sync implementation:

class KlarifySync {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://integration.klarify.biz/api/procedures';
this.lastSyncTime = localStorage.getItem('lastKlarifySync') || '2024-01-01T00:00:00Z';
}
async syncUpdates() {
const params = new URLSearchParams({
access_key: this.apiKey,
last_updated_at: this.lastSyncTime,
pageSize: 100,
sort: 'updated_at,asc'
});
try {
const response = await fetch(`${this.baseUrl}?${params}`);
const data = await response.json();
if (data.data.length > 0) {
// Process updated procedures
this.processUpdatedProcedures(data.data);
// Update sync timestamp to most recent item
const latestUpdate = data.data[data.data.length - 1].updated_at;
this.lastSyncTime = latestUpdate;
localStorage.setItem('lastKlarifySync', this.lastSyncTime);
}
return data.data;
} catch (error) {
console.error('Sync failed:', error);
throw error;
}
}
}

Sorting by name or date

Different sorting approaches:

Terminal window
# Alphabetical sorting for directory-style displays
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&sort=name,asc&pageSize=50"
# Most recently updated procedures first
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&sort=updated_at,desc&pageSize=25"
# Oldest procedures for historical analysis
curl "https://integration.klarify.biz/api/procedures?access_key=YOUR_KEY&sort=created_at,asc&pageSize=100"

Error handling

404: Invalid access_key

Error response:

{
"error": "invalid access_key",
"message": "The provided access key does not exist or has been disabled"
}

Common causes and solutions:

  • Key regeneration: Access key was regenerated, invalidating the previous key
  • Typo in key: Verify the key is copied correctly without extra spaces
  • Wrong organization: Ensure you’re using the key for the correct Klarify organization
  • Key deactivation: Contact your administrator if key access has been revoked

500: Missing required access_key

Error response:

{
"error": "missing required access_key",
"message": "The access_key parameter is required for API authentication"
}

Resolution steps:

  • Check parameter name: Ensure parameter is named access_key exactly
  • Verify request format: Confirm parameter is included in query string or POST body
  • URL encoding: Make sure special characters in key are properly encoded
  • HTTP method: Verify you’re using GET request for the procedures endpoint

General error handling strategy

Robust error handling implementation:

import requests
import time
def safe_api_request(url, params, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.get(url, params=params, timeout=30)
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
raise ValueError("Invalid API key - check key and regenerate if necessary")
elif response.status_code == 500:
raise ValueError("Missing access_key parameter in request")
else:
print(f"Unexpected status code: {response.status_code}")
except requests.exceptions.Timeout:
print(f"Request timeout on attempt {attempt + 1}")
except requests.exceptions.ConnectionError:
print(f"Connection error on attempt {attempt + 1}")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
raise Exception("API request failed after all retry attempts")

Best practices

Keep pageSize at 100 or below to prevent timeouts

Performance optimization:

  • Page size 50-100: Optimal balance between request efficiency and response time
  • Page size 25-50: Better for real-time applications needing fast responses
  • Page size over 100: Risk of timeouts, especially for organizations with complex processes
  • Page size under 25: Creates unnecessary request overhead for bulk operations

Timeout prevention strategies:

// Adaptive page sizing based on response times
class AdaptiveApiClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.currentPageSize = 100;
this.minPageSize = 25;
this.maxPageSize = 100;
}
async fetchWithAdaptiveSize(page = 0) {
const startTime = Date.now();
try {
const response = await this.makeRequest(page, this.currentPageSize);
const responseTime = Date.now() - startTime;
// Adjust page size based on response time
if (responseTime > 10000 && this.currentPageSize > this.minPageSize) {
this.currentPageSize = Math.max(this.minPageSize, this.currentPageSize - 25);
} else if (responseTime < 3000 && this.currentPageSize < this.maxPageSize) {
this.currentPageSize = Math.min(this.maxPageSize, this.currentPageSize + 25);
}
return response;
} catch (error) {
// Reduce page size on timeout
if (error.name === 'TimeoutError' && this.currentPageSize > this.minPageSize) {
this.currentPageSize = Math.max(this.minPageSize, this.currentPageSize - 25);
}
throw error;
}
}
}

Use incremental sync for continuous updates

Efficient ongoing synchronization: Instead of fetching all data repeatedly, use the last_updated_at parameter to only retrieve items that have changed since your last sync.

import datetime
import json
class IncrementalSync:
def __init__(self, api_key, storage_file='sync_state.json'):
self.api_key = api_key
self.storage_file = storage_file
self.state = self.load_state()
def load_state(self):
try:
with open(self.storage_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
return {'last_sync': '2024-01-01T00:00:00Z', 'known_items': {}}
def save_state(self):
with open(self.storage_file, 'w') as f:
json.dump(self.state, f)
def sync_updates(self):
params = {
'access_key': self.api_key,
'last_updated_at': self.state['last_sync'],
'pageSize': 100,
'sort': 'updated_at,asc'
}
updated_items = []
page = 0
while True:
params['page'] = page
response = requests.get('https://integration.klarify.biz/api/procedures', params=params)
data = response.json()
for item in data['data']:
# Track changes for incremental processing
item_id = item['id']
if item_id in self.state['known_items']:
if self.state['known_items'][item_id] != item['updated_at']:
updated_items.append(('modified', item))
else:
updated_items.append(('new', item))
self.state['known_items'][item_id] = item['updated_at']
if not data.get('hasNext'):
break
page += 1
# Update last sync time
if updated_items:
self.state['last_sync'] = max(item[1]['updated_at'] for item in updated_items)
self.save_state()
return updated_items

Store access keys securely - never in version control

Security best practices:

Environment variables:

Terminal window
# Set environment variable
export KLARIFY_API_KEY="your-api-key-here"
# Use in application
import os
api_key = os.getenv('KLARIFY_API_KEY')

Configuration files (excluded from version control):

main.py
# config.py (add to .gitignore)
KLARIFY_API_KEY = "your-api-key-here"
from config import KLARIFY_API_KEY

Key management services:

# Using AWS Secrets Manager
import boto3
def get_api_key():
secrets_client = boto3.client('secretsmanager')
response = secrets_client.get_secret_value(SecretId='klarify-api-key')
return response['SecretString']

What NOT to do:

# ❌ NEVER DO THIS - API key in source code
api_key = "your-api-key-here" # Will be exposed in version control
# ❌ NEVER DO THIS - API key in committed config
config = {
"api_key": "your-api-key-here" # Visible to anyone with repo access
}
# ❌ NEVER DO THIS - API key in logs
print(f"Using API key: {api_key}") # Sensitive information in logs

Implement retry logic for network failures

Resilient API client implementation:

import requests
import time
import random
from typing import Optional, Dict, Any
class ResilientApiClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://integration.klarify.biz/api/procedures"
self.session = requests.Session()
def make_request(
self,
params: Dict[str, Any],
max_retries: int = 3,
base_delay: float = 1.0
) -> Optional[Dict]:
"""Make API request with exponential backoff retry logic"""
params['access_key'] = self.api_key
for attempt in range(max_retries + 1):
try:
response = self.session.get(
self.base_url,
params=params,
timeout=30
)
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
raise ValueError("Invalid API key")
elif response.status_code >= 500:
# Server error - retry
if attempt < max_retries:
continue
else:
raise Exception(f"Server error: {response.status_code}")
else:
# Client error - don't retry
raise Exception(f"Client error: {response.status_code}")
except requests.exceptions.Timeout:
print(f"Request timeout on attempt {attempt + 1}")
except requests.exceptions.ConnectionError:
print(f"Connection error on attempt {attempt + 1}")
except requests.exceptions.RequestException as e:
print(f"Request error on attempt {attempt + 1}: {e}")
if attempt < max_retries:
# Exponential backoff with jitter
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
print(f"Retrying in {delay:.1f} seconds...")
time.sleep(delay)
raise Exception("API request failed after all retry attempts")

Ready to explore advanced API usage? Contact our support team at support@klarify.me for assistance with complex integration scenarios or custom API requirements.