All CRM Lookup endpoints are workspace-scoped and require both the client and crm OAuth scopes. These endpoints are called by the CRM Middleware during PBX events (incoming calls, outgoing calls, chat sessions).
Headers: Authorization: Bearer {workspace-token}
The customer context is resolved automatically from the OAuth token.
GET /api/crm/lookup/contacts/search
Searches for contacts in the connected CRM by phone number or email address. Typically called during a screen-pop when a call rings on the PBX.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
phone |
string | yes* | Phone number to search for |
email |
string | yes* | Email address to search for |
display_name |
string | no | Caller display name — used by URL-builder integrations to construct the contact URL |
*At least one of phone or email is required.
Response 200
{
"contacts": [
{
"id": "crm-contact-uuid",
"first_name": "Alice",
"last_name": "Martin",
"email": "alice.martin@acme.com",
"phone_business_1": "+33142000000",
"phone_mobile_1": "+33612345678",
"company": "Acme Corp",
"entity_url": "https://crm.example.com/contacts/123"
}
]
}
If no match is found in the CRM, a dummy contact placeholder is returned so that 3CX can still trigger the call creation step.
POST /api/crm/lookup/contacts
Creates a new contact in the connected CRM.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
last_name |
string | yes | Last name |
first_name |
string | no | First name |
civility |
string | no | Civility / salutation |
email |
string | no | Email address |
phone |
string | no | Generic phone number |
phone_business |
string | no | Business phone number |
phone_mobile |
string | no | Mobile phone number |
custom_value |
string | no | Custom CRM field value |
call_direction |
string | no | Direction of the triggering call (inbound or outbound) |
Response 201
{
"response": "ok",
"contact": { ... }
}
Response 400 — the CRM connector could not create the contact.
GET /api/crm/lookup/phone-calls
Returns the list of phone calls from the connected CRM connector.
Query parameters
| Parameter | Description |
|---|---|
filter[direction] |
inbound, outbound, or internal |
filter[status] |
Call status |
filter[answered] |
Boolean — whether the call was answered |
filter[number_from] |
Caller number |
filter[number_to] |
Callee number |
filter[number_did] |
DID / ring group number |
filter[start_time] |
Call start time |
filter[end_time] |
Call end time |
filter[agent_email] |
Agent email address |
filter[subject] |
Call subject |
include |
Comma-separated relationships to sideload: segments, logs |
sort |
Sort field: start_time, end_time, created_at, updated_at. Prefix with - for descending |
per_page |
Results per page (default: 20) |
Response 200 — paginated list of call objects.
POST /api/crm/lookup/phone-calls
Records a completed phone call in the connected CRM. This is the primary endpoint called by the CRM Middleware when a call ends on the PBX.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
direction |
string | yes | inbound, outbound, or internal (case-insensitive) |
status |
string | yes | completed, failed, busy, no-answer, Missed, or Notanswered |
number_from |
string | yes* | Caller number |
number_to |
string | yes* | Callee number |
number_external |
string | yes** | External party number |
number_internal |
string | yes** | Internal extension number |
source |
string | no | PBX source identifier (e.g. 3cx) |
answered |
boolean | no | Whether the call was answered |
duration |
string/integer | no | Call duration |
start_time_utc |
string | no | Call start time in UTC — format: YYYY-MM-DDTHH:MM:SSZ |
end_time_utc |
string | no | Call end time in UTC — format: YYYY-MM-DDTHH:MM:SSZ |
subject |
string | no | Call subject |
body |
string | no | Call notes or transcript excerpt |
recording_url |
string | no | URL to the call recording |
agent_first_name |
string | no | Answering agent's first name |
agent_last_name |
string | no | Answering agent's last name |
agent_email |
string | no | Answering agent's email address |
queue_extension |
string | no | Queue or ring group extension |
*number_from and number_to are mutually required — provide both or neither.
**number_external and number_internal are mutually required — provide both or neither.
Response 201
{
"response": "success",
"message": "Call saved successfully.",
"call": { ... }
}
Response 400 — phone call logging is not enabled for this account.
POST /api/crm/lookup/phone-calls/context
Creates or updates a call context record during a live call. The context is used to pre-populate the CRM record so that when the call ends, the full entry can be enriched without relying solely on the final call payload.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
direction |
string | yes | inbound or outbound |
number_from |
string | yes (if inbound) | Caller number |
number_to |
string | yes (if outbound) | Callee number |
source |
string | no | PBX source identifier (e.g. 3cx) |
start_time_utc |
string | no | Call start time in UTC — format: YYYY-MM-DDTHH:MM:SSZ |
start_time_reference |
string | no | Which timestamp to use as the context anchor: call (default) or segment |
segment_dn_type |
string | no | DN type: extension, trunk, call_queue, voicemail, ivr, external_number, call_flow |
context_data |
array | no | Arbitrary key-value pairs to store alongside the context |
Response 201
{
"response": "success",
"message": "Call context saved successfully.",
"call_context_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Token-based variant
For scenarios where the CRM Middleware cannot use a standard OAuth token, a pre-issued context token can be used instead:
POST /api/crm/phone-calls-context/{token}/{tokenSecret}
This endpoint accepts the same request body and requires no Authorization header. The token (UUID) and tokenSecret are issued by CX-Engine and scoped to a specific customer.
POST /api/crm/lookup/chats
Records a completed chat session in the connected CRM. Called by the CRM Middleware when a chat session ends on the PBX.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes | Customer's email address |
source |
string | no | PBX source identifier (e.g. 3cx) |
number_external |
string | no | Customer's external number or identifier |
name |
string | no | Customer's display name |
start_time_utc |
string | no | Chat start time in UTC — format: YYYY-MM-DDTHH:MM:SSZ |
end_time_utc |
string | no | Chat end time in UTC — format: YYYY-MM-DDTHH:MM:SSZ |
duration |
string/integer | no | Chat duration |
subject |
string | no | Chat subject |
chat_messages |
string | no | Chat transcript or summary |
queue_extension |
string | no | Queue or ring group extension |
entity_type |
string | no | CRM entity type to link the chat to |
entity_id |
string | no | CRM entity ID to link the chat to |
agent |
string | no | Agent identifier |
agent_first_name |
string | no | Answering agent's first name |
agent_last_name |
string | no | Answering agent's last name |
agent_email |
string | no | Answering agent's email address |
Response 201
{
"response": "success",
"message": "Chat saved successfully.",
"chat": { ... }
}
Response 400 — chat logging is not enabled for this account.