This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/commerce/*.
CRM API
Customer relationship management for contacts, leads, engagement tracking, and sales pipeline.
All endpoints require a valid Bearer token. See Authentication for details.
Overview
| Attribute | Value |
|---|---|
| Base Path | /api/v1/crm |
| Authentication | Bearer Token |
| Required Roles | marketing, sales, manager, restaurant_manager, tenant_admin, platform_admin, system_admin, super_admin |
Contacts
List Contacts
Retrieve CRM contacts.
GET /api/v1/crm/contacts
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | active, inactive, lead, customer |
segment | string | Filter by segment |
source | string | Acquisition source |
search | string | Search name/email |
page | integer | Page number |
limit | integer | Results per page |
Response
{
"data": [
{
"id": "contact_001",
"type": "customer",
"name": "John Smith",
"email": "john@example.com",
"phone": "+1234567890",
"company": "Acme Corp",
"title": "Director of Operations",
"source": "website",
"status": "active",
"score": 85,
"tags": ["enterprise", "high_value"],
"custom_fields": {
"industry": "technology",
"company_size": "500+"
},
"engagement": {
"last_interaction": "2026-01-24T15:00:00Z",
"total_interactions": 45,
"lifetime_value": 12500.00
},
"owner": {
"id": "user_001",
"name": "Sales Rep Mike"
},
"created_at": "2025-06-01T00:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1250
}
}
Create Contact
POST /api/v1/crm/contacts
Request Body
{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+1234567890",
"company": "Tech Corp",
"title": "VP of Food Services",
"source": "referral",
"type": "lead",
"tags": ["enterprise"],
"custom_fields": {
"industry": "healthcare",
"locations": 25
},
"owner_id": "user_001",
"notes": "Interested in multi-location deployment"
}
Get Contact
GET /api/v1/crm/contacts/{contact_id}
Response
{
"id": "contact_001",
"type": "customer",
"name": "John Smith",
"email": "john@example.com",
"phone": "+1234567890",
"company": "Acme Corp",
"title": "Director of Operations",
"address": {
"street": "123 Business Ave",
"city": "San Francisco",
"state": "CA",
"zip": "94105"
},
"social": {
"linkedin": "https://linkedin.com/in/johnsmith",
"twitter": "@johnsmith"
},
"score": 85,
"score_breakdown": {
"engagement": 25,
"profile_completeness": 20,
"recent_activity": 25,
"fit_score": 15
},
"deals": [
{
"id": "deal_001",
"name": "Enterprise License",
"value": 50000.00,
"stage": "negotiation"
}
],
"activities": [
{
"type": "email_opened",
"timestamp": "2026-01-24T15:00:00Z",
"details": "Opened pricing email"
}
],
"notes": [
{
"id": "note_001",
"content": "Very interested in drive-thru voice AI",
"created_by": "user_001",
"created_at": "2026-01-20T10:00:00Z"
}
]
}
Update Contact
PUT /api/v1/crm/contacts/{contact_id}
Delete Contact
DELETE /api/v1/crm/contacts/{contact_id}
Merge Contacts
Merging contacts permanently combines records into the primary contact. The merged contacts are deleted and cannot be recovered. Review field preferences carefully before merging.
Merge duplicate contacts.
POST /api/v1/crm/contacts/merge
Request Body
{
"primary_contact_id": "contact_001",
"merge_contact_ids": ["contact_002", "contact_003"],
"field_preferences": {
"email": "contact_001",
"phone": "contact_002"
}
}
Lead Scoring
Get Lead Score
GET /api/v1/crm/contacts/{contact_id}/score
Response
{
"contact_id": "contact_001",
"total_score": 85,
"grade": "A",
"breakdown": {
"demographic": {
"score": 25,
"max": 30,
"factors": [
{"factor": "company_size", "score": 10, "reason": "500+ employees"},
{"factor": "industry", "score": 8, "reason": "Technology sector"},
{"factor": "title", "score": 7, "reason": "Director level"}
]
},
"behavioral": {
"score": 35,
"max": 40,
"factors": [
{"factor": "email_engagement", "score": 12, "reason": "High open rate"},
{"factor": "website_visits", "score": 10, "reason": "15 visits this month"},
{"factor": "content_downloads", "score": 8, "reason": "Downloaded pricing guide"},
{"factor": "demo_request", "score": 5, "reason": "Requested demo"}
]
},
"fit": {
"score": 25,
"max": 30,
"factors": [
{"factor": "budget", "score": 10, "reason": "Enterprise budget"},
{"factor": "need", "score": 8, "reason": "Active pain points"},
{"factor": "timeline", "score": 7, "reason": "Q1 decision"}
]
}
},
"recommendation": "Sales ready - schedule call",
"updated_at": "2026-01-24T19:00:00Z"
}
Configure Scoring Rules
PUT /api/v1/crm/scoring/rules
Request Body
{
"rules": [
{
"category": "demographic",
"field": "company_size",
"conditions": [
{"operator": "gte", "value": 500, "score": 10},
{"operator": "gte", "value": 100, "score": 7},
{"operator": "gte", "value": 50, "score": 5}
]
},
{
"category": "behavioral",
"event": "demo_request",
"score": 15
}
]
}
Data Enrichment
Enrich Contact
Enrich contact with external data.
POST /api/v1/crm/contacts/{contact_id}/enrich
Response
{
"contact_id": "contact_001",
"enrichment_status": "completed",
"data_added": {
"company": {
"employees": 850,
"revenue": "$50M-$100M",
"industry": "Technology",
"founded": 2010,
"website": "https://acmecorp.com"
},
"social": {
"linkedin": "https://linkedin.com/in/johnsmith",
"linkedin_connections": 500
},
"contact": {
"verified_email": true,
"phone_type": "mobile"
}
},
"confidence": 0.92,
"sources": ["clearbit", "linkedin", "email_verification"]
}
Bulk Enrich
POST /api/v1/crm/contacts/enrich/bulk
Request Body
{
"contact_ids": ["contact_001", "contact_002", "contact_003"],
"fields": ["company", "social", "email_verification"]
}
Deals & Pipeline
List Deals
GET /api/v1/crm/deals
Query Parameters
| Parameter | Type | Description |
|---|---|---|
stage | string | Filter by stage |
owner_id | string | Filter by owner |
min_value | number | Minimum deal value |
close_date | date | Expected close date |
Response
{
"data": [
{
"id": "deal_001",
"name": "Acme Corp Enterprise License",
"contact_id": "contact_001",
"company": "Acme Corp",
"value": 50000.00,
"currency": "USD",
"stage": "negotiation",
"probability": 60,
"expected_close": "2026-02-15",
"owner": {
"id": "user_001",
"name": "Sales Rep Mike"
},
"products": [
{"name": "Enterprise License", "quantity": 1, "value": 45000.00},
{"name": "Implementation", "quantity": 1, "value": 5000.00}
],
"created_at": "2026-01-10T00:00:00Z",
"updated_at": "2026-01-24T15:00:00Z"
}
],
"pipeline_summary": {
"total_value": 450000.00,
"weighted_value": 285000.00,
"deal_count": 25
}
}
Deal Stages
| Stage | Description |
|---|---|
lead | Initial lead |
qualified | Qualified opportunity |
proposal | Proposal sent |
negotiation | In negotiation |
closed_won | Deal won |
closed_lost | Deal lost |
Create Deal
POST /api/v1/crm/deals
Request Body
{
"name": "New Enterprise Deal",
"contact_id": "contact_001",
"value": 75000.00,
"stage": "qualified",
"expected_close": "2026-03-01",
"owner_id": "user_001",
"products": [
{"product_id": "prod_001", "quantity": 1}
],
"notes": "Multi-location deployment"
}
Update Deal Stage
PATCH /api/v1/crm/deals/{deal_id}/stage
Request Body
{
"stage": "proposal",
"notes": "Sent pricing proposal"
}
Get Pipeline Analytics
GET /api/v1/crm/pipeline/analytics
Response
{
"pipeline": {
"total_value": 450000.00,
"weighted_value": 285000.00,
"deal_count": 25,
"avg_deal_size": 18000.00
},
"by_stage": [
{"stage": "lead", "count": 8, "value": 120000.00},
{"stage": "qualified", "count": 6, "value": 90000.00},
{"stage": "proposal", "count": 5, "value": 100000.00},
{"stage": "negotiation", "count": 4, "value": 80000.00},
{"stage": "closed_won", "count": 2, "value": 60000.00}
],
"velocity": {
"avg_days_to_close": 45,
"avg_days_in_stage": {
"lead": 7,
"qualified": 10,
"proposal": 14,
"negotiation": 14
}
},
"forecast": {
"this_month": 85000.00,
"next_month": 125000.00,
"this_quarter": 350000.00
}
}
Activities
Log Activity
POST /api/v1/crm/activities
Request Body
{
"contact_id": "contact_001",
"deal_id": "deal_001",
"type": "call",
"subject": "Discovery Call",
"description": "Discussed pain points and requirements",
"outcome": "positive",
"duration_minutes": 30,
"next_steps": "Send proposal by Friday"
}
Activity Types
| Type | Description |
|---|---|
call | Phone call |
email | Email sent/received |
meeting | In-person meeting |
demo | Product demo |
note | General note |
task | Task completed |
List Activities
GET /api/v1/crm/activities
Query Parameters
| Parameter | Type | Description |
|---|---|---|
contact_id | string | Filter by contact |
deal_id | string | Filter by deal |
type | string | Activity type |
start_date | date | Period start |
end_date | date | Period end |
Tasks
Create Task
POST /api/v1/crm/tasks
Request Body
{
"title": "Follow up on proposal",
"description": "Check if they reviewed the pricing",
"contact_id": "contact_001",
"deal_id": "deal_001",
"due_date": "2026-01-26T10:00:00Z",
"priority": "high",
"assigned_to": "user_001"
}
List Tasks
GET /api/v1/crm/tasks
Query Parameters
| Parameter | Type | Description |
|---|---|---|
assigned_to | string | Filter by assignee |
status | string | pending, completed, overdue |
priority | string | low, medium, high |
Complete Task
POST /api/v1/crm/tasks/{task_id}/complete
Bulk Operations
Bulk Update
POST /api/v1/crm/contacts/bulk-update
Request Body
{
"contact_ids": ["contact_001", "contact_002"],
"updates": {
"owner_id": "user_002",
"tags": {"add": ["enterprise"], "remove": ["small_business"]}
}
}
Bulk Import
POST /api/v1/crm/contacts/import
Request Body (multipart/form-data)
file: contacts.csv
mapping: {"name": "Full Name", "email": "Email Address"}
options: {"skip_duplicates": true, "source": "csv_import"}
Webhooks
| Event | Description |
|---|---|
crm.contact_created | New contact added |
crm.contact_updated | Contact modified |
crm.deal_created | New deal created |
crm.deal_stage_changed | Deal moved stages |
crm.deal_won | Deal closed won |
crm.deal_lost | Deal closed lost |
crm.task_due | Task due soon |
crm.score_changed | Lead score updated |
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | duplicate_contact | Contact already exists |
| 400 | invalid_stage | Invalid deal stage |
| 404 | contact_not_found | Contact ID not found |
| 404 | deal_not_found | Deal ID not found |
| 409 | merge_conflict | Cannot merge contacts |
Related Documentation
- CRM Guide - CRM setup guide
- Lead Scoring - Scoring configuration
- Marketing API - Marketing integration