API Reference
Clientra CRM exposes 377+ REST-style endpoints through a single PHP file. All requests go to /api.php with an action query parameter identifying the operation.
Overview
Base URL
https://yourdomain.com/api.php
Authentication
Session-based viaclientra_session cookie
⚠ All Delete Operations Use POST
The delete, delete_contact, delete_lead, and all other delete actions use POST method — not HTTP DELETE. The frontend ApiClient already handles this correctly.
Response Format
All endpoints return JSON with a consistent envelope structure:
json
// Success response { "success": true, "message": "Property created successfully", "data": { "id": 42, "ref": "PROP-042" }, "csrf_token": "abc123..." // Included on auth endpoints } // Error response { "success": false, "message": "Validation failed: price is required", "errors": { "price": "Price is required" } }
Making Requests
javascript
// GET request const result = await api.call('list_leads', 'GET', { status: 'New', page: 1, limit: 25 }); // POST request (create) const result = await api.call('add_lead', 'POST', { name: 'John Smith', phone: '+971501234567', source: 'Website' }); // Direct fetch (equivalent) const res = await fetch('/api.php?action=list_leads&status=New', { credentials: 'include' // Session cookie });
Authentication
POST
?action=login
Authenticate user. Body:
{email, password}
GET
?action=check_session
Validate current session. Returns user object if authenticated.
POST
?action=logout
Destroy the current session.
Properties
GET?action=listList properties with filters (status, type, location, price_min, price_max, beds, page, limit)
GET?action=get&id={id}Get single property by ID
POST?action=addCreate a new property listing
PUT?action=update&id={id}Update an existing property
POST?action=deleteSoft-delete a property. Body:
{id}GET?action=get_next_refGet next auto-generated property reference number
GET?action=get_history&id={id}Get audit history for a property
POST?action=set_cover_imageSet cover image for a property. Body:
{property_id, file_id}GET?action=get_locationsGet all available locations for filter dropdown
GET?action=get_communitiesGet communities (optionally filtered by location)
GET?action=get_typesGet property types list
GET?action=list_property_idsGet all matching property IDs (no pagination) — used for bulk select-all across pages. Accepts same filters as
listℹ Reference Generator Safety
All generateXxxRef() methods in the backend use a database transaction to ensure race-condition-safe reference generation. Do not revert to the old SELECT MAX() + 1 pattern.
Contacts
GET?action=list_contactsList contacts with filters (type, status, search, page, limit)
GET?action=get_contact&id={id}Get single contact with communication history
POST?action=add_contactCreate a new contact
PUT?action=update_contact&id={id}Update contact details
POST?action=delete_contactSoft-delete a contact. Body:
{id}GET?action=search_contacts&q={query}Search contacts by name, phone, or email (for pickers)
Leads
GET?action=list_leadsList leads with filters (status, source, agent_id, priority, date_from, date_to, page, limit)
GET?action=get_lead&id={id}Get single lead with full details and timeline
POST?action=add_leadCreate a new lead
PUT?action=update_lead&id={id}Update lead details or status
POST?action=delete_leadSoft-delete a lead. Body:
{id}⚠ backfillCampaignNames is Opt-In
The backfillCampaignNames function only runs when ?backfill_campaigns=1 is passed to list_leads. Do not call it unconditionally — it processes all lead records and can be slow.
Owners
GET?action=list_ownersList all owners with filters
GET?action=get_owner&id={id}Get owner by ID
GET?action=get_owner_by_ref&ref={ref}Get owner by reference number
POST?action=add_ownerCreate a new owner record
PUT?action=update_owner&id={id}Update owner details
POST?action=delete_ownerSoft-delete an owner. Body:
{id}Real Estate Projects
GET?action=list_real_estate_projectsList projects with filters
GET?action=get_real_estate_project&id={id}Get project with full details and unit breakdown
POST?action=add_real_estate_projectCreate a new development project
PUT?action=update_real_estate_project&id={id}Update project details
POST?action=delete_real_estate_projectDelete a project. Body:
{id}POST?action=set_project_cover_imageSet cover image for a project
Units
GET?action=list_unitsList units with filters (project_id, status, type, beds)
GET?action=get_unit&id={id}Get unit details
POST?action=add_unitCreate a new unit
PUT?action=update_unit&id={id}Update unit details
POST?action=delete_unitDelete a unit. Body:
{id}GET?action=get_units_by_project&project_id={id}Get all units for a specific project
ℹ Global Search Uses units Table
The global search feature queries the units table — not real_estate_units (which does not exist). Ensure all unit queries reference the correct table name.
Deals
GET?action=list_dealsList deals with filters (stage, agent_id, date_from)
GET?action=get_deal&id={id}Get deal with full details
GET?action=get_kanbanGet deals grouped by stage for kanban view
POST?action=add_dealCreate a new deal
PUT?action=update_deal&id={id}Update deal details
POST?action=move_deal_stageMove deal to different stage. Body:
{id, stage}POST?action=delete_dealSoft-delete a deal. Body:
{id}GET?action=deal_dashboard_statsGet deal pipeline stats for dashboard
POST?action=convert_lead_to_dealConvert a lead to a deal. Body:
{lead_id, deal_data}GET?action=get_deals_for_lead&lead_id={id}Get all deals associated with a lead
Communications
GET?action=list_communicationsList communications with filters (type, entity_type, entity_id)
POST?action=add_communicationLog a new communication. Use
body field for content.GET?action=get_communication&id={id}Get single communication record
POST?action=delete_communicationDelete a communication. Body:
{id}GET?action=entity_timeline&entity_type={t}&entity_id={id}Get full timeline for a specific entity
GET?action=communication_statsGet communication statistics by type and date range
GET?action=list_email_templatesList saved email templates
POST?action=save_email_templateCreate or update an email template
POST?action=delete_email_templateDelete an email template. Body:
{id}Tasks
GET?action=list_tasksList tasks (status, priority, assigned_to, due_date)
POST?action=add_taskCreate a new task
PUT?action=update_task&id={id}Update task details
POST?action=complete_taskMark task as completed. Body:
{id}POST?action=delete_taskDelete a task. Body:
{id}Mail / Email
GET?action=getEmailAccountsList all configured email accounts
POST?action=addEmailAccountAdd a new IMAP/SMTP email account
PUT?action=updateEmailAccount&id={id}Update email account settings
POST?action=deleteEmailAccountRemove an email account. Body:
{id}GET?action=fetchEmails&account_id={id}&folder={f}Fetch emails from IMAP for given account and folder
GET?action=getEmailDetail&uid={uid}&account_id={id}Get full email content by UID
POST?action=sendEmailSend email via SMTP. Body:
{account_id, to, subject, body, attachments}POST?action=markEmailReadMark email as read. Body:
{uid, account_id}GET?action=getEmailFolders&account_id={id}List IMAP folders for an account
GET?action=getEmailPermissions&account_id={id}Get user access permissions for email account
POST?action=saveEmailPermissionsUpdate user permissions for email account
Contracts
GET?action=list_contractsList contracts with filters
POST?action=create_contractCreate a new contract
PUT?action=update_contract&id={id}Update contract details
POST?action=delete_contractDelete a contract. Body:
{id}Financial
GET?action=list_invoicesList invoices with filters (status, contact_id, deal_id)
POST?action=create_invoiceCreate a new invoice with line items
POST?action=record_paymentRecord payment against an invoice
GET?action=financial_summaryGet financial summary (total invoiced, paid, outstanding, by period)
Commissions
GET?action=list_commissionsList commissions with filters
GET?action=commission_summaryGet commission totals (pending, approved, paid)
GET?action=commission_agent_summary&user_id={id}Commission summary for a specific agent
POST?action=approve_commissionApprove a pending commission. Body:
{id}POST?action=pay_commissionMark commission as paid. Body:
{id, paid_date}GET?action=export_commissionsExport commissions as CSV
Automation
GET?action=list_automation_rulesList all automation rules
POST?action=save_automation_ruleCreate or update an automation rule
POST?action=delete_automation_ruleDelete a rule. Body:
{id}POST?action=toggle_automation_ruleEnable or disable a rule. Body:
{id, enabled}GET?action=automation_logGet automation execution log
POST?action=duplicate_automation_ruleDuplicate an existing rule. Body:
{id}GET?action=get_automation_statsGet rule execution statistics
HR Module
Employees
GET?action=hr_list_employeesList all employees
POST?action=hr_add_employeeAdd a new employee record
PUT?action=hr_update_employee&id={id}Update employee details
POST?action=hr_delete_employeeDelete employee. Body:
{id}Attendance
GET?action=hr_daily_attendance&date={date}Get attendance for a specific date
POST?action=hr_mark_attendanceMark attendance for an employee
POST?action=hr_bulk_attendanceMark attendance for multiple employees at once
Leave Management
GET?action=hr_list_leavesList leave requests
POST?action=hr_request_leaveSubmit a leave request
POST?action=hr_approve_leaveApprove a leave request. Body:
{id}POST?action=hr_reject_leaveReject a leave request. Body:
{id, reason}GET?action=hr_leave_balance&employee_id={id}Get remaining leave balance for an employee
Payroll
GET?action=hr_list_payrollList payroll records
POST?action=hr_generate_payrollGenerate payroll for a period. Body:
{month, year}POST?action=hr_mark_paidMark payroll as paid. Body:
{id}Lookups
All lookup endpoints follow the same pattern for developers, locations, communities, projects, and phases:
GET?action=lookups_get_{type}List lookup items (type: developers, locations, communities, projects, phases)
POST?action=lookups_add_{type}Add a new lookup item
PUT?action=lookups_update_{type}&id={id}Update a lookup item
POST?action=lookups_delete_{type}Delete a lookup item. Body:
{id}Notifications
GET?action=get_notificationsGet paginated notifications for current user
GET?action=get_unread_countGet unread notification count
POST?action=mark_notification_readMark one notification as read. Body:
{id}POST?action=mark_all_notifications_readMark all notifications as read (POST — not GET)
POST?action=delete_notificationDelete a notification. Body:
{id}Reports
GET?action=report_statsHigh-level stats for reports dashboard
GET?action=report_team_performanceAgent performance metrics (calls, deals, revenue)
GET?action=report_sales_funnelLead-to-deal conversion rates per stage
GET?action=report_revenue_forecastProjected revenue based on current pipeline
GET?action=report_activity_overviewCommunications and activities by date range
Meta Ads
GET?action=meta_get_settingsGet Meta Ads integration settings
POST?action=meta_save_settingsSave Meta API credentials
POST?action=meta_test_connectionTest Meta API connectivity
GET?action=meta_list_queueList pending leads from Meta webhook queue
POST?action=meta_process_queueProcess queued Meta leads into CRM leads
GET?action=meta_list_logsView Meta webhook event logs
GET?action=meta_get_lead_statsMeta leads statistics by campaign and date
Trash
GET?action=trash_listList soft-deleted records (filterable by entity type)
POST?action=trash_restoreRestore a trashed record. Body:
{id, entity_type}POST?action=trash_deletePermanently delete a trashed record
POST?action=trash_restore_allRestore all trashed records of a given entity type
POST?action=trash_emptyPermanently delete all trashed records
GET?action=trash_countGet count of trashed records by entity type
Audit Log
GET?action=audit_listList audit changes with filters (entity_type, user_id, date)
GET?action=audit_get&id={id}Get full audit entry with before/after values
POST?action=audit_acceptAccept a change (mark as reviewed). Body:
{id}POST?action=audit_revertRevert a change to its previous value. Body:
{id}POST?action=audit_accept_allAccept all pending changes
POST?action=audit_revert_allRevert all pending changes
UAE Services
POST?action=calculate_dld_feesCalculate Dubai Land Department transfer fees. Body:
{property_value, transaction_type}POST?action=calculate_service_chargesCalculate annual service charges for a property
POST?action=validate_emirates_idValidate an Emirates ID format. Body:
{emirates_id}Global Search
GET?action=global_search&q={query}Search across properties, leads, contacts, owners, and units. Returns grouped results.