API Overview

Integrate with the Kantos REST API.

The Kantos API provides programmatic access to your CRM data. Build integrations, automate workflows, sync with external systems, and create custom applications using our RESTful API.

API-First Design

Everything you can do in the Kantos dashboard is also available via the API. This includes managing records, objects, automations, users, and more.

Base URL

All API requests are made to:

https://kantos.ai/api

Authentication

All API requests require authentication using an API key. Include your key in the X-Api-Key header with every request:

curl -X GET "https://kantos.ai/api/crm/records/query" \
  -H "X-Api-Key: sk_live_your_secret_key" \
  -H "Content-Type: application/json"

API Key Types

Key TypePrefixUse CasePermissions
Secret Keysk_live_Server-side integrationsFull read/write access
Publishable Keypk_live_Client-side form captureWrite-only to intake endpoint
Intake Keykantos_Smart Intake integrationWrite-only to ingest endpoint

Keep Secret Keys Secure

Secret keys (sk_live_...) provide full access to your CRM data. Never expose them in client-side code, public repositories, or browser requests. Use publishable keys for frontend integrations.

Creating API Keys

Step

Go to Settings → API Keys

Navigate to the API Keys section in your Kantos dashboard.

Step

Click "Create Key"

Choose the key type based on your use case.

Step

Name Your Key

Give it a descriptive name like "Production Server" or "Marketing Website".

Step

Copy and Store Securely

The full key is only shown once. Store it securely in environment variables.

Request Format

The API accepts JSON request bodies and returns JSON responses. Always include the appropriate headers:

curl -X POST "https://kantos.ai/api/crm/record" \
  -H "X-Api-Key: sk_live_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "object_id": "obj_contacts",
    "field_values": {
      "name": "John Doe",
      "email": "john@example.com"
    }
  }'

Response Format

Successful responses return the requested data directly. The response format varies by endpoint:

Single Record Response

{
  "id": "rec_abc123",
  "object_id": "obj_contacts",
  "field_values": {
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "+1 (555) 123-4567",
    "company": "rec_company_456"
  },
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "created_by": "user_789"
}

List Response (Paginated)

{
  "data": [
    { "id": "rec_abc123", ... },
    { "id": "rec_def456", ... }
  ],
  "pagination": {
    "total": 156,
    "page": 1,
    "per_page": 25,
    "total_pages": 7
  }
}

Error Handling

Errors return appropriate HTTP status codes with a JSON body describing the issue:

{
  "error": "Record not found",
  "code": "NOT_FOUND",
  "status": 404,
  "details": {
    "record_id": "rec_invalid123"
  }
}

Common Error Codes

StatusCodeDescription
400BAD_REQUESTInvalid request body or parameters
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENAPI key lacks required permissions
404NOT_FOUNDResource does not exist
409CONFLICTDuplicate record or constraint violation
422VALIDATION_ERRORField validation failed
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORServer error (contact support)

Records API

The Records API is the primary way to read and write CRM data.

Query Records

Retrieve records with optional filtering, sorting, and pagination:

GET /api/crm/records/query?object_id=obj_contacts&page=1&per_page=25

# With filters
GET /api/crm/records/query?object_id=obj_contacts&filters={"status":"active"}

# With sorting
GET /api/crm/records/query?object_id=obj_contacts&sort=created_at&order=desc

Query Parameters

ParameterTypeDescription
object_idstringRequired. The object to query
filtersJSONField filters (see Filter Syntax below)
sortstringField to sort by
orderstring"asc" or "desc" (default: "asc")
pagenumberPage number (default: 1)
per_pagenumberResults per page (default: 25, max: 100)

Filter Syntax

{
  // Exact match
  "status": "active",

  // Comparison operators
  "deal_value": { "$gte": 10000 },
  "created_at": { "$lt": "2024-01-01" },

  // Multiple conditions (AND)
  "status": "active",
  "source": "website",

  // Contains (text search)
  "name": { "$contains": "John" },

  // In array
  "category": { "$in": ["Enterprise", "SMB"] },

  // Is empty / not empty
  "phone": { "$empty": false }
}

Get Single Record

GET /api/crm/record/{record_id}

Create Record

POST /api/crm/record
Content-Type: application/json

{
  "object_id": "obj_contacts",
  "field_values": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "phone": "+1 (555) 987-6543",
    "status": "new",
    "source": "api"
  }
}

Update Record

PATCH /api/crm/record/{record_id}
Content-Type: application/json

{
  "field_values": {
    "status": "qualified",
    "notes": "Spoke on phone, interested in enterprise plan"
  }
}

