The Valethon CRM API enables external websites, marketing platforms, and third-party tools to integrate with the CRM module. It provides lead capture, contact management, opportunity tracking, and embeddable chat widgets for MSP customer websites.
Base URL: https://{tenant}.valethon.com/admin/api/v1/crm
The CRM API uses API keys for authentication. Keys are managed in Settings → CRM → API Keys.
| Prefix | Type | Use Case |
|---|---|---|
pk_live_* | Public Key (Live) | Production chat widget embed |
pk_test_* | Public Key (Test) | Development/staging widget |
crm_* | Secret Key | Server-side API access (leads, contacts, opportunities) |
X-API-Key: crm_a1b2c3d4e5f6...
Public keys (pk_live_, pk_test_) are used client-side in the chat widget embed and only grant access to widget endpoints.
Secret keys (crm_*) are used server-side and grant access to all CRM API endpoints. Never expose secret keys in client-side code.
Keys are stored securely using password_hash() with only the prefix visible in the admin UI. Each key has:
leads:write, contacts:read)active, suspended, or revokedThe API enforces rate limits using a sliding window algorithm (60-second window).
| Key Type | Default Limit |
|---|---|
Public keys (pk_*) | 30 requests/minute |
Secret keys (crm_*) | 120 requests/minute |
Rate limit headers are included in every response:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1710350400
When exceeded, a 429 Too Many Requests response is returned with a Retry-After header.
All responses return JSON with consistent structure:
Success:
{
"success": true,
"data": { ... }
}
Error:
{
"success": false,
"error": "Description of the error",
"code": "VALIDATION_ERROR"
}
Paginated:
{
"success": true,
"data": [ ... ],
"pagination": {
"page": 1,
"per_page": 25,
"total": 150,
"total_pages": 6
}
}
| Code | HTTP Status | Meaning |
|---|---|---|
AUTH_REQUIRED | 401 | Missing or invalid API key |
FORBIDDEN | 403 | Key lacks required permission |
NOT_FOUND | 404 | Resource not found |
VALIDATION_ERROR | 400 | Invalid request data |
RATE_LIMITED | 429 | Rate limit exceeded |
DUPLICATE | 409 | Duplicate resource (e.g., email already exists) |
SERVER_ERROR | 500 | Internal server error |
Initialize a chat widget session. Used by the embeddable widget on MSP customer websites.
Authentication: Public key (pk_live_ or pk_test_)
Request:
{
"visitor_id": "v_abc123",
"page_url": "https://customer-site.com/support",
"referrer": "https://google.com"
}
Response (200):
{
"success": true,
"session_id": "ws_98765",
"greeting": "Hello! How can we help you today?",
"branding": {
"company_name": "Acme IT Solutions",
"primary_color": "#1FB6FF",
"logo_url": "https://cdn.valethon.com/logos/acme.png"
}
}
Send a message from the widget visitor.
Request:
{
"session_id": "ws_98765",
"message": "I need help with my email"
}
Response (200):
{
"success": true,
"response": {
"message": "I can help with email issues. Could you describe the problem?",
"suggested_actions": ["Create ticket", "Check service status"]
}
}
End a widget chat session.
Get service status for the widget display.
List leads with filtering and pagination.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | int | 1 | Page number |
| per_page | int | 25 | Items per page (max 100) |
| status | string | all | new, contacted, qualified, unqualified, converted, all |
| source | string | Filter by lead source | |
| assigned_to | int | Filter by assigned employee | |
| search | string | Search by name, email, or company | |
| created_after | string | ISO 8601 date filter | |
| created_before | string | ISO 8601 date filter | |
| sort | string | created_at | Sort field |
| order | string | desc | asc or desc |
Response (200):
{
"success": true,
"data": [
{
"lead_id": 42,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "+1-555-0123",
"company_name": "Acme Corp",
"status": "new",
"source": "website_form",
"score": 75,
"assigned_to": null,
"created_at": "2026-03-10T14:30:00Z",
"updated_at": "2026-03-10T14:30:00Z"
}
],
"pagination": { "page": 1, "per_page": 25, "total": 150, "total_pages": 6 }
}
Create a new lead.
Request:
{
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@company.com",
"phone": "+1-555-9876",
"company_name": "Globex Corp",
"source": "website_form",
"form_type": "contact_us",
"raw_payload": {
"role": "IT Director",
"technicianCount": "11-25",
"industry": "MSP",
"message": "Looking for a PSA solution"
}
}
Response (201):
{
"success": true,
"data": {
"lead_id": 43,
"status": "new",
"created_at": "2026-03-13T10:00:00Z"
}
}
Get lead details including activity history and linked entities.
Update lead fields (status, assignment, score, custom fields).
Delete a lead.
Convert a lead to a contact, prospect account, and optionally an opportunity.
Request:
{
"create_contact": true,
"create_prospect": true,
"create_opportunity": true,
"opportunity_name": "Acme Corp - Managed IT Services",
"opportunity_value": 50000
}
Response (200):
{
"success": true,
"data": {
"contact_id": 201,
"prospect_id": 55,
"opportunity_id": 78,
"lead_status": "converted"
}
}
Log an activity against a lead.
Get activity history for a lead.
List opportunities with filtering.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | int | Page number |
| per_page | int | Items per page |
| stage | string | Filter by pipeline stage |
| status | string | open, won, lost, all |
| assigned_to | int | Filter by owner |
| prospect_id | int | Filter by prospect account |
| min_value | number | Minimum deal value |
| max_value | number | Maximum deal value |
Create a new opportunity.
Request:
{
"name": "Acme Corp - Managed Services",
"prospect_id": 55,
"stage": "discovery",
"value": 50000,
"expected_close_date": "2026-06-30",
"probability": 30,
"assigned_to": 5
}
Get opportunity details with activities, notes, and linked entities.
Update opportunity fields.
Delete an opportunity.
Advance to the next pipeline stage.
List CRM contacts.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | int | Page number |
| per_page | int | Items per page |
| search | string | Search by name or email |
| prospect_id | int | Filter by linked prospect |
| tag | string | Filter by tag |
Create a new contact.
Get contact details.
Update contact fields.
Delete a contact.
List prospect accounts.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | int | Page number |
| per_page | int | Items per page |
| search | string | Search by account name |
| status | string | active, inactive, converted |
| industry | string | Filter by industry |
Create a new prospect account.
Get prospect details with linked contacts, opportunities, and activities.
Update prospect fields.
Delete a prospect account.
Convert a prospect to a full customer (creates a company record).
List activities across all CRM entities.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | int | Page number |
| per_page | int | Items per page |
| type | string | call, email, meeting, task, note |
| entity_type | string | lead, contact, opportunity, prospect |
| entity_id | int | Filter by specific entity |
| assigned_to | int | Filter by assignee |
| completed | boolean | Filter by completion status |
Create an activity.
Request:
{
"type": "call",
"subject": "Discovery call with Acme Corp",
"description": "Discuss current IT infrastructure and pain points",
"entity_type": "opportunity",
"entity_id": 78,
"assigned_to": 5,
"due_date": "2026-03-15T14:00:00Z",
"duration_minutes": 30
}
Get activity details.
Update activity (mark complete, reschedule, reassign).
Delete an activity.
Add a note to any CRM entity.
Request:
{
"entity_type": "lead",
"entity_id": 42,
"content": "Spoke with John. Interested in managed services for 50 endpoints.",
"is_pinned": false
}
List notes for an entity.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| entity_type | string | lead, contact, opportunity, prospect |
| entity_id | int | Entity ID |
| page | int | Page number |
Update a note.
Delete a note.
The CRM API can send webhook notifications when events occur.
List configured webhooks.
Register a new webhook.
Request:
{
"url": "https://your-app.com/webhooks/crm",
"events": ["lead.created", "lead.converted", "opportunity.won"],
"secret": "your_webhook_secret"
}
Remove a webhook registration.
| Event | Trigger |
|---|---|
lead.created | New lead created |
lead.updated | Lead fields updated |
lead.converted | Lead converted to contact/prospect |
lead.deleted | Lead deleted |
opportunity.created | New opportunity created |
opportunity.stage_changed | Opportunity moved to new stage |
opportunity.won | Opportunity marked as won |
opportunity.lost | Opportunity marked as lost |
contact.created | New contact created |
contact.updated | Contact fields updated |
prospect.created | New prospect account |
prospect.converted | Prospect converted to customer |
activity.completed | Activity marked as complete |
Webhook Payload:
{
"event": "lead.created",
"timestamp": "2026-03-13T10:00:00Z",
"data": {
"lead_id": 43,
"email": "jane@company.com",
"source": "website_form"
},
"signature": "sha256=a1b2c3..."
}
Verify webhook signatures using HMAC-SHA256 with your webhook secret.
List custom field definitions for a CRM entity type.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| entity_type | string | lead, contact, opportunity, prospect |
Create a new custom field definition.
Update a custom field definition.
Remove a custom field definition.
Search across all CRM entities.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| q | string | Search query |
| types | string | Comma-separated entity types to search |
| limit | int | Max results (default 20) |
Response (200):
{
"success": true,
"data": {
"results": [
{
"type": "lead",
"id": 42,
"title": "John Doe",
"subtitle": "Acme Corp",
"score": 0.95,
"url": "/crm/leads/42"
}
],
"total": 1
}
}
To embed the CRM chat widget on an MSP customer website:
<script>
window.ValethonWidget = {
publicKey: 'pk_live_xxxxxxxxxxxx',
position: 'bottom-right',
primaryColor: '#1FB6FF',
greeting: 'Need IT help? Chat with us!'
};
</script>
<script src="https://{tenant}.valethon.com/widget/chat.js" async></script>
| Option | Type | Default | Description |
|---|---|---|---|
publicKey | string | Required | Your public API key |
position | string | bottom-right | Widget position: bottom-right, bottom-left |
primaryColor | string | #1FB6FF | Widget accent color |
greeting | string | Hi! How can we help? | Initial greeting message |
showOnMobile | boolean | true | Display on mobile devices |
autoOpen | boolean | false | Auto-open after delay |
autoOpenDelay | number | 5000 | Auto-open delay in ms |
| Permission | Controls |
|---|---|
leads:read | View leads |
leads:write | Create and update leads |
leads:delete | Delete leads |
contacts:read | View contacts |
contacts:write | Create and update contacts |
opportunities:read | View opportunities |
opportunities:write | Create and update opportunities |
prospects:read | View prospect accounts |
prospects:write | Create and update prospects |
activities:read | View activities |
activities:write | Create and update activities |
webhooks:manage | Configure webhooks |
widget:access | Chat widget access (public keys) |
For the Helpdesk API, see Helpdesk API Reference.
For the ServiceOS admin API, see ServiceOS API Reference.