From contact management to message sending, from tickets to live chat: every endpoint and sample body for connecting Cxperium to your own systems.
All requests go to https://api.cxperium.com under the /api/… path over HTTPS. Add the apikey header carrying your API key to every request.
curl https://api.cxperium.com/api/contacts?page=1&limit=10 \
-H "apikey: $CX_API_KEY"
An invalid, missing or plan-ineligible key returns 401:
{ "error": "Invalid API key!" }
Request and response formats are the same across all endpoints. Bodies are JSON (Content-Type: application/json); the one exception is ticket creation with attachments (multipart/form-data).
# Successful request (200 / 201)
{ "status": 201, "success": true, "message": "OK", "data": { … } }
# Validation error (400) — which field was rejected and why is in error/message
{ "status": 400, "success": false, "error": "MEDIA_NOT_SUPPORTED_ON_CHANNEL", "message": "…" }
# Rate limit (429)
{ "error": "Too many requests, please slow down." }
| Topic | Rule |
|---|---|
| Pagination | List endpoints take the page (starting at 1) and limit query parameters. Default order is createdAt descending; you can pass JSON to sort: sort={"createdAt":-1}. |
| Filtering | The filter parameter is URL-encoded JSON: filter={"phone":"9055"}. Text fields match case-insensitively as "contains"; the tags field can be given as an array. |
| Identifiers | All _id values are 24-character hexadecimal strings. |
| Phone numbers | With country code, without plus sign or spaces: 905551112233. |
| Dates | ISO 8601, UTC. Export endpoints take date_type (TODAY, THIS_WEEK, THIS_MONTH, THIS_YEAR) or start / end (YYYY-MM-DD). |
| Rate limit | 100 requests per minute per IP. Beyond it 429; the remaining quota can be read from the RateLimit response headers. |
| Body size | Up to 10 MB on endpoints that carry media. |
| Language | The optional language header (TR, EN …) sets the language of response messages. |
A contact is unique: the phone number is the identity. A second create request with the same number does not open a new record; it updates the existing one.
| Endpoint | Description |
|---|---|
GET/api/contacts | Paginated, filtered list, e.g. filter={"userProfileName":"Jane"}. |
GET/api/contacts/phone/:phone | One contact by phone. |
GET/api/contacts/:id | One contact by id. |
POST/api/contacts | Create a contact (update if it exists). Body below. |
POST/api/contacts/bulk | Bulk create: { "data": [ {…}, {…} ], "uniqueData": "phone" }. With uniqueData, existing records with the same value are not recreated. |
PUT/api/contacts/:id | Update; send only the changed fields (phone, userProfileName, email, language, tags, custom). |
PUT/api/contacts | Bulk tag assignment: { "contact_ids": ["…"], "tags": ["…"] }. |
PUT/api/contacts/delete/:id | Delete a contact. |
PUT/api/contacts/delete-many | Bulk delete by condition: { "condition": [ { "column": "phone", "operation": "EQUAL", "value": "9055…" } ] }. operation: EQUAL, NOT_EQUAL, CONTAINS. |
PATCH/api/contacts/anonymize/:phone | Anonymise a contact (for "right to be forgotten" requests). |
{
"phone": "905551112233", // required
"userProfileName": "Jane Doe", // required — the name shown in the dashboard
"email": "jane@example.com",
"language": "EN",
"tags": ["66201122334455667788990a"],
"custom": { "customerNo": "C-4821", "segment": "vip" } // free custom fields; new keys become columns in the dashboard
}
Contact tags and ticket tags are separate lists.
| Endpoint | Description |
|---|---|
GET/api/tags | Paginated list of contact tags. |
POST/api/tags | Create a contact tag: { "name": "VIP", "color": "#ff0f30" }. |
GET/api/ticket/tags | List ticket tags. |
POST/api/ticket/tag | Create a ticket tag. |
The WhatsApp rule: if the customer wrote to you within the last 24 hours you can send free-form messages; otherwise you can only reach them with a Meta-approved template. The endpoints are split along these two cases.
| Endpoint | Description |
|---|---|
POST/api/send-message | Free-form message to a contact with an open session. type: TEXT, IMAGE, DOCUMENT, VIDEO. Give media as link (URL) or media (Base64) + file_name. |
POST/api/notification/send-single | Notification with an approved template to one contact (no session window needed). Body in Notifications. |
POST/api/message/one-person | Survey invitation to one contact: { "name": "…", "survey_id": "…", "phone": "9055…", "tags": [] }. |
POST/api/message/bulk | Creates a sending group from contacts matching a condition (does not send yet): { "name", "survey_id", "condition": [ { "column", "operation", "value" } ] }. |
POST/api/message/send/:id | Sends the created group. Empty body. |
POST/api/message/direct | Instant survey invitation to one contact with custom template parameters (customNotification). |
POST/api/message/basic-direct | Same as direct; template fields (template_name, template_lang, bodyPayload) at the root of the body. |
GET/api/message | List sending tasks. |
GET/api/message/task/:taskId | Status of one sending task. |
# Text
{ "type": "TEXT", "phone": "905551112233", "text": "Hi! Your order has been shipped." }
# Image by URL
{ "type": "IMAGE", "phone": "905551112233", "link": "https://example.com/campaign.jpg", "text": "September campaign" }
# Document as Base64
{ "type": "DOCUMENT", "phone": "905551112233", "media": "JVBERi0xLjcK…", "file_name": "invoice.pdf" }
The response is 201 and echoes the body you sent in data. If the channel does not support media you get 400 with MEDIA_NOT_SUPPORTED_ON_CHANNEL.
Surveys are designed in the dashboard; through the API you list them, read results and generate personalised pre-filled links.
| Endpoint | Description |
|---|---|
GET/api/survey/form | Paginated list of surveys. |
GET/api/survey/pure-survey | Plain list (id and name), unpaginated. |
GET/api/survey/form/:id | The survey form: questions, options, flow. |
GET/api/statistic/:survey_id | Survey results (sessions and answers), paginated. |
GET/api/survey/pre-start/:surveyForm_id | Lists the pre-filled links generated for this survey. |
POST/api/survey/pre-start/:surveyForm_id | Generates a pre-filled short link. The body is free JSON ({ "orderNo": "12345", "segment": "vip" }); the fields are available in the survey flow and arrive in webhooks as preData. data in the response carries the short link: https://cxpe.net/pXXXXXXXX. |
A notification schema is Cxperium's counterpart of the WhatsApp template submitted to Meta for approval. Creating, listing and deleting schemas is open on Professional and higher plans.
| Endpoint | Description |
|---|---|
POST/api/notification/schema | Creates a template and submits it to Meta. Required: name, category (UTILITY, MARKETING, AUTHENTICATION), lang. Optional: headerOptions, bodyOptions, footerText, buttonOptions, carouselOptions. |
GET/api/notification/schema | Lists templates and their approval status. |
GET/api/notification/schema/:id | One template. |
DELETE/api/notification/schema/:templateName | Deletes the template. |
POST/api/notification/send-single | Sends a template notification to one contact. Body below. |
GET/api/notification/form | Lists notification sending tasks. |
GET/api/notification/form/:taskId | Details of one task. |
GET/api/notification/export | Exports notification records as Excel (date_type or start/end). |
GET/api/notification/notification-message-status/:id | Delivery status of one notification (sent, delivered, read, failed). |
{
"contact": { "phone": "905551112233" },
"notification": {
"template_name": "order_shipped", // Meta-approved template name
"name": "Shipping notification", // task name (shown in the dashboard)
"data": {
"template_lang": "en",
"bodyPayload": ["Jane", "TR-48291"], // {{1}}, {{2}} … in order
"headerPayload": { "format": "IMAGE", "link": "https://example.com/shipping.jpg" }, // if the template has a media header
"buttonPayload": [ { "type": "QUICK_REPLY", "payload": "track_shipping" } ] // if the template has buttons
}
}
}
Fill the body according to your template's structure: an empty bodyPayload array for a template without variables, no headerPayload for a template without a header. When a bulk send finishes, the NOTIFICATION_SENDING_COMPLETED webhook event arrives.
Ticket statuses are NEW, OPEN, PENDING, CLOSED. Ticket creation accepts multipart/form-data so that files can be attached.
| Endpoint | Description |
|---|---|
GET/api/ticket | Paginated, filtered, sorted list: filter={"status":"NEW"}&sort={"createdAt":-1}. |
GET/api/ticket/:_id | One ticket with its comments. |
GET/api/ticket/task/:taskId | By the ticket number shown in the dashboard. |
GET/api/ticket/contact/:contactNumber | A contact's tickets by phone. |
GET/api/ticket/contact-by-id/:_id | Tickets by contact id. |
GET/api/ticket/assignee-count | Open ticket counts per agent. |
GET/api/last-answer/:id | The ticket's last answer. |
POST/api/ticket | Create a ticket (multipart). Fields: subject, contactId, message (required); tags (JSON array), media (one or more files). |
POST/api/ticket/send-comment/user/:_id | Comment on a ticket on behalf of a dashboard user: { "message": "…" }. |
POST/api/ticket/send-comment/phone/:_id/:phone | A message/comment on the ticket delivered to the contact over WhatsApp: { "message": "…" }. |
POST/api/ticket/:_id/wa/:phone/comments | Adds a comment the contact sent over WhatsApp to the ticket (for bot integrations). |
PATCH/api/assignee-change/:_id/:type/:assigneeId | Assigns the ticket to a user. |
curl -X POST https://api.cxperium.com/api/ticket \
-H "apikey: $CX_API_KEY" \
-F "subject=Delivery delay" \
-F "contactId=6612cc33dd44ee55ff667788" \
-F "message=My order has not arrived for 5 days." \
-F 'tags=["66201122334455667788990a"]' \
-F "media=@invoice.pdf"
There are webhook events for creation, status and assignee changes and comments: Ticket events.
Live support chats are the records agents see in the dashboard. Through the API you can open chats, send messages and change the team or status.
| Endpoint | Description |
|---|---|
POST/api/chat | Create a chat: { "contactId": "…", "message": "…", "teamId": "…" } (only contactId is required). If the contact has an open chat, that one is returned. |
GET/api/chat | List chats. Unassigned new chats: filter={"status":"NEW","assignee":{"exists":false}}. |
GET/api/chat/active/:id | Whether the contact has an open chat. |
POST/api/chat/send-message | Sends a message to a contact, opening a chat if needed: { "message": "…", "contactId": "…" }. |
POST/api/chat/send-message/:_id | Message to an existing chat (message and/or media). |
POST/api/chat/send-message/phone/:_id | Message by phone: { "phone": "9055…", "message": { "text": "…" } }. |
PATCH/api/chat/team-change/:_id/:teamId | Moves the chat to another team. |
PATCH/api/chat/status-change/:_id/:status | Changes the status (NEW, OPEN, PENDING, CLOSED). |
PUT/api/chat/:_id/tags | Assigns tags to the chat: { "tags": ["…"] }. |
GET/api/chat/export | Exports chat records (date_type or start/end). |
PUT/api/chat/settings/timeout | Updates the session timeout setting. |
GET/api/business-hours | Business hours; /api/business-hours/:phone for a specific number. |
GET/api/teams | Lists teams. |
GET/api/subuser | Lists sub-users (agents); /api/subuser/:id one record, updated with PUT (e.g. chatAssignmentThreshold). |
For chat creation, message, status and assignee events see Chat events.
Webhook definitions can be managed from the dashboard or the API; both see the same record. Delivery is exclusive to the Enterprise plan.
| Endpoint | Description |
|---|---|
POST/api/webhook | Create or update (updates when the address matches): webhook_adress, webhook_time (event codes), access_survey (survey ids or ["*"]), webhook_active. |
GET/api/webhook | Lists the defined webhooks. |
DELETE/api/webhook | Deletes by address: { "webhook_adress": "https://…" }. |
Event codes and the fields sent: Webhook Reference.
Assistant endpoints used by chatbot integrations, WhatsApp catalog/product messages, and Pipeline management.
| Endpoint | Description |
|---|---|
GET/api/assistant/configuration | Assistant configuration. |
GET/api/assistant/intent | Intent list. |
GET/api/assistant/localization | Localization texts; /:languageId for one language. |
POST/api/assistant/localization | Bulk add texts: { "data": [ { "languageId", "key", "value" } ] }. |
POST/api/assistant/session | Create/update a contact session: { "phone", "language", "data": [ { "message", "isLast" } ], "isActive" }. |
GET/api/assistant/session | Sessions; /:phone by number, /api/assistant/session-id/:id by id. |
POST/api/assistant/report | Assistant report record: { "phone", "intentName", "message", "nlp" }; /api/assistant/bulk-report in bulk. |
GET/api/assistant/report | Reports (start, end); /export Excel; /session-without-ticket numbers that wrote in the range without a ticket. |
POST/api/assistant/shopping-carts | Cart record: { "cartKey", "customerId", "productCode", "quantity", "unitPrice" }; PUT updates, GET /:cartKey reads. |
PATCH/api/assistant/stage/:id | Update a knowledge base (stage); /file/:fileId/status updates a file's processing status. |
GET/api/waba | The account's WhatsApp number details. |
| Endpoint | Description |
|---|---|
GET/api/catalog/catalogs | Lists catalogs; POST creates a new catalog. |
GET/api/catalog/products | Lists products; POST adds, DELETE /:productId removes. |
GET/api/catalog/commerce-settings | Cart and catalog visibility; updated with POST. |
POST/api/catalog/send/single-product | Single product message; /multi-product multiple products, /catalog catalog message. |
| Endpoint | Description |
|---|---|
GET/api/funnel/stages | Lists stages; POST creates, PATCH /:id updates, DELETE /:id deletes, POST /:id/move-stage reorders. |
GET/api/funnel/cards | Lists lead cards; POST creates, PATCH /:id updates, DELETE /:id deletes, POST /:id/move-card changes the stage. |
POST/api/funnel/cards/search-by-custom-field | Searches cards by a custom field. |
POST/api/funnel/cards/:id/add-activity | Adds an activity (todo, call, mail, meeting, document); PATCH …/update-activity/:activityId, DELETE …/remove-activity. |
POST/api/funnel/cards/:id/add-log | Adds a note/log; DELETE …/remove-log. Likewise add-follower/remove-follower and add-attachment/remove-attachment. |
For using Pipeline in the dashboard see CRM Features → Pipeline.
Let our technical team guide you through your integration — send us your question and we'll get back to you the same day.
Dedicated technical support · Free integration consulting