Delete Record

DELETE /api/crm/record/{record_id}

Objects API

Manage your CRM schema programmatically.

List Objects

GET /api/crm/objects

# Response
{
  "data": [
    {
      "id": "obj_contacts",
      "name": "Contacts",
      "slug": "contacts",
      "icon": "user",
      "field_count": 12
    },
    {
      "id": "obj_companies",
      "name": "Companies",
      "slug": "companies",
      "icon": "building",
      "field_count": 8
    }
  ]
}

Get Object Schema

GET /api/crm/objects/{object_id}

# Response includes all fields
{
  "id": "obj_contacts",
  "name": "Contacts",
  "slug": "contacts",
  "fields": [
    {
      "id": "fld_name",
      "name": "Name",
      "slug": "name",
      "type": "text",
      "required": true
    },
    {
      "id": "fld_email",
      "name": "Email",
      "slug": "email",
      "type": "email",
      "required": true,
      "unique": true
    }
  ]
}

Create Object

POST /api/crm/objects
Content-Type: application/json

{
  "name": "Projects",
  "icon": "folder",
  "fields": [
    {
      "name": "Project Name",
      "type": "text",
      "required": true
    },
    {
      "name": "Status",
      "type": "status",
      "options": {
        "stages": ["Planning", "In Progress", "Review", "Complete"]
      }
    },
    {
      "name": "Budget",
      "type": "currency"
    }
  ]
}

Intake API

The Intake API receives form submissions from websites and external sources.

Ingest Endpoint

POST /api/ingest
X-Api-Key: kantos_your_intake_key
Content-Type: application/json

{
  "source": "website_contact_form",
  "fields": {
    "name": "John Doe",
    "email": "john@example.com",
    "message": "I'm interested in your services"
  },
  "metadata": {
    "page_url": "https://example.com/contact",
    "referrer": "https://google.com",
    "user_agent": "Mozilla/5.0..."
  }
}

Use Smart Intake

For website form capture, use the Smart Intake Universal Script which handles all the details automatically.

Webhooks

Configure webhooks to receive real-time notifications when records change.

Webhook Events

EventTriggered When
record.createdA new record is created
record.updatedA record is modified
record.deletedA record is deleted
intake.receivedA form submission is received

Webhook Payload

{
  "event": "record.created",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "id": "rec_abc123",
    "object_id": "obj_contacts",
    "field_values": {
      "name": "John Doe",
      "email": "john@example.com"
    }
  },
  "signature": "sha256=..."
}

Rate Limits

API requests are rate limited to ensure fair usage and platform stability.

PlanRequests/MinuteRequests/Day
Free10010,000
Pro1,000100,000
EnterpriseCustomCustom

Rate limit information is included in response headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1705312800

Exceeding Limits

When rate limited, you'll receive a 429 response. Implement exponential backoff in your integration to handle this gracefully.

SDKs & Libraries

Official and community SDKs make integration easier:

JavaScript / TypeScript

npm install @kantos/sdk
import { Kantos } from '@kantos/sdk';

const kantos = new Kantos({
  apiKey: process.env.KANTOS_API_KEY
});

// Create a contact
const contact = await kantos.records.create({
  objectId: 'obj_contacts',
  fieldValues: {
    name: 'John Doe',
    email: 'john@example.com'
  }
});

// Query records
const leads = await kantos.records.query({
  objectId: 'obj_contacts',
  filters: { status: 'new' },
  sort: 'created_at',
  order: 'desc'
});

Python

pip install kantos
from kantos import Kantos

client = Kantos(api_key=os.environ['KANTOS_API_KEY'])

# Create a contact
contact = client.records.create(
    object_id='obj_contacts',
    field_values={
        'name': 'John Doe',
        'email': 'john@example.com'
    }
)

# Query records
leads = client.records.query(
    object_id='obj_contacts',
    filters={'status': 'new'},
    sort='created_at',
    order='desc'
)

Best Practices

Security

  • Store API keys in environment variables, never in code
  • Use secret keys only on the server, publishable keys for client-side
  • Rotate keys periodically and after any suspected compromise
  • Use HTTPS for all API requests

Performance

  • Batch operations when possible to reduce API calls
  • Use pagination for large datasets
  • Cache responses where appropriate
  • Implement retry logic with exponential backoff

Error Handling

  • Always check response status codes
  • Log errors for debugging
  • Handle rate limits gracefully
  • Validate data before sending to the API

Next Steps

    API Reference | Kantos Docs