CRM API
API endpoints for the CRM module. All endpoints require JWT authentication via the token_admin strategy.
Authentication
All endpoints require a valid admin JWT token:
Authorization: Bearer <token>Permission-based access is enforced per endpoint (see the Auth column in each table).
Prospects
Listing & Queries
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /prospects/grouped | Prospects grouped by follow-up category (Kanban) | Permission 319 |
| GET | /prospects/list | Paginated prospect list with sorting and filters | Permission 319 |
| GET | /prospects/activities | Follow-up activities in a date range (Calendar) | Permission 319 |
| GET | /prospects/kpis | KPI aggregates per follow-up category | Permission 319 |
| GET | /prospects/{id} | Single prospect with notes, contacts, locations | Permission 319 |
CRUD Operations
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /prospects/process | Validate and deduplicate prospects (no DB write) | token_admin |
| POST | /prospects | Create prospects (batch) | token_admin |
| PATCH | /prospects/{id} | Update prospect fields (name, email, phone, etc.) | token_admin |
| PATCH | /prospects/{id}/data | Update follow-up data (channel, account value, etc.) | Permission 319 |
| PATCH | /prospects/{id}/partner-data | Update partner prospect data (URL, rating, etc.) | crm-partners |
Contacts
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /prospects/{id}/contacts | Add contact for a prospect | Permission 319 |
| PUT | /prospects/{id}/contacts | Update contact (or default prospect contact) | Permission 319 |
| DELETE | /prospects/{id}/contacts | Delete contact by ID | Permission 319 |
Notes
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /prospects/{id}/notes | Add follow-up note | Permission 319 |
| PATCH | /prospects/{id}/notes/{noteId} | Update note scheduled date | Permission 319 |
Locations
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /prospects/{id}/locations | Create location for a prospect | crm-menu |
| PUT | /prospects/locations/{id} | Update location | crm-menu |
| DELETE | /prospects/locations/{id} | Delete location | crm-menu |
Clients
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /clients/{id} | Client details with contacts, notes, integrations, locations | Permission 319 |
| GET | /clients/{id}/onboarding | Client onboarding data | Permission 319 |
| POST | /clients/{id}/contacts | Add contact for a client | Permission 319 |
| POST | /clients/{id}/notes | Add follow-up note for a client | Permission 319 |
| PATCH | /clients/{id}/data | Update client follow-up data | Permission 319 |
| POST | /clients/{id}/locations | Create location for a client | crm-menu |
| PUT | /clients/locations/{id} | Update client location | crm-menu |
| DELETE | /clients/locations/{id} | Delete client location | crm-menu |
Endpoint Details
GET /prospects/grouped
Returns prospects grouped by follow-up category for the Kanban board. Supports pagination per group and extensive filters.
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
start | number | No | Offset for pagination |
length | number | No | Page size |
sortBy | string | No | Sort field |
sortType | string | No | Sort direction |
category | number | No | Filter by specific follow-up category |
search | string | No | Free-text search (company name, contact name) |
follow | string | No | Filter by follow-up status ID(s) |
type | string | No | Filter by prospect type |
onboarding | string | No | Filter by onboarding status |
ecommerce | string | No | Filter by ecommerce type |
campaing | string | No | Filter by campaign |
salesman | string | No | Filter by assigned salesman (requires all-prospects) |
startDate | string | No | Date range start (requires all-prospects) |
endDate | string | No | Date range end (requires all-prospects) |
kae | string | No | Filter by KAE assignment |
kae_ltl | string | No | Filter by KAE LTL assignment |
csr | string | No | Filter by CSR assignment |
csr_ltl | string | No | Filter by CSR LTL assignment |
fullfilment | string | No | Filter by Fulfillment assignment |
wms | string | No | Filter by WMS assignment |
ecartpay | string | No | Filter by Ecartpay assignment |
parapaquetes | string | No | Filter by Parapaquetes assignment |
source | string | No | company (default) or partner |
counters | boolean | No | Include record counts per category |
report | boolean | No | Report mode flag |
Response (200):
{
"categories": [
{
"id": 1,
"name": "new_lead",
"records": [
{
"id": 42,
"company_name": "Acme Corp",
"name": "John Doe",
"email": "john@acme.com",
"follow_up_id": 1,
"follow_name": "new_lead",
"balance": 0,
"account_value": 5000,
"last_contact": "2026-03-15T10:30:00Z",
"salesman_name": "Maria Garcia",
"verified": true,
"tier": "gold",
"monthly_shipments": 150,
"services": [1, 3, 5]
}
],
"count": 23
}
]
}GET /prospects/list
Returns a paginated, sortable list of prospects for the data table view.
Query Parameters:
All parameters from /prospects/grouped plus:
| Param | Type | Required | Description |
|---|---|---|---|
start | number | No | Offset (default: 0) |
length | number | No | Page size (default: 25) |
sortBy | string | No | Column to sort by |
sortType | string | No | asc or desc |
weightRange | string | No | Filter by weight range |
contentId | string | No | Filter by content type |
planTypeId | string | No | Filter by plan type |
minShipments | number | No | Minimum monthly shipments |
leadStatus | string | No | Filter by lead status |
nextContact[0] | string | No | Next contact date range start |
nextContact[1] | string | No | Next contact date range end |
estimatedCloseDate[0] | string | No | Estimated close date range start |
estimatedCloseDate[1] | string | No | Estimated close date range end |
estimatedCloseMonth | string | No | Filter by estimated close month |
commercialOfferDate[0] | string | No | Commercial offer date range start |
commercialOfferDate[1] | string | No | Commercial offer date range end |
hasRecharge | string | No | 0 or 1 — filter by recharge status |
Response (200):
{
"recordsTotal": 1250,
"recordsFiltered": 89,
"data": [
{
"id": 42,
"company_name": "Acme Corp",
"follow_name": "contacted",
"salesman_name": "Maria Garcia",
"balance": 15000.00,
"account_value": 5000,
"first_contact": "2026-01-15",
"last_contact": "2026-03-10",
"days_uc": 5,
"days_without_contact": 9,
"next_contact": "2026-03-20",
"monthly_shipments_desc": "100-500",
"campaign": "Q1-2026",
"lead_status": "qualified",
"estimated_close_date": "2026-04-15"
}
]
}GET /prospects/activities
Returns follow-up activities within a date range for the calendar view.
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
startDate | string | Yes | Date range start |
endDate | string | Yes | Date range end |
search | string | No | Free-text search |
follow | string | No | Filter by follow-up status |
type | string | No | Filter by prospect type |
onboarding | string | No | Filter by onboarding status |
ecommerce | string | No | Filter by ecommerce type |
campaing | string | No | Filter by campaign |
salesman | string | No | Filter by assigned salesman |
kae ... parapaquetes | string | No | Role-based filters |
Response (200):
[
{
"id": 101,
"entity_name": "Acme Corp",
"entity_type": "prospect",
"entity_id": 42,
"action": "call",
"comment": "Discussed pricing options",
"scheduled_date": "2026-03-15T09:00:00Z",
"created_by_name": "Maria Garcia",
"follow_name": "negotiation"
}
]GET /prospects/kpis
Returns KPI aggregates (e.g., total account value) per follow-up category.
Query Parameters: Same filters as /prospects/grouped (excluding pagination).
Response (200):
[
{
"category_id": 1,
"category_name": "new_lead",
"total_value": 125000,
"count": 23
}
]GET /prospects/{id}
Returns full prospect details including notes, contacts, and locations.
Path Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
id | number | Yes | Prospect ID |
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
source | string | No | company (default) or partner |
Response (200):
{
"prospect": {
"id": 42,
"name": "John Doe",
"company_name": "Acme Corp",
"email": "john@acme.com",
"phone_code": "52",
"phone": "5551234567",
"company_id": null,
"follow_up_id": 3,
"locale_id": 1,
"type": 1,
"status": 1,
"created_by": 10,
"created_at": "2026-01-15T08:00:00Z"
},
"follow_data": {
"channel": "website",
"account_value": 5000,
"monthly_shipments": 150,
"ecommerce_type_id": 2,
"account_type": "sme",
"estimated_close_date": "2026-04-15"
},
"notes": [],
"contacts": [],
"locations": []
}POST /prospects/process
Validates and deduplicates a batch of prospects without writing to the database. Used as a preview step during CSV import.
Request:
[
{
"name": "John Doe",
"company": "Acme Corp",
"email": "john@acme.com",
"phone": 5551234567,
"code": 52,
"locale": 1
}
]Response (200):
{
"inserts": [
{
"name": "John Doe",
"company": "Acme Corp",
"email": "john@acme.com",
"phone": 5551234567,
"code": 52,
"locale": 1
}
],
"updates": [],
"errors": [
{
"email": "duplicate@example.com",
"code": "DUPLICATE_EMAIL",
"existing_id": 99
}
]
}POST /prospects
Creates prospects in batch from validated data. Triggers Respondio integration for new leads.
Request:
[
{
"name": "John Doe",
"company": "Acme Corp",
"email": "john@acme.com",
"phone": 5551234567,
"code": 52,
"locale": 1,
"type": 1,
"monthly_shipments": 150,
"follow_up_id": 1
}
]| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Contact name |
company | string | No | Company name |
email | string | No | Email address |
phone | number | No | Phone number |
code | number | No | Phone country code |
locale | number | No | Locale/country ID |
type | number | No | 1 = prospect (default), 2 = client, 3 = partner |
monthly_shipments | string/number | No | Estimated monthly shipments |
follow_up_id | number | No | Initial follow-up status |
Response (200):
{
"inserts": [
{ "id": 42, "email": "john@acme.com" }
],
"errors": []
}POST /prospects/{id}/notes
Creates a follow-up note for a prospect or client, optionally updating the follow-up status.
Request:
{
"follow": 3,
"action": "call",
"note": "Discussed pricing options. Client interested in enterprise plan.",
"scheduled_date": "2026-03-20T09:00:00Z"
}| Field | Type | Required | Description |
|---|---|---|---|
follow | number | No | New follow-up status ID (updates current status) |
action | string | No | Action type: call, whatsapp, email, meeting, sms, other |
note | string | Yes | Note content |
scheduled_date | ISO date | No | Scheduled follow-up date/time |
PATCH /prospects/{id}/notes/{noteId}
Updates the scheduled date of an existing note.
Request:
{
"scheduled_date": "2026-03-25T14:00:00Z",
"origin": "prospect"
}| Field | Type | Required | Description |
|---|---|---|---|
scheduled_date | ISO date | Yes | New scheduled date (null to remove) |
origin | string | Yes | prospect or company |
PATCH /prospects/{id}/data
Updates follow-up metadata for a prospect.
Request:
{
"channel": "referral",
"account_value": 8000,
"monthly_shipments": 200,
"ecommerce_type_id": 3,
"weight_id": 2,
"content_id": 1,
"account_type": "enterprise",
"estimated_close_date": "2026-05-01",
"annotations": "High-priority account, needs custom pricing."
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Display name |
ecommerce_type_id | number | No | E-commerce platform type |
channel | string | No | Acquisition channel |
account_value | number | No | Estimated account value |
locale | number | No | Locale ID |
monthly_shipments | number | No | Monthly shipment estimate |
weight_id | number | No | Weight range category |
content_id | number | No | Content type |
annotations | string | No | Free-text annotations |
account_type | string | No | individual, startup, sme, enterprise, corporate |
estimated_close_date | ISO date | No | Expected close date |
PATCH /prospects/{id}
Updates core prospect fields.
Request:
{
"company_name": "Acme Corporation",
"name": "John Doe",
"email": "john.doe@acme.com",
"phone_code": "52",
"phone": "5559876543",
"created_by": 15
}| Field | Type | Required | Description |
|---|---|---|---|
company_name | string | No | Company name |
name | string | No | Contact name |
email | string | No | Email (validated) |
phone_code | string | No | Country phone code |
phone | string | No | Phone number |
created_by | number | No | Reassign to another admin |
PATCH /prospects/{id}/partner-data
Updates partner-specific data for type-3 prospects. Requires crm-partners permission.
Request:
{
"url": "https://partner-store.com",
"partner_type_id": 2,
"partner_origin_id": 1,
"rating": 4,
"locale_id": 1,
"social_network": "@partnerstore"
}| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Partner website URL |
partner_type_id | number | Yes | Partner type |
partner_origin_id | number | Yes | Partner origin |
rating | number | Yes | Rating 1-5 |
locale_id | number | Yes | Locale ID |
social_network | string | No | Social media handle (max 150 chars) |
POST /prospects/{id}/contacts
Adds a new contact to a prospect.
Request:
{
"name": "Jane Smith",
"email": "jane@acme.com",
"phone_code": "52",
"phone": "5559876543",
"position": "CTO"
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Contact name |
email | string | Yes | Contact email |
phone_code | string | Yes | Country phone code |
phone | string | Yes | Phone number |
position | string | No | Job title/position |
PUT /prospects/{id}/contacts
Updates an existing contact. If isDefault is true, updates the primary prospect record instead of extra_contacts.
Request:
{
"name": "Jane Smith",
"email": "jane.smith@acme.com",
"phone_code": "52",
"phone": "5559876543",
"position": "VP Engineering",
"isDefault": false
}DELETE /prospects/{id}/contacts
Deletes a contact from extra_contacts. The {id} path parameter refers to the contact ID.
POST /prospects/{id}/locations
Creates a location for a prospect. Requires crm-menu permission.
Request:
{
"name": "Main Office",
"link": "https://maps.google.com/?q=...",
"type": "headquarters"
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Location name (max 50 chars) |
link | string | Yes | Map URL (max 150 chars) |
type | string | Yes | office, warehouse, branch, headquarters, distribution_center |
PUT /prospects/locations/{id}
Updates an existing location. Same fields as POST, all optional.
DELETE /prospects/locations/{id}
Deletes a location by ID.
Client Endpoints
GET /clients/{id}
Returns full client details by company ID, including contacts, notes, integrations, locations, and onboarding data.
Path Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
id | number | Yes | Company ID |
Response (200):
{
"company": {
"id": 100,
"company_name": "Acme Corp",
"balance": 15000.00,
"follow_up_id": 5,
"follow_name": "active_client"
},
"follow_data": {},
"notes": [],
"contacts": [],
"locations": [],
"integrations": [],
"onboarding": {}
}GET /clients/{id}/onboarding
Returns onboarding data for a client.
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
translate | boolean | No | Translate onboarding keys (default: false) |
POST /clients/{id}/contacts
Same payload as POST /prospects/{id}/contacts.
POST /clients/{id}/notes
Same payload as POST /prospects/{id}/notes.
PATCH /clients/{id}/data
Same payload as PATCH /prospects/{id}/data.
POST /clients/{id}/locations
Same payload as POST /prospects/{id}/locations. Requires crm-menu permission.
PUT /clients/locations/{id}
Same payload as PUT /prospects/locations/{id}. Requires crm-menu permission.
DELETE /clients/locations/{id}
Deletes a client location by ID. Requires crm-menu permission.
Common Error Responses
All errors follow the Boom format:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Descriptive error message"
}| Status | When |
|---|---|
| 400 | Validation failed (Joi schema) |
| 401 | Missing or invalid JWT |
| 403 | Insufficient permissions for the action |
| 404 | Prospect, client, contact, or location not found |
| 409 | Duplicate email/phone detected during creation |
| 422 | Malformed request data (Boom badData) |
Validation Notes
- Email uniqueness is checked on contact update (
PUT /prospects/{id}/contacts) against bothprospection_usersanduserstables. - Phone numbers are validated as numeric values during prospect creation.
- Location types are restricted to:
office,warehouse,branch,headquarters,distribution_center. - Partner data rating must be an integer between 1 and 5.
- The
sourcequery parameter on listing endpoints defaults tocompanyand can be set topartnerfor partner-type prospects.
