Zealdash Tenant API
REST API for tenant-specific CRM data. 238 endpoints. JWT authentication. Documentation-first reference.
REST API Overview
Zealdash SaaS CRM provides a Tenant API for programmatic access to tenant-specific CRM data in an isolated environment.
URL Structure
{{base_url}}/api/v1/{endpoint}
Environments
| Environment | Base URL |
| Production | https://app.zealdash.com |
| Staging | https://app-sandbox.zealdash.com |
| Development | http://localhost:8080 |
Tenant slug is provided during onboarding (lowercase, alphanumeric, hyphens). Example: https://app.zealdash.com/api/v1/clients
Technology Stack
- Style: REST · Format: JSON · Methods: GET, POST, PUT, DELETE
- Versioning: /api/v1/
- Authentication: JWT (HS256), Access & Refresh tokens
Response Standard
Success:
{
"status": "success",
"message": "Operation completed",
"data": { ... }
}
Error:
{
"status": "error",
"message": "Validation failed",
"errors": {},
"code": 422
}
HTTP status codes: 200 Success · 201 Created · 400 Bad Request · 401 Unauthorized · 403 Forbidden · 404 Not Found · 422 Validation Error · 500 Server Error
Authentication
Authentication endpoints handle login, token refresh, user identity, password reset and logout.
All secured APIs (other than login) require a JWT Bearer token obtained from these endpoints.
Login with email, password and tenant slug. Returns access and refresh tokens and basic user info.
{
"email": "[email protected]", "_comment": "required",
"password": "yourpassword", "_comment": "required",
"tenant_slug": "my-company" "_comment": "required; selects tenant"
}
{
"status": "success",
"message": "Login successful",
"data": {
"access_token": "eyJhbGciOi...",
"refresh_token": "9rk3j...",
"expires_in": 3600,
"user": {
"id": 1,
"name": "Admin User",
"email": "[email protected]"
}
}
}
Field Explanation
| Field |
Description |
email |
Tenant admin or user email. Required. |
password |
User password. Required. |
tenant_slug |
Tenant identifier used to select the workspace. Required. |
Exchange a valid refresh token for a new access token. The response has the same structure as login.
{
"refresh_token": "your_refresh_token_here"
}
The response returns new access/refresh tokens in the same shape as Login.
Returns the currently authenticated user and tenant information for the supplied access token.
{
"status": "success",
"data": {
"user": {
"id": 1,
"name": "Admin User",
"email": "[email protected]"
},
"tenant": {
"id": 12,
"name": "My Company",
"slug": "my-company"
}
}
}
Starts the password reset flow by generating a reset key for the specified tenant user.
{
"email": "[email protected]", "_comment": "required",
"tenant_slug": "gold-plan-2" "_comment": "required"
}
{
"status": "success",
"message": "Password reset link generated",
"data": {
"email": "[email protected]",
"reset_key": "ddea754640155a214d9d55cf8ac5071e"
}
}
Completes the password reset flow by setting a new password using a valid reset key.
{
"email": "[email protected]", "_comment_email": "required",
"reset_key": "d523b6192e556ccafc4a5eb6774362dd", "_comment_reset_key": "required",
"password": "Password@12",
"_comment_password": "required | min 8 chars | must match confirmation",
"password_confirm": "Password@12",
"_comment_password_confirm": "required | must match password",
"tenant_slug": "gold-plan-2", "_comment_tenant_slug": "required"
}
{
"status": "success",
"message": "Password reset successfully",
"data": {}
}
Logs the current user out and invalidates the supplied access token.
{
"email": "[email protected]", "_comment_email": "required",
"reset_key": "d523b6192e556ccafc4a5eb6774362dd", "_comment_reset_key": "required",
"password": "Password@12",
"_comment_password": "required | min 8 chars | must match confirmation",
"password_confirm": "Password@12",
"_comment_password_confirm": "required | must match password",
"tenant_slug": "gold-plan-2", "_comment_tenant_slug": "required"
}
{
"status": "success",
"message": "Logged out successfully",
"data": {}
}
Dashboard
Dashboard endpoints return overview widgets such as summary cards, finance metrics and charts.
The main endpoint is an overview that aggregates key CRM metrics for the tenant.
Load the tenant dashboard overview including summary cards, finance breakdown and charts.
No query parameters. Uses the authenticated tenant context.
{
"status": "success",
"message": "Dashboard overview loaded",
"data": {
"summary_cards": [
{
"key": "clients_total",
"label": "Clients",
"countValue": 58
},
{
"key": "invoices_pending",
"label": "Invoices awaiting payment",
"countValue": 12,
"total": 34,
"percent": 35.3
},
{
"key": "projects_in_progress",
"label": "Projects - In Progress",
"countValue": 6,
"total": 15,
"percent": 40
}
],
"finance": {
"currency": {
"name": "USD",
"symbol": "$"
},
"values": {
"due": 3200,
"paid": 11800,
"overdue": 450
}
},
"charts": {
"weekly_payments": {
"labels": ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],
"datasets": [
{
"label": "This week",
"data": [0,300,250,0,0,0,0]
}
]
},
"projects_status": {
"labels": ["In Progress","Completed"],
"datasets": [
{
"label": "Projects by status",
"data": [5,10]
}
]
}
}
}
}
Clients
Client endpoints manage customer organisations and contacts. This section includes list, create,
retrieve, update, delete and contact listing APIs.
Returns a paginated list of clients with optional search and pagination parameters.
| Parameter | Description |
page | Page number (default 1). |
per_page | Items per page (default 20, max 100). |
search | Optional search string to filter by client fields. |
{
"status": "success",
"data": {
"items": [
{
"userid": 1,
"company": "ACME Corp",
"email": "[email protected]",
"phonenumber": "+1234567890"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 50
}
}
}
Creates a new client record with basic company and contact information.
{
"company": "New Company Ltd", "_comment": "required",
"email": "[email protected]", "_comment": "required",
"firstname": "John", "_comment": "optional but recommended",
"lastname": "Doe",
"password": "securepassword123", "_comment": "required",
"phonenumber": "+1987654321"
}
{
"status": "success",
"message": "Client created successfully",
"data": {
"id": 123
}
}
Retrieve a single client by ID.
| Parameter | Description |
id | Required client ID (integer). |
{
"status": "success",
"data": {
"client": {
"userid": 1,
"company": "ACME Corp",
"email": "[email protected]",
"phonenumber": "+1234567890"
}
}
}
Update an existing client. Only fields provided in the body will be changed.
{
"id": 1, "_comment": "required client id",
"company": "ACME Corp Updated", "_comment": "optional",
"email": "[email protected]", "_comment": "optional",
"firstname": "John",
"lastname": "Doe",
"phonenumber": "+1234567890",
"password": "newpass123" "_comment": "optional; set to update"
}
{
"status": "success",
"message": "Client updated successfully"
}
Permanently delete a client by ID.
Send id (required, integer) as query parameter or in the body.
{
"status": "success",
"message": "Client deleted successfully"
}
List contacts for a given client ID with optional pagination.
| Parameter | Description |
client_id | Required client ID (integer). |
page | Optional page number. |
per_page | Optional page size. |
{
"status": "success",
"data": {
"contacts": [
{
"id": 10,
"firstname": "Jane",
"lastname": "Smith",
"email": "[email protected]",
"phonenumber": "+123"
}
]
}
}
Finance
Finance endpoints cover expenses, estimates, invoices and payments, including categories,
statuses and invoice payment helpers.
Returns a paginated list of expenses with optional search and category filters.
| Parameter | Description |
page | Page number. |
per_page | Items per page. |
search | Optional text search. |
category_id | Optional expense category ID. |
{
"status": "success",
"data": {
"items": [
{
"id": 1,
"category": "Travel",
"amount": 120.50,
"date": "2024-02-01"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 30
}
}
}
Create a new expense entry with category, amount, date and optional links to client or project.
{
"category": 3, "_comment": "required; category id",
"amount": 120.50, "_comment": "required",
"date": "2024-02-01", "_comment": "required",
"note": "Taxi ride", "_comment": "optional",
"customer_id": 1, "_comment": "optional link to client",
"project_id": 2 "_comment": "optional"
}
{
"status": "success",
"message": "Expense created",
"data": {
"id": 123
}
}
Retrieve a single expense by ID.
id – required expense ID.
{
"status": "success",
"data": {
"expense": {
"...": "full expense fields"
}
}
}
Update an existing expense. Provide the expense id and the fields to change.
Body: same fields as create plus required id.
{
"status": "success",
"message": "Expense updated"
}
Delete an expense by ID.
id – required, provided as query or body.
{
"status": "success",
"message": "Expense deleted"
}
Returns the list of available expense categories.
{
"status": "success",
"data": {
"categories": [
{
"id": 1,
"name": "Travel"
}
]
}
}
Endpoints to list, create, retrieve, update, delete and list statuses for estimates.
4.7 – GET List Estimates — /estimates/index
Query: page, per_page, status, client_id optional. Response includes estimate items and pagination.
{
"clientid": 1, "_comment": "required",
"date": "2024-02-01",
"expirydate": "2024-02-15",
"subtotal": 1000,
"total": 1100,
"newitems": [
{
"description": "Design work",
"qty": 1,
"rate": 1000
}
]
}
{
"status": "success",
"data": {
"id": 456
}
}
4.9 – GET Get Estimates — /estimates/show
id required; response contains full estimate payload.
4.10 – PUT Update Estimates — /estimates/update
Body: same as create plus required id; response {"status":"success","message":"Estimate updated"}.
4.11 – DELETE Delete Estimates — /estimates/destroy
id required; response {"status":"success","message":"Estimate deleted"}.
4.12 – GET Estimate Statuses — /estimates/statuses
Returns list of estimate statuses as {id,label} pairs.
Endpoints to list, create, retrieve, update, delete and manage invoice statuses.
4.13 – GET List Invoices — /invoices/index
Query: page, per_page, status, client_id optional; returns invoices and pagination.
{
"clientid": 1, "_comment": "required",
"date": "2024-01-15",
"duedate": "2024-02-15",
"subtotal": 1000.00,
"total_tax": 100.00,
"total": 1100.00,
"newitems": [
{
"description": "Web Development",
"qty": 1,
"rate": 1000
}
]
}
{
"status": "success",
"data": {
"id": 123
}
}
4.15 – GET Get Invoices — /invoices/{id}
Path id required; returns full invoice payload.
4.16 – PUT Update Invoices — /invoices/{id}
Path id; body same shape as create; response {"status":"success","message":"Invoice updated"}.
4.17 – DELETE Delete Invoices — /invoices/{id}
Response {"status":"success","message":"Invoice deleted"}.
4.18 – POST Mark Sent — /invoices/{id}/mark-sent
Marks invoice as sent; returns success message.
4.19 – POST Mark Cancelled — /invoices/{id}/mark-cancelled
Marks invoice as cancelled; returns success message.
4.20 – GET Invoice Statuses — /invoices/statuses
Returns list of invoice statuses with IDs and labels.
Endpoints for listing, creating, updating and deleting payments, plus invoice-specific
payment lists and payment mode metadata.
4.21 – GET List Payments — /payments/index
Query: page, per_page, client_id, invoice_id optional; returns payments and pagination.
{
"invoice_id": 10, "_comment": "required",
"amount": 200.00, "_comment": "required",
"paymentmode": 2, "_comment": "required; payment mode id",
"date": "2024-02-01",
"note": "Partial payment"
}
{
"status": "success",
"data": {
"id": 789
}
}
Other Payment Endpoints
- 4.22 – GET Get Payments —
/payments/show, query id required; returns a single payment.
- 4.24 – PUT Update Payments —
/payments/update, body similar to create with required id; returns success message.
- 4.25 – DELETE Delete Payments —
/payments/destroy, id required; returns success message.
- 4.26 – GET Invoice Payments —
/payments/invoice_payments, query invoice_id required; returns list of payments for the invoice.
- 4.27 – GET Modes —
/payments/modes, returns available payment modes.
Projects
Project endpoints manage project records, their lifecycle and status metadata.
Returns a paginated list of projects for the tenant, with optional filters by status and client.
| Parameter | Description |
page | Page number (optional). |
per_page | Items per page (optional). |
search | Optional search term for project name. |
status | Optional project status ID. |
client_id | Optional client filter. |
{
"status": "success",
"data": {
"projects": [
{
"id": 1,
"name": "Website Redesign",
"status": 2,
"clientid": 1,
"progress": 45,
"deadline": "2024-03-15"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 50
}
}
}
Create a new project linked to a client, with optional start/end dates and budget.
{
"name": "Website Redesign Project", "_comment": "required",
"clientid": 1, "_comment": "required",
"status": 1, "_comment": "status id",
"start_date": "2024-01-15",
"deadline": "2024-03-15",
"project_cost": 10000.00
}
{
"status": "success",
"data": {
"id": 123
}
}
Retrieve a full project payload by its ID.
Path parameter id (required) – project ID.
Returns the full project object, including status, client and progress fields.
Update an existing project by ID. Only supplied fields are updated.
Path parameter id (required). Body uses the same structure as create.
{
"status": "success",
"message": "Project updated"
}
Permanently delete a project by ID.
Path parameter id (required) – project ID.
{
"status": "success",
"message": "Project deleted"
}
Retrieve all available project statuses with colors and ordering information.
{
"status": "success",
"message": "Project statuses retrieved successfully",
"data": [
{
"id": 1,
"name": "Not Started",
"color": "#475569",
"order": 1,
"filter_default": true
},
{
"id": 2,
"name": "In Progress",
"color": "#3b82f6",
"order": 2,
"filter_default": false
},
{
"id": 3,
"name": "On Hold",
"color": "#f59e0b",
"order": 3,
"filter_default": false
},
{
"id": 4,
"name": "Completed",
"color": "#10b981",
"order": 4,
"filter_default": false
},
{
"id": 5,
"name": "Cancelled",
"color": "#ef4444",
"order": 5,
"filter_default": false
}
]
}
Tasks
Tasks endpoints expose operations around CRM task management including listing, creating,
retrieving, updating and deleting tasks.
Retrieve a paginated list of tasks with optional filtering by search, status, project and assignee.
| Parameter | Description |
page | Optional integer, default 1 – page number. |
per_page | Optional integer, default 20, max 100 – items per page. |
search | Optional string – search by task name. |
status | Optional integer – filter by status ID (1–5). |
project_id | Optional integer – filter by project ID. |
assigned_to | Optional integer – filter by assigned staff ID. |
{
"status": "success",
"message": "Tasks retrieved successfully",
"data": {
"tasks": [
{
"id": 1,
"name": "Design homepage",
"description": "Create homepage design mockup",
"status": 1,
"priority": 2,
"rel_type": "project",
"rel_id": 1,
"startdate": "2024-01-15",
"duedate": "2024-01-20",
"dateadded": "2024-01-10 09:00:00",
"addedfrom": 1,
"milestone": 1,
"hourly_rate": "75.00",
"is_public": 0,
"billable": 1,
"billed": 0
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 75,
"total_pages": 4
}
}
}
Create a new task associated with a project or other related entity.
{
"_comment": "Required fields: name, rel_type, rel_id",
"name": "Design homepage",
"_comment_name": "Required - Task name (max 200 characters)",
"description": "Create homepage design mockup",
"_comment_description": "Optional - Task description (max 65000 characters)",
"rel_type": "project",
"_comment_rel_type": "Required - Related entity type: 'project', 'customer', etc. (max 40 characters)",
"rel_id": 1,
"_comment_rel_id": "Required - Related entity ID (integer)",
"status": 1,
"_comment_status": "Optional - Task status: 1=Not Started, 2=In Progress, 3=Testing, 4=Awaiting Feedback, 5=Complete (default: 1)",
"priority": 2,
"_comment_priority": "Optional - Priority: 1=Low, 2=Medium, 3=High, 4=Urgent (default: 2)",
"startdate": "2024-01-15",
"_comment_startdate": "Optional - Start date (format: Y-m-d)",
"duedate": "2024-01-20",
"_comment_duedate": "Optional - Due date (format: Y-m-d)",
"milestone": 1,
"_comment_milestone": "Optional - Milestone ID (integer)",
"hourly_rate": 75.00,
"_comment_hourly_rate": "Optional - Hourly rate (decimal)",
"is_public": false,
"_comment_is_public": "Optional - Is task public: true/false (default: false)",
"billable": true,
"_comment_billable": "Optional - Is task billable: true/false (default: true)",
"assignees": [1, 2],
"_comment_assignees": "Optional - Array of staff IDs assigned to task",
"followers": [3],
"_comment_followers": "Optional - Array of staff IDs following task"
}
{
"status": "success",
"message": "Task created successfully",
"data": {
"id": 123
}
}
Retrieve a specific task by ID with all related data including assignees and milestones.
Path parameter id (required, integer) – task ID.
{
"status": "success",
"message": "Task retrieved successfully",
"data": {
"id": 1,
"name": "Design homepage",
"description": "Create homepage design mockup",
"status": 1,
"priority": 2,
"rel_type": "project",
"rel_id": 1,
"startdate": "2024-01-15",
"duedate": "2024-01-20",
"dateadded": "2024-01-10 09:00:00",
"addedfrom": 1,
"milestone": 1,
"milestone_name": "Phase 1",
"hourly_rate": "75.00",
"is_public": 0,
"billable": 1,
"billed": 0,
"assignees": [
{
"staffid": 1,
"firstname": "John",
"lastname": "Doe"
}
],
"followers": [],
"attachments": [],
"timesheets": [],
"checklist_items": [],
"comments": [],
"current_user_is_assigned": true,
"current_user_is_creator": false
}
}
Update an existing task. All fields in the body are optional; only included fields are changed.
{
"_comment": "All fields are optional - only include fields to update",
"name": "Design homepage updated",
"_comment_name": "Optional - Task name (max 200 characters)",
"description": "Updated task description",
"_comment_description": "Optional - Task description (max 65000 characters)",
"status": 2,
"_comment_status": "Optional - Task status: 1-5",
"priority": 3,
"_comment_priority": "Optional - Priority: 1-4",
"startdate": "2024-01-16",
"_comment_startdate": "Optional - Start date (format: Y-m-d)",
"duedate": "2024-01-25",
"_comment_duedate": "Optional - Due date (format: Y-m-d)",
"milestone": 2,
"_comment_milestone": "Optional - Milestone ID",
"hourly_rate": 80.00,
"_comment_hourly_rate": "Optional - Hourly rate",
"is_public": true,
"_comment_is_public": "Optional - Is task public",
"billable": false,
"_comment_billable": "Optional - Is task billable",
"assignees": [1, 2, 3],
"_comment_assignees": "Optional - Array of staff IDs",
"followers": [2, 4],
"_comment_followers": "Optional - Array of staff IDs"
}
{
"status": "success",
"message": "Task updated successfully"
}
Delete a task by ID.
Path parameter id (required) – task ID.
{
"status": "success",
"message": "Task deleted successfully"
}
{
"status": "error",
"message": "Task not found",
"code": 404
}
Todos
Todo endpoints manage lightweight personal todo items for staff, including list, create,
retrieve, update, delete and toggle status operations.
Retrieve list of todos for the current authenticated user, optionally filtered by finished status.
| Parameter | Description |
finished | Optional, integer (default 0). 0 = Unfinished, 1 = Finished. |
page | Optional, integer (default 0). Page number. |
{
"status": "success",
"message": "Todos retrieved successfully",
"data": {
"todos": [
{
"id": 1,
"description": "Review project proposal",
"finished": 0,
"dateadded": "2024-01-10 09:00:00",
"item_order": 1,
"staffid": 1
},
{
"id": 2,
"description": "Call client for feedback",
"finished": 0,
"dateadded": "2024-01-11 10:30:00",
"item_order": 2,
"staffid": 1
}
]
}
}
Create a new todo item for the current user.
{
"_comment": "Required field: description",
"description": "Review project proposal",
"_comment_description": "Required - Todo description"
}
{
"status": "success",
"message": "Todo created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"description": "The description field is required"
},
"code": 422
}
Retrieve a specific todo item by ID.
Path parameter id (required, integer) – todo ID.
{
"status": "success",
"message": "Todo retrieved successfully",
"data": {
"id": 1,
"description": "Review project proposal",
"finished": 0,
"dateadded": "2024-01-10 09:00:00",
"item_order": 1,
"staffid": 1
}
}
{
"status": "error",
"message": "Access denied",
"code": 403
}
Update an existing todo item. Only fields present in the body are updated.
{
"_comment": "All fields are optional - only include fields to update",
"description": "Review project proposal - Updated",
"_comment_description": "Optional - Todo description",
"finished": 0,
"_comment_finished": "Optional - Finished status: 0=Unfinished, 1=Finished",
"item_order": 2,
"_comment_item_order": "Optional - Order position (integer)"
}
{
"status": "success",
"message": "Todo updated successfully"
}
Delete a todo item by ID.
Query parameter id (required, integer) – todo ID.
{
"status": "success",
"message": "Todo deleted successfully"
}
Toggle the finished status of a todo item. The documentation notes that although a GET
variant exists, the correct implementation uses POST at /todos/{id}/toggle_status.
{
"_comment": "Optional field: status",
"status": 1,
"_comment_status": "Optional - Status: 0=Unfinished, 1=Finished (default: 1)"
}
{
"status": "success",
"message": "Todo status updated successfully"
}
Activity Logs
Activity log endpoints surface audit-style event history for entities. (Details for these
endpoints are covered by the general Activity Log utilities in the Tenant API docs.)
Departments
Department endpoints configure organisational units used across tickets, leads and other modules.
Retrieve list of all departments configured for the tenant.
{
"status": "success",
"message": "Departments retrieved successfully",
"data": {
"departments": [
{
"departmentid": 1,
"name": "Sales",
"email": "[email protected]",
"calendar_id": "",
"hidefromclient": 0,
"host": "",
"password": "",
"encryption": "",
"delete_mail_after_import": 0,
"imap_username": "",
"notify_lead_imported": 1,
"notify_lead_contact_more_times": 1,
"notify_type": "",
"notify_ids": "",
"responsible": 0,
"no_default_mailbox": 0
}
]
}
}
Retrieve a specific department by ID.
id – required, integer department ID.
{
"status": "success",
"message": "Department retrieved successfully",
"data": {
"departmentid": 1,
"name": "Sales",
"email": "[email protected]",
"calendar_id": "",
"hidefromclient": 0,
"host": "",
"password": "",
"encryption": "",
"delete_mail_after_import": 0,
"imap_username": "",
"notify_lead_imported": 1,
"notify_lead_contact_more_times": 1,
"notify_type": "",
"notify_ids": "",
"responsible": 0,
"no_default_mailbox": 0
}
}
{
"status": "error",
"message": "Department not found",
"code": 404
}
Create a new department with email configuration and notification settings.
{
"_comment": "Required field: name",
"name": "Sales",
"_comment_name": "Required - Department name (max 100 characters)",
"email": "[email protected]",
"_comment_email": "Optional - Department email (valid email, max 100 characters)",
"calendar_id": "",
"_comment_calendar_id": "Optional - Calendar ID",
"hidefromclient": 0,
"_comment_hidefromclient": "Optional - Hide from client: 0=No, 1=Yes",
"host": "",
"_comment_host": "Optional - Email host",
"password": "",
"_comment_password": "Optional - Email password",
"encryption": "",
"_comment_encryption": "Optional - Encryption type",
"delete_mail_after_import": 0,
"_comment_delete_mail_after_import": "Optional - Delete mail after import: 0=No, 1=Yes",
"imap_username": "",
"_comment_imap_username": "Optional - IMAP username",
"notify_lead_imported": 1,
"_comment_notify_lead_imported": "Optional - Notify when lead imported: 0=No, 1=Yes",
"notify_lead_contact_more_times": 1,
"_comment_notify_lead_contact_more_times": "Optional - Notify when lead contacts more times: 0=No, 1=Yes",
"notify_type": "",
"_comment_notify_type": "Optional - Notification type",
"notify_ids": "",
"_comment_notify_ids": "Optional - Notification IDs",
"responsible": 0,
"_comment_responsible": "Optional - Responsible staff ID",
"no_default_mailbox": 0,
"_comment_no_default_mailbox": "Optional - No default mailbox: 0=No, 1=Yes"
}
{
"status": "success",
"message": "Department created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"name": "The name field is required",
"email": "The email field must be a valid email address"
},
"code": 422
}
Update an existing department by ID. All fields in the body are optional.
Query parameter id (required, integer) – department ID.
{
"_comment": "All fields are optional - only include fields to update",
"name": "Sales Department",
"_comment_name": "Optional - Department name (max 100 characters)",
"email": "[email protected]",
"_comment_email": "Optional - Department email (valid email, max 100 characters)",
"calendar_id": "cal_123",
"_comment_calendar_id": "Optional - Calendar ID",
"hidefromclient": 1,
"_comment_hidefromclient": "Optional - Hide from client: 0=No, 1=Yes"
}
{
"status": "success",
"message": "Department updated successfully"
}
Delete a department by ID.
Query parameter id (required, integer).
{
"status": "success",
"message": "Department deleted successfully"
}
Email Templates
Email template endpoints allow you to list and manage automated email templates by type and language.
Retrieve list of email templates filtered by type and language.
| Parameter | Description |
type |
Optional. Template type (e.g. invoice, estimate, proposal, ticket, etc.). |
language |
Optional. Template language, default english. |
{
"status": "success",
"message": "Email templates retrieved successfully",
"data": {
"templates": [
{
"emailtemplateid": 1,
"type": "invoice",
"slug": "invoice-send-to-client",
"language": "english",
"name": "Invoice Send to Client",
"subject": "Invoice #{invoice_number}",
"message": "Dear {contact_firstname} {contact_lastname},\n\nPlease find attached invoice #{invoice_number}.\n\nAmount: {invoice_total}\nDue Date: {invoice_date}\n\nThank you!",
"fromname": "",
"fromemail": "",
"plaintext": 0,
"active": 1,
"order": 1
}
]
}
}
Retrieve a specific email template by its ID.
id – required, integer email template ID.
{
"status": "success",
"message": "Email template retrieved successfully",
"data": {
"emailtemplateid": 1,
"type": "invoice",
"slug": "invoice-send-to-client",
"language": "english",
"name": "Invoice Send to Client",
"subject": "Invoice #{invoice_number}",
"message": "Dear {contact_firstname} {contact_lastname},\n\nPlease find attached invoice #{invoice_number}.\n\nAmount: {invoice_total}\nDue Date: {invoice_date}\n\nThank you!",
"fromname": "",
"fromemail": "",
"plaintext": 0,
"active": 1,
"order": 1
}
}
Update an existing email template. All fields in the body are optional.
Query parameter id (required, integer) – email template ID.
{
"_comment": "All fields are optional - only include fields to update",
"name": "Invoice Send to Client - Updated",
"_comment_name": "Optional - Template name",
"subject": "Invoice #{invoice_number} - Updated Subject",
"_comment_subject": "Optional - Email subject (can include placeholders like {invoice_number})",
"message": "Dear {contact_firstname} {contact_lastname},\n\nPlease find attached invoice #{invoice_number}.\n\nAmount: {invoice_total}\nDue Date: {invoice_date}\n\nThank you for your business!",
"_comment_message": "Optional - Email message body (can include HTML and placeholders)",
"fromname": "Company Name",
"_comment_fromname": "Optional - From name",
"fromemail": "[email protected]",
"_comment_fromemail": "Optional - From email address",
"plaintext": 0,
"_comment_plaintext": "Optional - Plain text mode: 0=HTML, 1=Plain text",
"active": 1,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active",
"order": 1,
"_comment_order": "Optional - Display order"
}
{
"status": "success",
"message": "Email template updated successfully"
}
Estimate Requests
Estimate request endpoints manage inbound estimate or quote requests and allow updates,
assignment changes and conversions.
Retrieve a paginated list of estimate requests submitted by prospects.
| Parameter | Description |
page | Optional, default 1 – page number. |
per_page | Optional, default 20, max 100 – items per page. |
{
"status": "success",
"message": "Estimate requests retrieved successfully",
"data": {
"requests": [
{
"id": 1,
"name": "Website Development",
"email": "[email protected]",
"phonenumber": "+1234567890",
"message": "We need a new website",
"assigned": 1,
"status": 1,
"date": "2024-01-15 10:30:00",
"date_converted": null,
"converted": 0
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 45,
"total_pages": 3
}
}
}
Retrieve a single estimate request by its ID.
Query parameter id (required, integer) – estimate request ID.
{
"status": "success",
"message": "Estimate request retrieved successfully",
"data": {
"id": 1,
"name": "Website Development",
"email": "[email protected]",
"phonenumber": "+1234567890",
"message": "We need a new website",
"assigned": 1,
"status": 1,
"date": "2024-01-15 10:30:00",
"date_converted": null,
"converted": 0
}
}
Create a new estimate request from a prospect or customer.
{
"_comment": "Required fields may vary - check validation",
"name": "Website Development",
"_comment_name": "Required - Request name/company name",
"email": "[email protected]",
"_comment_email": "Required - Contact email",
"phonenumber": "+1234567890",
"_comment_phonenumber": "Optional - Phone number",
"message": "We need a new website with e-commerce functionality",
"_comment_message": "Optional - Request message/description",
"assigned": 1,
"_comment_assigned": "Optional - Assigned staff ID",
"status": 1,
"_comment_status": "Optional - Status ID"
}
{
"status": "success",
"message": "Estimate request created successfully",
"data": {
"id": 123
}
}
Update an existing estimate request. All body fields are optional.
Query parameter id (required, integer) – estimate request ID.
{
"_comment": "All fields are optional - only include fields to update",
"name": "Website Development - Updated",
"_comment_name": "Optional - Request name",
"email": "[email protected]",
"_comment_email": "Optional - Contact email",
"phonenumber": "+1987654321",
"_comment_phonenumber": "Optional - Phone number",
"message": "Updated request message",
"_comment_message": "Optional - Request message",
"assigned": 2,
"_comment_assigned": "Optional - Assigned staff ID",
"status": 2,
"_comment_status": "Optional - Status ID"
}
{
"status": "success",
"message": "Estimate request updated successfully"
}
Delete an estimate request by ID.
Query parameter id (required, integer) – estimate request ID.
{
"status": "success",
"message": "Estimate request deleted successfully"
}
Update the assigned staff member for an estimate request. The documentation notes that, although
a GET URL variant exists, the correct implementation uses POST with the ID in the path.
Path parameter id (required) – estimate request ID.
{
"_comment": "Required field: assigned",
"assigned": 2,
"_comment_assigned": "Required - Staff ID to assign"
}
{
"status": "success",
"message": "Assigned staff updated successfully"
}
Convert an estimate request into an estimate or proposal. The docs clarify that this
should be a POST to /estimaterequests/{id}/convert.
Path parameter id (required, integer) – estimate request ID.
{
"_comment": "Optional field: convert_to",
"convert_to": "estimate",
"_comment_convert_to": "Optional - Conversion type: 'estimate' or 'proposal' (default: 'estimate')"
}
{
"status": "success",
"message": "Conversion initiated. Use the returned URL to complete the conversion.",
"data": {
"convert_to": "estimate",
"request_id": 1
}
}
{
"status": "error",
"message": "Invalid convert_to value. Must be \"estimate\" or \"proposal\"",
"code": 400
}
Filters
Filter endpoints provide saved view/filter definitions for various modules such as customers,
invoices, projects, tasks and more.
Retrieve list of saved filters for a given identifier and view.
| Parameter | Description |
identifier |
Optional. Module identifier such as customers, invoices, estimates, projects, tasks, leads, tickets, etc. |
view |
Optional. View type such as list, table, kanban, calendar. |
{
"status": "success",
"message": "Filters retrieved successfully",
"data": {
"filters": [
{
"id": 1,
"name": "Active Customers",
"identifier": "customers",
"view": "list",
"builder": "{\"condition\":\"AND\",\"rules\":[{\"id\":\"active\",\"field\":\"active\",\"type\":\"integer\",\"input\":\"select\",\"operator\":\"equal\",\"value\":\"1\"}]}",
"is_shared": 1,
"is_default": 0,
"staff_id": 1,
"date_created": "2024-01-10 09:00:00"
}
]
}
}
Retrieve a single filter definition by ID.
Query parameter id (required, integer) – filter ID.
{
"status": "success",
"message": "Filter retrieved successfully",
"data": {
"id": 1,
"name": "Active Customers",
"identifier": "customers",
"view": "list",
"builder": "{\"condition\":\"AND\",\"rules\":[{\"id\":\"active\",\"field\":\"active\",\"type\":\"integer\",\"input\":\"select\",\"operator\":\"equal\",\"value\":\"1\"}]}",
"is_shared": 1,
"is_default": 0,
"staff_id": 1,
"date_created": "2024-01-10 09:00:00"
}
}
Create a new saved filter for a module and view combination.
{
"_comment": "Required fields: name, identifier, view",
"name": "Active Customers",
"_comment_name": "Required - Filter name (max 191 characters)",
"identifier": "customers",
"_comment_identifier": "Required - Filter identifier (max 50 characters): 'customers', 'invoices', 'estimates', 'projects', 'tasks', 'leads', 'tickets', 'expenses', 'credit_notes', 'proposals', 'subscriptions', 'contracts', 'knowledge_base'",
"view": "list",
"_comment_view": "Required - Filter view (max 50 characters): 'list', 'table', 'kanban', 'calendar'",
"rules": {
"_comment_rules": "Optional - Filter rules object (JSON structure for query builder)",
"condition": "AND",
"rules": [
{
"id": "active",
"field": "active",
"type": "integer",
"input": "select",
"operator": "equal",
"value": "1"
}
]
},
"is_shared": 1,
"_comment_is_shared": "Optional - Is shared: 0=No, 1=Yes (default: 0)",
"is_default": 0,
"_comment_is_default": "Optional - Is default: 0=No, 1=Yes (default: 0)"
}
{
"status": "success",
"message": "Filter created successfully",
"data": {
"id": 123,
"name": "Active Customers",
"identifier": "customers",
"view": "list",
"builder": "{\"condition\":\"AND\",\"rules\":[{\"id\":\"active\",\"field\":\"active\",\"type\":\"integer\",\"input\":\"select\",\"operator\":\"equal\",\"value\":\"1\"}]}",
"is_shared": 1,
"is_default": 0,
"staff_id": 1,
"date_created": "2024-01-15 10:30:00"
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"name": "The name field is required",
"identifier": "The identifier field is required"
},
"code": 422
}
Update an existing filter configuration. All body fields are optional.
Query parameter id (required, integer) – filter ID.
{
"_comment": "All fields are optional - only include fields to update",
"name": "Active Customers - Updated",
"_comment_name": "Optional - Filter name",
"is_shared": 0,
"_comment_is_shared": "Optional - Is shared: 0=No, 1=Yes",
"is_default": 1,
"_comment_is_default": "Optional - Is default: 0=No, 1=Yes",
"rules": {
"_comment_rules": "Optional - Filter rules object (JSON structure)",
"condition": "OR",
"rules": [
{
"id": "active",
"field": "active",
"type": "integer",
"input": "select",
"operator": "equal",
"value": "1"
}
]
}
}
{
"status": "success",
"message": "Filter updated successfully",
"data": {
"id": 1,
"name": "Active Customers - Updated",
"identifier": "customers",
"view": "list",
"builder": "{\"condition\":\"OR\",\"rules\":[{\"id\":\"active\",\"field\":\"active\",\"type\":\"integer\",\"input\":\"select\",\"operator\":\"equal\",\"value\":\"1\"}]}",
"is_shared": 0,
"is_default": 1,
"staff_id": 1,
"date_created": "2024-01-10 09:00:00"
}
}
Delete a saved filter by ID.
Query parameter id (required, integer) – filter ID.
{
"status": "success",
"message": "Filter deleted successfully"
}
{
"status": "error",
"message": "Access denied",
"code": 403
}
Currencies
Currency endpoints.
Retrieve list of all currencies (Admin only).
{
"status": "success",
"message": "Currencies retrieved successfully",
"data": {
"currencies": [
{
"id": 1,
"name": "USD",
"symbol": "$",
"decimal_separator": ".",
"thousand_separator": ",",
"placement": "before",
"isdefault": 1
},
{
"id": 2,
"name": "EUR",
"symbol": "€",
"decimal_separator": ".",
"thousand_separator": ",",
"placement": "before",
"isdefault": 0
}
]
}
}
{
"status": "error",
"message": "Access denied",
"code": 403
}
Retrieve a specific currency by ID (Admin only).
Query Parameters
| Param | Description |
id | Currency ID |
{
"status": "success",
"message": "Currency retrieved successfully",
"data": {
"id": 1,
"name": "USD",
"symbol": "$",
"decimal_separator": ".",
"thousand_separator": ",",
"placement": "before",
"isdefault": 1
}
}
Create a new currency (Admin only).
{
"_comment": "Required fields: name, symbol",
"name": "GBP",
"_comment_name": "Required - Currency name/code (max 10 characters)",
"symbol": "£",
"_comment_symbol": "Required - Currency symbol (max 10 characters)",
"decimal_separator": ".",
"_comment_decimal_separator": "Optional - Decimal separator (default: '.')",
"thousand_separator": ",",
"_comment_thousand_separator": "Optional - Thousand separator (default: ',')",
"placement": "before",
"_comment_placement": "Optional - Symbol placement: 'before' or 'after' (default: 'before')"
}
{
"status": "success",
"message": "Currency created successfully"
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"name": "The name field is required",
"symbol": "The symbol field is required"
},
"code": 422
}
Update an existing currency (Admin only).
Query Parameters
| Param | Description |
id | Currency ID |
{
"_comment": "All fields are optional - only include fields to update",
"name": "GBP",
"_comment_name": "Optional - Currency name/code (max 10 characters)",
"symbol": "£",
"_comment_symbol": "Optional - Currency symbol (max 10 characters)",
"decimal_separator": ".",
"_comment_decimal_separator": "Optional - Decimal separator",
"thousand_separator": ",",
"_comment_thousand_separator": "Optional - Thousand separator",
"placement": "after",
"_comment_placement": "Optional - Symbol placement: 'before' or 'after'"
}
{
"status": "success",
"message": "Currency updated successfully"
}
Delete a currency (Admin only). Cannot delete the default currency.
Query Parameters
| Param | Description |
id | Currency ID |
{
"status": "success",
"message": "Currency deleted successfully"
}
{
"status": "error",
"message": "Cannot delete default currency",
"code": 400
}
Boards
Board endpoints.
Retrieve kanban board data for a specific entity type.
Query Parameters
| Param | Description |
type | Entity type (e.g., 'projects', 'tasks', 'leads', 'invoices', 'estimates') |
rel_id | Related entity ID (e.g., project ID for task boards) |
{
"status": "success",
"message": "Board data retrieved successfully",
"data": {
"boards": [
{
"id": 1,
"name": "To Do",
"type": "tasks",
"rel_id": 1,
"order": 1,
"color": "#64748b",
"items": [
{
"id": 1,
"name": "Task 1",
"status": 1,
"priority": 2,
"duedate": "2024-01-20"
}
]
},
{
"id": 2,
"name": "In Progress",
"type": "tasks",
"rel_id": 1,
"order": 2,
"color": "#3b82f6",
"items": []
}
]
}
}
Create a new kanban board.
{
"_comment": "Required fields: name, type",
"name": "To Do",
"_comment_name": "Required - Board name",
"type": "tasks",
"_comment_type": "Required - Entity type: 'projects', 'tasks', 'leads', 'invoices', 'estimates'",
"rel_id": 1,
"_comment_rel_id": "Optional - Related entity ID (e.g., project ID for task boards)",
"order": 1,
"_comment_order": "Optional - Display order (integer)",
"color": "#64748b",
"_comment_color": "Optional - Board color (hex code)"
}
{
"status": "success",
"message": "Board created successfully",
"data": {
"id": 123
}
}
Update an existing kanban board.
{
"_comment": "All fields are optional - only include fields to update",
"name": "To Do - Updated",
"_comment_name": "Optional - Board name",
"order": 2,
"_comment_order": "Optional - Display order",
"color": "#3b82f6",
"_comment_color": "Optional - Board color (hex code)"
}
{
"status": "success",
"message": "Board updated successfully"
}
Delete a kanban board.
{
"status": "success",
"message": "Board deleted successfully"
}
Retrieve items for a kanban board.
Query Parameters
| Param | Description |
board_id | Board ID |
type | Entity type |
rel_id | Related entity ID |
{
"status": "success",
"message": "Board items retrieved successfully",
"data": {
"items": [
{
"id": 1,
"name": "Task 1",
"board_id": 1,
"type": "tasks",
"rel_id": 1,
"status": 1,
"priority": 2,
"duedate": "2024-01-20",
"order": 1
}
]
}
}
Create a new item on a kanban board.
{
"_comment": "Required fields: name, board_id, type",
"name": "New Task",
"_comment_name": "Required - Item name",
"board_id": 1,
"_comment_board_id": "Required - Board ID (integer)",
"type": "tasks",
"_comment_type": "Required - Entity type: 'projects', 'tasks', 'leads', 'invoices', 'estimates'",
"rel_id": 1,
"_comment_rel_id": "Optional - Related entity ID",
"status": 1,
"_comment_status": "Optional - Status ID",
"priority": 2,
"_comment_priority": "Optional - Priority: 1=Low, 2=Medium, 3=High, 4=Urgent",
"duedate": "2024-01-20",
"_comment_duedate": "Optional - Due date (format: Y-m-d)",
"order": 1,
"_comment_order": "Optional - Display order within board"
}
{
"status": "success",
"message": "Board item created successfully",
"data": {
"id": 123
}
}
Update an existing kanban board item.
{
"_comment": "All fields are optional - only include fields to update",
"name": "Updated Task",
"_comment_name": "Optional - Item name",
"board_id": 2,
"_comment_board_id": "Optional - Move to different board",
"status": 2,
"_comment_status": "Optional - Status ID",
"priority": 3,
"_comment_priority": "Optional - Priority",
"duedate": "2024-01-25",
"_comment_duedate": "Optional - Due date",
"order": 2,
"_comment_order": "Optional - Display order"
}
{
"status": "success",
"message": "Board item updated successfully"
}
Delete a kanban board item.
{
"status": "success",
"message": "Board item deleted successfully"
}
Categories / Knowledgebase
Knowledgebase endpoints.
Retrieve list of knowledge base categories (groups).
{
"status": "success",
"message": "Groups retrieved successfully",
"data": {
"groups": [
{
"groupid": 1,
"name": "Getting Started",
"group_slug": "getting-started",
"description": "Basic information to get you started",
"active": 1,
"color": "#3b82f6",
"group_order": 1,
"articles_count": 5
},
{
"groupid": 2,
"name": "FAQ",
"group_slug": "faq",
"description": "Frequently asked questions",
"active": 1,
"color": "#10b981",
"group_order": 2,
"articles_count": 12
}
]
}
}
Create a new knowledge base category.
{
"_comment": "Required field: name",
"name": "API Documentation",
"_comment_name": "Required - Category name",
"description": "API related articles",
"_comment_description": "Optional - Category description",
"active": 1,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active (default: 1)",
"color": "#8b5cf6",
"_comment_color": "Optional - Category color (hex code)",
"group_order": 3,
"_comment_group_order": "Optional - Display order (integer)"
}
{
"status": "success",
"message": "Category created successfully",
"data": {
"id": 123
}
}
Update an existing knowledge base category.
{
"_comment": "All fields are optional - only include fields to update",
"name": "API Documentation - Updated",
"_comment_name": "Optional - Category name",
"description": "Updated description",
"_comment_description": "Optional - Category description",
"active": 0,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active",
"color": "#6366f1",
"_comment_color": "Optional - Category color",
"group_order": 4,
"_comment_group_order": "Optional - Display order"
}
{
"status": "success",
"message": "Category updated successfully"
}
Delete a knowledge base category.
{
"status": "success",
"message": "Category deleted successfully"
}
Retrieve list of knowledge base articles.
Query Parameters
| Param | Description |
groupid | Filter by category/group ID |
page | Page number |
per_page | Items per page |
{
"status": "success",
"message": "Articles retrieved successfully",
"data": {
"articles": [
{
"articleid": 1,
"subject": "How to Get Started",
"slug": "how-to-get-started",
"articlegroup": 1,
"description": "This article explains how to get started with the platform.",
"staff_article": 0,
"datecreated": "2024-01-15 10:30:00",
"article_order": 1,
"views": 150,
"active": 1
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 45,
"total_pages": 3
}
}
}
Create a new knowledge base article.
{
"_comment": "Required fields: subject, articlegroup, description",
"subject": "How to Use the API",
"_comment_subject": "Required - Article title/subject (max 191 characters)",
"articlegroup": 1,
"_comment_articlegroup": "Required - Category/group ID (integer)",
"description": "This article explains how to use the API endpoints.",
"_comment_description": "Required - Article content/description",
"staff_article": 0,
"_comment_staff_article": "Optional - Staff only article: 0=No, 1=Yes (default: 0)",
"article_order": 1,
"_comment_article_order": "Optional - Display order within category (integer)",
"active": 1,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active (default: 1)"
}
{
"status": "success",
"message": "Article created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"subject": "The subject field is required",
"articlegroup": "The articlegroup field is required",
"description": "The description field is required"
},
"code": 422
}
Retrieve a specific knowledge base article by ID.
{
"status": "success",
"message": "Article retrieved successfully",
"data": {
"articleid": 1,
"subject": "How to Get Started",
"slug": "how-to-get-started",
"articlegroup": 1,
"group_name": "Getting Started",
"description": "This article explains how to get started with the platform.",
"staff_article": 0,
"datecreated": "2024-01-15 10:30:00",
"article_order": 1,
"views": 150,
"active": 1,
"attachments": []
}
}
Update an existing knowledge base article.
{
"_comment": "All fields are optional - only include fields to update",
"subject": "How to Use the API - Updated",
"_comment_subject": "Optional - Article title (max 191 characters)",
"articlegroup": 2,
"_comment_articlegroup": "Optional - Category/group ID",
"description": "Updated article content.",
"_comment_description": "Optional - Article content",
"staff_article": 1,
"_comment_staff_article": "Optional - Staff only article: 0=No, 1=Yes",
"article_order": 2,
"_comment_article_order": "Optional - Display order",
"active": 0,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active"
}
{
"status": "success",
"message": "Article updated successfully"
}
Delete a knowledge base article.
{
"status": "success",
"message": "Article deleted successfully"
}
Leads
Lead endpoints.
Retrieve paginated list of leads with optional filtering.
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
search | Search by lead name, email, or company |
status | Filter by status ID |
source | Filter by source ID |
assigned | Filter by assigned staff ID |
{
"status": "success",
"message": "Leads retrieved successfully",
"data": {
"leads": [
{
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"phonenumber": "+1234567890",
"company": "ACME Corp",
"status": 1,
"status_name": "New",
"source": 1,
"source_name": "Website",
"assigned": 1,
"lead_value": "5000.00",
"dateadded": "2024-01-15 10:30:00",
"lastcontact": "2024-01-16 14:20:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8
}
}
}
Create a new lead.
{
"_comment": "Required fields: name, email",
"name": "John Doe",
"_comment_name": "Required - Lead name (max 100 characters)",
"email": "[email protected]",
"_comment_email": "Required - Lead email (valid email, max 100 characters)",
"phonenumber": "+1234567890",
"_comment_phonenumber": "Optional - Phone number (max 50 characters)",
"company": "ACME Corp",
"_comment_company": "Optional - Company name (max 200 characters)",
"title": "CEO",
"_comment_title": "Optional - Job title (max 100 characters)",
"website": "https://example.com",
"_comment_website": "Optional - Website URL (max 150 characters)",
"description": "Potential client for web development",
"_comment_description": "Optional - Lead description (max 65000 characters)",
"address": "123 Main St, City, State",
"_comment_address": "Optional - Address (max 200 characters)",
"city": "New York",
"_comment_city": "Optional - City (max 100 characters)",
"state": "NY",
"_comment_state": "Optional - State (max 50 characters)",
"country": 1,
"_comment_country": "Optional - Country ID (integer)",
"zip": "10001",
"_comment_zip": "Optional - ZIP code (max 15 characters)",
"status": 1,
"_comment_status": "Optional - Lead status ID (default: system default)",
"source": 1,
"_comment_source": "Optional - Lead source ID (default: system default)",
"assigned": 1,
"_comment_assigned": "Optional - Assigned staff ID (integer)",
"lead_value": 5000.00,
"_comment_lead_value": "Optional - Potential lead value (decimal)",
"is_public": false,
"_comment_is_public": "Optional - Is lead public: true/false (default: false)"
}
{
"status": "success",
"message": "Lead created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Lead with this email already exists",
"code": 400
}
Retrieve a specific lead by ID.
Query Parameters
| Param | Description |
id | Lead ID |
{
"status": "success",
"message": "Lead retrieved successfully",
"data": {
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"phonenumber": "+1234567890",
"company": "ACME Corp",
"title": "CEO",
"website": "https://example.com",
"description": "Potential client",
"address": "123 Main St",
"city": "New York",
"state": "NY",
"country": 1,
"zip": "10001",
"status": 1,
"status_name": "New",
"source": 1,
"source_name": "Website",
"assigned": 1,
"lead_value": "5000.00",
"dateadded": "2024-01-15 10:30:00",
"lastcontact": "2024-01-16 14:20:00",
"is_public": 0,
"attachments": [],
"public_url": "https://example.com/leads/public/abc123"
}
}
Update an existing lead.
Query Parameters
| Param | Description |
id | Lead ID |
{
"_comment": "All fields are optional - only include fields to update",
"name": "John Doe Updated",
"_comment_name": "Optional - Lead name (max 100 characters)",
"email": "[email protected]",
"_comment_email": "Optional - Lead email (valid email, max 100 characters)",
"phonenumber": "+1987654321",
"_comment_phonenumber": "Optional - Phone number",
"company": "ACME Corp Updated",
"_comment_company": "Optional - Company name",
"status": 2,
"_comment_status": "Optional - Lead status ID",
"source": 2,
"_comment_source": "Optional - Lead source ID",
"assigned": 2,
"_comment_assigned": "Optional - Assigned staff ID",
"lead_value": 7500.00,
"_comment_lead_value": "Optional - Potential lead value",
"is_public": true,
"_comment_is_public": "Optional - Is lead public"
}
{
"status": "success",
"message": "Lead updated successfully"
}
Delete a lead.
Query Parameters
| Param | Description |
id | Lead ID |
{
"status": "success",
"message": "Lead deleted successfully"
}
Get import template or initiate lead import process.
Query Parameters
| Param | Description |
format | Import format: 'csv', 'xlsx', 'json' (default: 'csv') |
{
"status": "success",
"message": "Import template retrieved successfully",
"data": {
"template_url": "https://example.com/templates/leads_import.csv",
"format": "csv",
"required_fields": ["name", "email"],
"optional_fields": ["phonenumber", "company", "status", "source", "assigned", "lead_value"],
"instructions": "Download the template, fill in the data, and upload via POST /api/v1/leads/import"
}
}
Convert a lead to a customer or other entity.
{
"_comment": "Optional field: convert_to",
"convert_to": "customer",
"_comment_convert_to": "Optional - Conversion type: 'customer' (default: 'customer')",
"do_not_redirect": false,
"_comment_do_not_redirect": "Optional - Do not redirect: true/false (default: false)"
}
{
"status": "success",
"message": "Lead converted successfully",
"data": {
"converted_to": "customer",
"customer_id": 123,
"redirect_url": "https://example.com/clients/client/123"
}
}
Notes
Notes endpoints.
Retrieve list of notes for a specific entity.
Query Parameters
| Param | Description |
rel_type | Related entity type (e.g., 'customer', 'lead', 'project', 'task', 'invoice', 'estimate', 'ticket') |
rel_id | Related entity ID |
page | Page number |
per_page | Items per page |
{
"status": "success",
"message": "Notes retrieved successfully",
"data": {
"notes": [
{
"id": 1,
"rel_type": "customer",
"rel_id": 123,
"description": "Customer called regarding invoice payment",
"date_contacted": "2024-01-15 10:30:00",
"addedfrom": 1,
"addedfrom_name": "John Doe",
"dateadded": "2024-01-15 10:30:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 45,
"total_pages": 3
}
}
}
Create a new note.
{
"_comment": "Required fields: rel_type, rel_id, description",
"rel_type": "customer",
"_comment_rel_type": "Required - Related entity type: 'customer', 'lead', 'project', 'task', 'invoice', 'estimate', 'ticket'",
"rel_id": 123,
"_comment_rel_id": "Required - Related entity ID (integer)",
"description": "Customer called regarding invoice payment. Will pay by end of week.",
"_comment_description": "Required - Note description/content",
"date_contacted": "2024-01-15 10:30:00",
"_comment_date_contacted": "Optional - Contact date (format: Y-m-d H:i:s)",
"is_public": 0,
"_comment_is_public": "Optional - Is note public: 0=No, 1=Yes (default: 0)"
}
{
"status": "success",
"message": "Note created successfully",
"data": {
"id": 123
}
}
Retrieve a specific note by ID.
Query Parameters
| Param | Description |
id | Note ID |
{
"status": "success",
"message": "Note retrieved successfully",
"data": {
"id": 1,
"rel_type": "customer",
"rel_id": 123,
"description": "Customer called regarding invoice payment. Will pay by end of week.",
"date_contacted": "2024-01-15 10:30:00",
"addedfrom": 1,
"addedfrom_name": "John Doe",
"dateadded": "2024-01-15 10:30:00",
"is_public": 0
}
}
Update an existing note.
Query Parameters
| Param | Description |
id | Note ID |
{
"_comment": "All fields are optional - only include fields to update",
"description": "Updated note content - Customer confirmed payment will be made.",
"_comment_description": "Optional - Note description/content",
"date_contacted": "2024-01-16 14:20:00",
"_comment_date_contacted": "Optional - Contact date (format: Y-m-d H:i:s)",
"is_public": 1,
"_comment_is_public": "Optional - Is note public: 0=No, 1=Yes"
}
{
"status": "success",
"message": "Note updated successfully"
}
Delete a note.
Query Parameters
| Param | Description |
id | Note ID |
{
"status": "success",
"message": "Note deleted successfully"
}
Notifications
Notification endpoints.
Retrieve list of notifications for the current user.
Query Parameters
| Param | Description |
is_read | Filter by read status: 0=Unread, 1=Read |
page | Page number |
per_page | Items per page |
{
"status": "success",
"message": "Notifications retrieved successfully",
"data": {
"notifications": [
{
"id": 1,
"description": "New invoice #INV-000001 created",
"date": "2024-01-15 10:30:00",
"is_read": 0,
"from_user_id": 1,
"from_user_name": "John Doe",
"from_company": null,
"link": "/invoices/list_invoices/1",
"additional_data": null
},
{
"id": 2,
"description": "Task assigned to you: Design homepage",
"date": "2024-01-15 09:15:00",
"is_read": 1,
"from_user_id": 2,
"from_user_name": "Jane Smith",
"from_company": null,
"link": "/tasks/view/5",
"additional_data": null
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 45,
"total_pages": 3
},
"unread_count": 12
}
}
Mark one or more notifications as read.
{
"_comment": "Optional fields: notification_id, mark_all",
"notification_id": 1,
"_comment_notification_id": "Optional - Specific notification ID to mark as read (integer). If not provided and mark_all is false, marks all as read.",
"mark_all": false,
"_comment_mark_all": "Optional - Mark all notifications as read: true/false (default: false)"
}
{
"status": "success",
"message": "Notification(s) marked as read successfully",
"data": {
"marked_count": 1
}
}
Clear/delete notifications for the current user.
Query Parameters
| Param | Description |
is_read | Filter by read status: 0=Unread, 1=Read (if not provided, clears all) |
{
"status": "success",
"message": "Notifications cleared successfully",
"data": {
"cleared_count": 25
}
}
Proposals
Proposal endpoints.
Retrieve paginated list of proposals with optional filtering.
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
search | Search by proposal subject |
client_id | Filter by client ID |
status | Filter by status ID |
{
"status": "success",
"message": "Proposals retrieved successfully",
"data": {
"proposals": [
{
"id": 1,
"subject": "Website Development Proposal",
"rel_type": "customer",
"rel_id": 123,
"client_name": "ACME Corp",
"date": "2024-01-15",
"open_till": "2024-02-15",
"total": "5000.00",
"status": 1,
"datecreated": "2024-01-15 10:30:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8
}
}
}
Create a new proposal.
{
"_comment": "Required fields: subject, rel_type, rel_id, date",
"subject": "Website Development Proposal",
"_comment_subject": "Required - Proposal subject/title (max 191 characters)",
"rel_type": "customer",
"_comment_rel_type": "Required - Related entity type: 'customer' or 'lead'",
"rel_id": 123,
"_comment_rel_id": "Required - Related entity ID (integer)",
"date": "2024-01-15",
"_comment_date": "Required - Proposal date (format: Y-m-d)",
"open_till": "2024-02-15",
"_comment_open_till": "Optional - Proposal expiry date (format: Y-m-d)",
"currency": 1,
"_comment_currency": "Optional - Currency ID (integer)",
"assigned": 1,
"_comment_assigned": "Optional - Assigned staff ID (integer)",
"discount_type": "percentage",
"_comment_discount_type": "Optional - Discount type: 'percentage' or 'before_tax' or 'after_tax'",
"discount_percent": 10,
"_comment_discount_percent": "Optional - Discount percentage (decimal)",
"discount_total": 500.00,
"_comment_discount_total": "Optional - Discount total amount (decimal)",
"subtotal": 5000.00,
"_comment_subtotal": "Optional - Subtotal amount (decimal)",
"total": 4500.00,
"_comment_total": "Optional - Total amount (decimal)",
"status": 1,
"_comment_status": "Optional - Proposal status ID (integer)",
"content": "Proposal content/description",
"_comment_content": "Optional - Proposal content/description"
}
{
"status": "success",
"message": "Proposal created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"subject": "The subject field is required",
"rel_type": "The rel_type field must be one of: customer, lead",
"date": "The date field is required"
},
"code": 422
}
Retrieve a specific proposal by ID.
Query Parameters
| Param | Description |
id | Proposal ID |
{
"status": "success",
"message": "Proposal retrieved successfully",
"data": {
"id": 1,
"subject": "Website Development Proposal",
"rel_type": "customer",
"rel_id": 123,
"date": "2024-01-15",
"open_till": "2024-02-15",
"total": "5000.00",
"status": 1,
"currency": 1,
"assigned": 1,
"content": "Proposal content/description",
"attachments": [],
"comments": []
}
}
Update an existing proposal.
Query Parameters
| Param | Description |
id | Proposal ID |
{
"_comment": "All fields are optional - only include fields to update",
"subject": "Website Development Proposal - Updated",
"_comment_subject": "Optional - Proposal subject (max 191 characters)",
"date": "2024-01-20",
"_comment_date": "Optional - Proposal date (format: Y-m-d)",
"open_till": "2024-02-20",
"_comment_open_till": "Optional - Proposal expiry date (format: Y-m-d)",
"status": 2,
"_comment_status": "Optional - Proposal status ID",
"total": 5500.00,
"_comment_total": "Optional - Total amount"
}
{
"status": "success",
"message": "Proposal updated successfully"
}
Delete a proposal.
Query Parameters
| Param | Description |
id | Proposal ID |
{
"status": "success",
"message": "Proposal deleted successfully"
}
Send a proposal to the client via email.
Query Parameters
| Param | Description |
id | Proposal ID |
{
"_comment": "All fields are optional",
"attach_pdf": true,
"_comment_attach_pdf": "Optional - Attach PDF to email: true/false (default: true)",
"cc": "[email protected]",
"_comment_cc": "Optional - CC email addresses (comma-separated)"
}
{
"status": "success",
"message": "Proposal sent to client successfully"
}
Retrieve all available proposal statuses.
{
"status": "success",
"message": "Proposal statuses retrieved successfully",
"data": {
"statuses": [
{
"id": 1,
"name": "Draft",
"color": "#64748b"
},
{
"id": 2,
"name": "Sent",
"color": "#3b82f6"
},
{
"id": 3,
"name": "Open",
"color": "#10b981"
},
{
"id": 4,
"name": "Accepted",
"color": "#22c55e"
},
{
"id": 5,
"name": "Declined",
"color": "#ef4444"
}
]
}
}
Income Reports
Finance report endpoints.
Retrieve income report data.
Query Parameters
| Param | Description |
year | Year for the report |
month | Month for the report (1-12) |
currency | Filter by currency ID |
{
"status": "success",
"message": "Income report retrieved successfully",
"data": {
"total_income": 125000.00,
"invoices": {
"total": 100000.00,
"count": 45,
"paid": 85000.00,
"unpaid": 15000.00
},
"payments": {
"total": 85000.00,
"count": 38,
"by_month": [
{
"month": "2024-01",
"amount": 25000.00
}
]
},
"by_currency": [
{
"currency_id": 1,
"currency_name": "USD",
"total": 125000.00
}
]
}
}
Retrieve expense report data.
Query Parameters
| Param | Description |
year | Year for the report |
category | Filter by expense category ID |
{
"status": "success",
"message": "Expenses report retrieved successfully",
"data": {
"total_expenses": 35000.00,
"expenses_vs_income": [
{
"month": "2024-01",
"income": 25000.00,
"expenses": 5000.00,
"profit": 20000.00
}
],
"by_category": [
{
"category_id": 1,
"category_name": "Office Supplies",
"total": 5000.00,
"count": 12
}
],
"category_report": {
"labels": ["Jan", "Feb", "Mar"],
"data": [5000, 6000, 7000]
}
}
}
Retrieve profit and loss report data.
Query Parameters
| Param | Description |
year | Year for the report |
month | Month for the report (1-12) |
{
"status": "success",
"message": "Profit loss report retrieved successfully",
"data": {
"total_income": 125000.00,
"total_expenses": 35000.00,
"net_profit": 90000.00,
"profit_margin": 72.00,
"by_month": [
{
"month": "2024-01",
"income": 25000.00,
"expenses": 5000.00,
"profit": 20000.00,
"margin": 80.00
}
],
"by_category": {
"income": [
{
"category": "Invoices",
"amount": 100000.00
}
],
"expenses": [
{
"category": "Office Supplies",
"amount": 5000.00
}
]
}
}
}
Retrieve project summary report data.
Query Parameters
| Param | Description |
status | Filter by project status ID |
assigned | Filter by assigned staff ID |
client_id | Filter by client ID |
{
"status": "success",
"message": "Project summary report retrieved successfully",
"data": {
"total_projects": 25,
"by_status": [
{
"status_id": 1,
"status_name": "Not Started",
"count": 5
},
{
"status_id": 2,
"status_name": "In Progress",
"count": 15
},
{
"status_id": 3,
"status_name": "On Hold",
"count": 3
},
{
"status_id": 4,
"status_name": "Completed",
"count": 2
}
],
"by_client": [
{
"client_id": 123,
"client_name": "ACME Corp",
"project_count": 5,
"total_value": 50000.00
}
],
"by_staff": [
{
"staff_id": 1,
"staff_name": "John Doe",
"project_count": 10,
"completed": 8
}
],
"total_value": 250000.00,
"completed_value": 150000.00
}
}
Retrieve tasks summary report data.
Query Parameters
| Param | Description |
status | Filter by task status ID |
assigned | Filter by assigned staff ID |
project_id | Filter by project ID |
{
"status": "success",
"message": "Tasks summary report retrieved successfully",
"data": {
"total_tasks": 150,
"by_status": [
{
"status_id": 1,
"status_name": "Not Started",
"count": 30
},
{
"status_id": 2,
"status_name": "In Progress",
"count": 80
},
{
"status_id": 3,
"status_name": "Testing",
"count": 20
},
{
"status_id": 4,
"status_name": "Awaiting Feedback",
"count": 10
},
{
"status_id": 5,
"status_name": "Complete",
"count": 10
}
],
"by_priority": [
{
"priority": 1,
"priority_name": "Low",
"count": 50
},
{
"priority": 2,
"priority_name": "Medium",
"count": 70
},
{
"priority": 3,
"priority_name": "High",
"count": 25
},
{
"priority": 4,
"priority_name": "Urgent",
"count": 5
}
],
"by_staff": [
{
"staff_id": 1,
"staff_name": "John Doe",
"total": 50,
"completed": 40,
"in_progress": 8,
"not_started": 2
}
],
"overdue": 5,
"due_today": 10,
"due_this_week": 25
}
}
Roles
Role endpoints.
Retrieve list of all roles.
{
"status": "success",
"message": "Roles retrieved successfully",
"data": {
"roles": [
{
"roleid": 1,
"name": "Administrator",
"permissions": {}
},
{
"roleid": 2,
"name": "Manager",
"permissions": {
"customers": {
"view": true,
"create": true,
"edit": true,
"delete": false
}
}
}
]
}
}
Create a new role.
{
"_comment": "Required field: name",
"name": "Sales Representative",
"_comment_name": "Required - Role name (max 50 characters)",
"permissions": {
"_comment_permissions": "Optional - Role permissions object",
"customers": {
"view": true,
"create": true,
"edit": true,
"delete": false
},
"invoices": {
"view": true,
"create": true,
"edit": false,
"delete": false
}
}
}
{
"status": "success",
"message": "Role created successfully",
"data": {
"id": 123
}
}
Retrieve a specific role by ID.
Query Parameters
| Param | Description |
id | Role ID |
{
"status": "success",
"message": "Role retrieved successfully",
"data": {
"roleid": 2,
"name": "Manager",
"permissions": {
"customers": {
"view": true,
"create": true,
"edit": true,
"delete": false
}
}
}
}
Update an existing role.
Query Parameters
| Param | Description |
id | Role ID |
{
"_comment": "All fields are optional - only include fields to update",
"name": "Sales Representative - Updated",
"_comment_name": "Optional - Role name (max 50 characters)",
"permissions": {
"_comment_permissions": "Optional - Role permissions object",
"customers": {
"view": true,
"create": true,
"edit": true,
"delete": true
}
}
}
{
"status": "success",
"message": "Role updated successfully"
}
Delete a role.
Query Parameters
| Param | Description |
id | Role ID |
{
"status": "success",
"message": "Role deleted successfully"
}
General Settings
General settings endpoints.
Retrieve general settings.
{
"status": "success",
"message": "Settings retrieved successfully",
"data": {
"company_name": "Zealdash CRM",
"company_logo": "logo.png",
"company_logo_dark": "logo_dark.png",
"favicon": "favicon.ico",
"admin_area_title": "Zealdash Admin",
"clients_area_title": "Zealdash Client Portal",
"company_phonenumber": "+1234567890",
"company_address": "123 Main St",
"company_city": "New York",
"company_state": "NY",
"company_zip": "10001",
"company_country": 1,
"company_vat": "VAT123456",
"company_website": "https://example.com",
"default_language": "english",
"active_language": "english",
"timezone": "America/New_York",
"date_format": "d/m/Y",
"time_format": "H:i"
}
}
Update general settings.
{
"_comment": "All fields are optional - only include fields to update",
"company_name": "Updated Company Name",
"_comment_company_name": "Optional - Company name (max 200 characters)",
"company_phonenumber": "+1987654321",
"_comment_company_phonenumber": "Optional - Phone number (max 50 characters)",
"company_address": "456 Oak Ave",
"_comment_company_address": "Optional - Address (max 500 characters)",
"company_city": "Los Angeles",
"_comment_company_city": "Optional - City",
"company_state": "CA",
"_comment_company_state": "Optional - State",
"company_zip": "90210",
"_comment_company_zip": "Optional - ZIP code",
"company_country": 1,
"_comment_company_country": "Optional - Country ID",
"default_language": "english",
"_comment_default_language": "Optional - Default language",
"timezone": "America/Los_Angeles",
"_comment_timezone": "Optional - Timezone (must be valid timezone identifier)",
"date_format": "m/d/Y",
"_comment_date_format": "Optional - Date format: 'd/m/Y', 'm/d/Y', 'Y/m/d', etc.",
"time_format": "g:i A",
"_comment_time_format": "Optional - Time format: 'H:i', 'g:i A', 'g:i a'"
}
{
"status": "success",
"message": "Settings updated successfully",
"data": {
"updated_count": 5
}
}
Retrieve invoice-related settings.
{
"status": "success",
"message": "Settings retrieved successfully",
"data": {
"invoice_prefix": "INV-",
"invoice_number_format": "{number}",
"next_invoice_number": 1001,
"invoice_due_after": 30,
"default_tax": 0,
"invoice_auto_operations_hour": 9,
"invoice_reminders_enabled": true,
"invoice_reminder_days": [7, 3, 1]
}
}
Update invoice-related settings.
{
"_comment": "All fields are optional - only include fields to update",
"invoice_prefix": "INV-",
"_comment_invoice_prefix": "Optional - Invoice number prefix",
"invoice_number_format": "{number}",
"_comment_invoice_number_format": "Optional - Invoice number format",
"next_invoice_number": 1001,
"_comment_next_invoice_number": "Optional - Next invoice number (integer)",
"invoice_due_after": 30,
"_comment_invoice_due_after": "Optional - Days until invoice due (integer)",
"default_tax": 0,
"_comment_default_tax": "Optional - Default tax ID (integer)",
"invoice_auto_operations_hour": 9,
"_comment_invoice_auto_operations_hour": "Optional - Auto operations hour (0-23)"
}
{
"status": "success",
"message": "Settings updated successfully"
}
Retrieve email-related settings.
{
"status": "success",
"message": "Settings retrieved successfully",
"data": {
"mail_engine": "smtp",
"smtp_host": "smtp.gmail.com",
"smtp_port": "587",
"smtp_username": "[email protected]",
"smtp_password": "********",
"smtp_encryption": "tls",
"email_header": "Email header content",
"email_footer": "Email footer content",
"email_signature": "Best regards",
"bcc_emails": ""
}
}
Update email-related settings.
{
"_comment": "All fields are optional - only include fields to update",
"mail_engine": "smtp",
"_comment_mail_engine": "Optional - Mail engine: 'smtp' or 'sendmail'",
"smtp_host": "smtp.example.com",
"_comment_smtp_host": "Optional - SMTP host",
"smtp_port": "465",
"_comment_smtp_port": "Optional - SMTP port (1-65535)",
"smtp_username": "[email protected]",
"_comment_smtp_username": "Optional - SMTP username",
"smtp_password": "newpassword",
"_comment_smtp_password": "Optional - SMTP password",
"smtp_encryption": "ssl",
"_comment_smtp_encryption": "Optional - SMTP encryption: 'tls', 'ssl', or ''",
"email_header": "Updated header",
"_comment_email_header": "Optional - Email header content",
"email_footer": "Updated footer",
"_comment_email_footer": "Optional - Email footer content",
"email_signature": "Best regards,\nTeam",
"_comment_email_signature": "Optional - Email signature",
"bcc_emails": "[email protected]",
"_comment_bcc_emails": "Optional - BCC email addresses (comma-separated)"
}
{
"status": "success",
"message": "Settings updated successfully"
}
Staff
Staff endpoints.
Retrieve paginated list of staff members with optional filtering.
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
search | Search by staff name or email |
active | Filter by active status: 0=Inactive, 1=Active |
{
"status": "success",
"message": "Staff retrieved successfully",
"data": {
"staff": [
{
"staffid": 1,
"email": "[email protected]",
"firstname": "John",
"lastname": "Doe",
"phonenumber": "+1234567890",
"facebook": "john.doe",
"linkedin": "john-doe",
"skype": "john.doe",
"role": 1,
"active": 1,
"profile_image": "profile.jpg",
"last_ip": "192.168.1.1",
"last_login": "2024-01-15 10:30:00",
"last_activity": "2024-01-15 11:45:00",
"datecreated": "2024-01-01 09:00:00",
"hourly_rate": "50.00",
"email_signature": "Best regards,\nJohn Doe"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 25,
"total_pages": 2
}
}
}
Create a new staff member.
{
"_comment": "Required fields: firstname, lastname, email, password",
"firstname": "Jane",
"_comment_firstname": "Required - First name (max 50 characters)",
"lastname": "Smith",
"_comment_lastname": "Required - Last name (max 50 characters)",
"email": "[email protected]",
"_comment_email": "Required - Email address (valid email, must be unique)",
"password": "securepassword123",
"_comment_password": "Required - Password (min 6 characters)",
"phonenumber": "+1987654321",
"_comment_phonenumber": "Optional - Phone number (max 50 characters)",
"facebook": "jane.smith",
"_comment_facebook": "Optional - Facebook username (max 100 characters)",
"linkedin": "jane-smith",
"_comment_linkedin": "Optional - LinkedIn username (max 100 characters)",
"skype": "jane.smith",
"_comment_skype": "Optional - Skype username (max 100 characters)",
"role": 2,
"_comment_role": "Optional - Role ID (integer)",
"active": true,
"_comment_active": "Optional - Active status: true/false (default: true)",
"hourly_rate": 45.00,
"_comment_hourly_rate": "Optional - Hourly rate (decimal)",
"email_signature": "Best regards,\nJane Smith",
"_comment_email_signature": "Optional - Email signature",
"direction": "ltr",
"_comment_direction": "Optional - Text direction: 'ltr' or 'rtl' (default: 'ltr')",
"send_welcome_email": true,
"_comment_send_welcome_email": "Optional - Send welcome email: true/false (default: false)",
"permissions": ["customers.view", "invoices.view"],
"_comment_permissions": "Optional - Array of permission strings"
}
{
"status": "success",
"message": "Staff member created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"email": "The email field must contain a unique value",
"password": "The password field must be at least 6 characters in length"
},
"code": 400
}
Retrieve a specific staff member by ID.
Query Parameters
| Param | Description |
id | Staff ID |
{
"status": "success",
"message": "Staff member retrieved successfully",
"data": {
"staffid": 1,
"email": "[email protected]",
"firstname": "John",
"lastname": "Doe",
"phonenumber": "+1234567890",
"role": 1,
"active": 1,
"hourly_rate": "50.00",
"permissions": {}
}
}
Update an existing staff member.
Query Parameters
| Param | Description |
id | Staff ID |
{
"_comment": "All fields are optional - only include fields to update",
"firstname": "Jane Updated",
"_comment_firstname": "Optional - First name (max 50 characters)",
"lastname": "Smith Updated",
"_comment_lastname": "Optional - Last name (max 50 characters)",
"email": "[email protected]",
"_comment_email": "Optional - Email address (valid email, must be unique if changed)",
"password": "newpassword123",
"_comment_password": "Optional - New password (min 6 characters)",
"phonenumber": "+1555123456",
"_comment_phonenumber": "Optional - Phone number",
"role": 3,
"_comment_role": "Optional - Role ID",
"active": false,
"_comment_active": "Optional - Active status: true/false",
"hourly_rate": 55.00,
"_comment_hourly_rate": "Optional - Hourly rate"
}
{
"status": "success",
"message": "Staff member updated successfully"
}
Delete a staff member. Cannot delete your own account.
Query Parameters
| Param | Description |
id | Staff ID |
{
"status": "success",
"message": "Staff member deleted successfully"
}
{
"status": "error",
"message": "Cannot delete your own account",
"code": 400
}
Retrieve permissions for a specific staff member.
Query Parameters
| Param | Description |
staff_id | Staff ID (if not provided, returns current user's permissions) |
{
"status": "success",
"message": "Staff permissions retrieved successfully",
"data": {
"staff_id": 1,
"staff_name": "John Doe",
"role_id": 1,
"role_name": "Administrator",
"permissions": {
"customers": {
"view": true,
"create": true,
"edit": true,
"delete": true
},
"invoices": {
"view": true,
"create": true,
"edit": true,
"delete": true
},
"projects": {
"view": true,
"create": true,
"edit": true,
"delete": true
}
}
}
}
Tickets
Ticket endpoints.
Retrieve paginated list of support tickets with optional filtering.
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
search | Search by subject or ticket ID |
status | Filter by status ID |
department | Filter by department ID |
{
"status": "success",
"message": "Tickets loaded",
"data": {
"tickets": [
{
"id": 1,
"subject": "Website login issue",
"date": "2024-01-15 10:30:00",
"lastreply": "2024-01-15 14:20:00",
"userid": 123,
"status": 1,
"status_name": "Open",
"priority": 2,
"priority_name": "High",
"department_name": "Technical Support"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8
}
}
}
Create a new support ticket.
{
"_comment": "Required fields: subject, department, message",
"subject": "Website login issue",
"_comment_subject": "Required - Ticket subject (max 191 characters)",
"department": 1,
"_comment_department": "Required - Department ID (integer)",
"priority": 2,
"_comment_priority": "Optional - Priority ID (integer)",
"status": 1,
"_comment_status": "Optional - Status ID (integer)",
"message": "I am unable to log in to the website. Getting an error message.",
"_comment_message": "Required - Ticket message/description",
"userid": 123,
"_comment_userid": "Optional - User/Client ID (integer)",
"contactid": 456,
"_comment_contactid": "Optional - Contact ID (integer)"
}
{
"status": "success",
"message": "Ticket created successfully",
"data": {
"id": 123
}
}
Retrieve a specific ticket by ID with full details and replies.
Query Parameters
| Param | Description |
id | Ticket ID |
{
"status": "success",
"message": "Ticket loaded",
"data": {
"ticket": {
"ticketid": 1,
"subject": "Website login issue",
"date": "2024-01-15 10:30:00",
"userid": 123,
"status": 1,
"priority": 2,
"department": 1,
"message": "I am unable to log in to the website."
},
"replies": [
{
"replyid": 1,
"ticketid": 1,
"message": "We are looking into this issue.",
"admin": 1,
"date": "2024-01-15 11:00:00"
}
]
}
}
Update an existing ticket.
Query Parameters
| Param | Description |
id | Ticket ID |
{
"_comment": "All fields are optional - only include fields to update",
"subject": "Website login issue - Resolved",
"_comment_subject": "Optional - Ticket subject (max 191 characters)",
"department": 2,
"_comment_department": "Optional - Department ID",
"priority": 1,
"_comment_priority": "Optional - Priority ID",
"status": 3,
"_comment_status": "Optional - Status ID"
}
{
"status": "success",
"message": "Ticket updated successfully"
}
Delete a ticket.
Query Parameters
| Param | Description |
id | Ticket ID |
{
"status": "success",
"message": "Ticket deleted successfully"
}
{
"status": "error",
"message": "Ticket not found",
"code": 404
}
Retrieve all available ticket statuses.
{
"status": "success",
"message": "Ticket statuses retrieved successfully",
"data": {
"statuses": [
{
"ticketstatusid": 1,
"name": "Open",
"statuscolor": "#28a745",
"statusorder": 1,
"isdefault": 1
},
{
"ticketstatusid": 2,
"name": "In Progress",
"statuscolor": "#ffc107",
"statusorder": 2,
"isdefault": 0
},
{
"ticketstatusid": 3,
"name": "Answered",
"statuscolor": "#17a2b8",
"statusorder": 3,
"isdefault": 0
},
{
"ticketstatusid": 4,
"name": "Closed",
"statuscolor": "#6c757d",
"statusorder": 4,
"isdefault": 0
}
]
}
}
Add a reply to a ticket.
Query Parameters
| Param | Description |
id | Ticket ID |
{
"_comment": "Required field: message",
"message": "Thank you for your inquiry. We are looking into this issue and will get back to you shortly.",
"_comment_message": "Required - Reply message/content",
"admin": 1,
"_comment_admin": "Optional - Staff ID who is replying (default: current user)",
"attachments": [],
"_comment_attachments": "Optional - Array of attachment file IDs"
}
{
"status": "success",
"message": "Reply added successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"message": "The message field is required"
},
"code": 422
}
Time Logs
Time log endpoints.
Retrieve time logs with optional filtering.
Query Parameters
| Param | Description |
task_id | Filter by task ID |
project_id | Filter by project ID |
staff_id | Filter by staff ID |
start_date | Filter by start date (format: Y-m-d) |
end_date | Filter by end date (format: Y-m-d) |
page | Page number |
per_page | Items per page |
{
"status": "success",
"message": "Time logs retrieved successfully",
"data": {
"logs": [
{
"id": 1,
"task_id": 5,
"project_id": 2,
"staff_id": 1,
"staff_name": "John Doe",
"start_time": "2024-01-15 09:00:00",
"end_time": "2024-01-15 12:30:00",
"note": "Working on feature implementation",
"hours": 3.5,
"billable": 1,
"hourly_rate": 50.00,
"date": "2024-01-15"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 45,
"total_pages": 3
}
}
}
Start a timer for a task or project.
{
"_comment": "Required field: task_id or project_id",
"task_id": 5,
"_comment_task_id": "Required if project_id not provided - Task ID (integer)",
"project_id": 2,
"_comment_project_id": "Required if task_id not provided - Project ID (integer)",
"note": "Starting work on feature implementation",
"_comment_note": "Optional - Note/description for the time entry"
}
{
"status": "success",
"message": "Timer started successfully",
"data": {
"id": 123,
"start_time": "2024-01-15 14:30:00",
"task_id": 5,
"project_id": 2
}
}
{
"status": "error",
"message": "Either task_id or project_id is required",
"code": 400
}
Stop the currently running timer for the current user.
{
"_comment": "Optional field: note",
"note": "Completed feature implementation",
"_comment_note": "Optional - Note/description for the time entry"
}
{
"status": "success",
"message": "Timer stopped successfully",
"data": {
"id": 123,
"start_time": "2024-01-15 14:30:00",
"end_time": "2024-01-15 17:45:00",
"hours": 3.25,
"task_id": 5,
"project_id": 2
}
}
{
"status": "error",
"message": "No active timer found",
"code": 400
}
Create a manual time entry (not from a timer).
{
"_comment": "Required fields: task_id or project_id, date, hours",
"task_id": 5,
"_comment_task_id": "Required if project_id not provided - Task ID (integer)",
"project_id": 2,
"_comment_project_id": "Required if task_id not provided - Project ID (integer)",
"date": "2024-01-15",
"_comment_date": "Required - Date of time entry (format: Y-m-d)",
"hours": 3.5,
"_comment_hours": "Required - Number of hours worked (decimal)",
"note": "Manual entry for completed work",
"_comment_note": "Optional - Note/description for the time entry",
"billable": true,
"_comment_billable": "Optional - Is time entry billable: true/false (default: true)",
"hourly_rate": 50.00,
"_comment_hourly_rate": "Optional - Hourly rate for billing (decimal)"
}
{
"status": "success",
"message": "Time entry created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"date": "The date field is required",
"hours": "The hours field is required"
},
"code": 422
}
Delete a time entry.
Query Parameters
| Param | Description |
id | Time entry ID |
{
"status": "success",
"message": "Time entry deleted successfully"
}
{
"status": "error",
"message": "Time entry not found",
"code": 404
}
Users
User endpoints.
Retrieve paginated list of users (client contacts).
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
search | Search by name or email |
active | Filter by active status: 0=Inactive, 1=Active |
client_id | Filter by client ID |
{
"status": "success",
"message": "Users retrieved successfully",
"data": {
"users": [
{
"id": 1,
"userid": 123,
"firstname": "John",
"lastname": "Doe",
"email": "[email protected]",
"phonenumber": "+1234567890",
"title": "CEO",
"client_id": 123,
"client_name": "ACME Corp",
"active": 1,
"is_primary": 1,
"last_login": "2024-01-15 10:30:00",
"datecreated": "2024-01-01 09:00:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8
}
}
}
Create a new user (client contact).
{
"_comment": "Required fields: firstname, lastname, email, client_id",
"firstname": "Jane",
"_comment_firstname": "Required - First name (max 50 characters)",
"lastname": "Smith",
"_comment_lastname": "Required - Last name (max 50 characters)",
"email": "[email protected]",
"_comment_email": "Required - Email address (valid email, max 100 characters)",
"client_id": 123,
"_comment_client_id": "Required - Client ID (integer)",
"phonenumber": "+1987654321",
"_comment_phonenumber": "Optional - Phone number (max 50 characters)",
"title": "CTO",
"_comment_title": "Optional - Job title (max 100 characters)",
"password": "securepassword123",
"_comment_password": "Optional - Password (min 6 characters). If not provided, a random password will be generated.",
"active": 1,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active (default: 1)",
"is_primary": 0,
"_comment_is_primary": "Optional - Is primary contact: 0=No, 1=Yes (default: 0)",
"send_set_password_email": true,
"_comment_send_set_password_email": "Optional - Send password setup email: true/false (default: false)"
}
{
"status": "success",
"message": "User created successfully",
"data": {
"id": 123
}
}
{
"status": "error",
"message": "User with this email already exists",
"code": 400
}
Retrieve a specific user (client contact) by ID.
Query Parameters
| Param | Description |
id | User ID |
{
"status": "success",
"message": "User retrieved successfully",
"data": {
"id": 1,
"userid": 123,
"firstname": "John",
"lastname": "Doe",
"email": "[email protected]",
"phonenumber": "+1234567890",
"title": "CEO",
"client_id": 123,
"client_name": "ACME Corp",
"active": 1,
"is_primary": 1,
"last_login": "2024-01-15 10:30:00",
"datecreated": "2024-01-01 09:00:00",
"permissions": []
}
}
Update an existing user (client contact).
Query Parameters
| Param | Description |
id | User ID |
{
"_comment": "All fields are optional - only include fields to update",
"firstname": "Jane",
"_comment_firstname": "Optional - First name (max 50 characters)",
"lastname": "Smith Updated",
"_comment_lastname": "Optional - Last name (max 50 characters)",
"email": "[email protected]",
"_comment_email": "Optional - Email address (valid email, max 100 characters)",
"phonenumber": "+1555123456",
"_comment_phonenumber": "Optional - Phone number",
"title": "CTO",
"_comment_title": "Optional - Job title",
"password": "newpassword123",
"_comment_password": "Optional - New password (min 6 characters)",
"active": 0,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active",
"is_primary": 1,
"_comment_is_primary": "Optional - Is primary contact: 0=No, 1=Yes"
}
{
"status": "success",
"message": "User updated successfully"
}
Delete a user (client contact).
Query Parameters
| Param | Description |
id | User ID |
{
"status": "success",
"message": "User deleted successfully"
}
{
"status": "error",
"message": "Cannot delete primary contact",
"code": 400
}
Webhooks
Webhook endpoints.
Retrieve paginated list of webhooks.
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
active | Filter by active status: 0=Inactive, 1=Active |
{
"status": "success",
"message": "Webhooks retrieved successfully",
"data": {
"webhooks": [
{
"id": 1,
"name": "Invoice Created",
"url": "https://example.com/webhooks/invoice-created",
"events": ["invoice.created", "invoice.updated"],
"active": 1,
"secret": "whsec_abc123...",
"datecreated": "2024-01-15 10:30:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 10,
"total_pages": 1
}
}
}
Create a new webhook.
{
"_comment": "Required fields: name, url, events",
"name": "Invoice Created",
"_comment_name": "Required - Webhook name (max 100 characters)",
"url": "https://example.com/webhooks/invoice-created",
"_comment_url": "Required - Webhook URL (valid URL)",
"events": ["invoice.created", "invoice.updated", "invoice.deleted"],
"_comment_events": "Required - Array of event names to subscribe to",
"active": 1,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active (default: 1)",
"secret": "whsec_abc123...",
"_comment_secret": "Optional - Webhook secret for signature verification. If not provided, one will be generated."
}
{
"status": "success",
"message": "Webhook created successfully",
"data": {
"id": 123,
"secret": "whsec_abc123..."
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"name": "The name field is required",
"url": "The url field is required",
"events": "The events field is required"
},
"code": 422
}
Retrieve a specific webhook by ID.
Query Parameters
| Param | Description |
id | Webhook ID |
{
"status": "success",
"message": "Webhook retrieved successfully",
"data": {
"id": 1,
"name": "Invoice Created",
"url": "https://example.com/webhooks/invoice-created",
"events": ["invoice.created", "invoice.updated"],
"active": 1,
"secret": "whsec_abc123...",
"datecreated": "2024-01-15 10:30:00",
"last_triggered": "2024-01-16 14:20:00",
"total_requests": 45,
"successful_requests": 43,
"failed_requests": 2
}
}
Update an existing webhook.
Query Parameters
| Param | Description |
id | Webhook ID |
{
"_comment": "All fields are optional - only include fields to update",
"name": "Invoice Created - Updated",
"_comment_name": "Optional - Webhook name (max 100 characters)",
"url": "https://example.com/webhooks/invoice-created-updated",
"_comment_url": "Optional - Webhook URL (valid URL)",
"events": ["invoice.created", "invoice.updated", "invoice.paid"],
"_comment_events": "Optional - Array of event names to subscribe to",
"active": 0,
"_comment_active": "Optional - Active status: 0=Inactive, 1=Active"
}
{
"status": "success",
"message": "Webhook updated successfully"
}
Delete a webhook.
Query Parameters
| Param | Description |
id | Webhook ID |
{
"status": "success",
"message": "Webhook deleted successfully"
}
Audit Logs
Audit log endpoints.
Retrieve paginated list of audit logs.
Query Parameters
| Param | Description |
page | Page number |
per_page | Items per page |
user_id | Filter by user ID |
action | Filter by action (e.g., 'create', 'update', 'delete', 'view') |
date_from | Filter from date (format: Y-m-d) |
date_to | Filter to date (format: Y-m-d) |
entity_type | Filter by entity type (e.g., 'invoice', 'client', 'project') |
{
"status": "success",
"message": "Audit logs retrieved successfully",
"data": {
"logs": [
{
"id": 1,
"user_id": 1,
"user_name": "John Doe",
"action": "create",
"entity_type": "invoice",
"entity_id": 123,
"description": "Invoice #INV-000001 created",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"date": "2024-01-15 10:30:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 500,
"total_pages": 25
}
}
}
Retrieve a specific audit log entry by ID.
Query Parameters
| Param | Description |
id | Audit log ID |
{
"status": "success",
"message": "Audit log retrieved successfully",
"data": {
"id": 1,
"user_id": 1,
"user_name": "John Doe",
"action": "create",
"entity_type": "invoice",
"entity_id": 123,
"description": "Invoice #INV-000001 created",
"old_values": null,
"new_values": {
"number": "INV-000001",
"client_id": 123,
"total": 5000.00
},
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"date": "2024-01-15 10:30:00"
}
}
Import APIs
Import endpoints.
Import clients from a file (CSV, XLSX, or JSON).
Request Body (multipart/form-data):
file: [file upload]
format: csv (optional, default: auto-detect)
skip_duplicates: true (optional, default: false)
update_existing: false (optional, default: false)
Request Body (JSON alternative):
{
"_comment": "Required field: file or data",
"file": "base64_encoded_file_content",
"_comment_file": "Optional - Base64 encoded file content (if not using multipart/form-data)",
"format": "csv",
"_comment_format": "Optional - File format: 'csv', 'xlsx', 'json' (default: auto-detect)",
"skip_duplicates": true,
"_comment_skip_duplicates": "Optional - Skip duplicate records: true/false (default: false)",
"update_existing": false,
"_comment_update_existing": "Optional - Update existing records: true/false (default: false)",
"data": [
{
"company": "ACME Corp",
"email": "[email protected]",
"phonenumber": "+1234567890"
}
],
"_comment_data": "Optional - Direct JSON data array (if not using file upload)"
}
{
"status": "success",
"message": "Import completed successfully",
"data": {
"imported": 50,
"updated": 5,
"failed": 2,
"errors": [
{
"row": 5,
"error": "Invalid email format"
}
]
}
}
Import leads from a file (CSV, XLSX, or JSON).
Request Body (multipart/form-data):
file: [file upload]
format: csv (optional, default: auto-detect)
skip_duplicates: true (optional, default: false)
update_existing: false (optional, default: false)
Request Body (JSON alternative):
{
"_comment": "Required field: file or data",
"file": "base64_encoded_file_content",
"_comment_file": "Optional - Base64 encoded file content",
"format": "csv",
"_comment_format": "Optional - File format: 'csv', 'xlsx', 'json'",
"skip_duplicates": true,
"_comment_skip_duplicates": "Optional - Skip duplicate records",
"update_existing": false,
"_comment_update_existing": "Optional - Update existing records",
"data": [
{
"name": "John Doe",
"email": "[email protected]",
"company": "ACME Corp",
"phonenumber": "+1234567890"
}
],
"_comment_data": "Optional - Direct JSON data array"
}
{
"status": "success",
"message": "Import completed successfully",
"data": {
"imported": 75,
"updated": 3,
"failed": 1,
"errors": []
}
}
Import products/items from a file (CSV, XLSX, or JSON).
Request Body (multipart/form-data):
file: [file upload]
format: csv (optional, default: auto-detect)
skip_duplicates: true (optional, default: false)
update_existing: false (optional, default: false)
Request Body (JSON alternative):
{
"_comment": "Required field: file or data",
"file": "base64_encoded_file_content",
"_comment_file": "Optional - Base64 encoded file content",
"format": "csv",
"_comment_format": "Optional - File format: 'csv', 'xlsx', 'json'",
"skip_duplicates": true,
"_comment_skip_duplicates": "Optional - Skip duplicate records",
"update_existing": false,
"_comment_update_existing": "Optional - Update existing records",
"data": [
{
"description": "Web Development Service",
"rate": 100.00,
"tax": 1
}
],
"_comment_data": "Optional - Direct JSON data array"
}
{
"status": "success",
"message": "Import completed successfully",
"data": {
"imported": 30,
"updated": 2,
"failed": 0,
"errors": []
}
}
Import staff members from a file (CSV, XLSX, or JSON).
Request Body (multipart/form-data):
file: [file upload]
format: csv (optional, default: auto-detect)
skip_duplicates: true (optional, default: false)
update_existing: false (optional, default: false)
send_welcome_email: false (optional, default: false)
Request Body (JSON alternative):
{
"_comment": "Required field: file or data",
"file": "base64_encoded_file_content",
"_comment_file": "Optional - Base64 encoded file content",
"format": "csv",
"_comment_format": "Optional - File format: 'csv', 'xlsx', 'json'",
"skip_duplicates": true,
"_comment_skip_duplicates": "Optional - Skip duplicate records",
"update_existing": false,
"_comment_update_existing": "Optional - Update existing records",
"send_welcome_email": false,
"_comment_send_welcome_email": "Optional - Send welcome email to imported staff: true/false",
"data": [
{
"firstname": "Jane",
"lastname": "Smith",
"email": "[email protected]",
"role": 2
}
],
"_comment_data": "Optional - Direct JSON data array"
}
{
"status": "success",
"message": "Import completed successfully",
"data": {
"imported": 20,
"updated": 1,
"failed": 0,
"errors": []
}
}
Export APIs
Export endpoints.
Export clients to a file (CSV, XLSX, or JSON).
Query Parameters
| Param | Description |
format | Export format: 'csv', 'xlsx', 'json' (default: 'csv') |
status | Filter by status: 0=Inactive, 1=Active |
date_from | Filter from date (format: Y-m-d) |
date_to | Filter to date (format: Y-m-d) |
Content-Type: application/csv (or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet for XLSX, or application/json)
Content-Disposition: attachment; filename="clients_export_2024-01-15.csv"
[File content]
Export leads to a file (CSV, XLSX, or JSON).
Query Parameters
| Param | Description |
format | Export format: 'csv', 'xlsx', 'json' (default: 'csv') |
status | Filter by status ID |
source | Filter by source ID |
date_from | Filter from date (format: Y-m-d) |
date_to | Filter to date (format: Y-m-d) |
Content-Type: application/csv
Content-Disposition: attachment; filename="leads_export_2024-01-15.csv"
[File content]
Export invoices to a file (CSV, XLSX, or JSON).
Query Parameters
| Param | Description |
format | Export format: 'csv', 'xlsx', 'json' (default: 'csv') |
status | Filter by status ID |
client_id | Filter by client ID |
date_from | Filter from date (format: Y-m-d) |
date_to | Filter to date (format: Y-m-d) |
Content-Type: application/csv
Content-Disposition: attachment; filename="invoices_export_2024-01-15.csv"
[File content]
System APIs
System health/info endpoints.
Check the health status of the system, including database connectivity, cache status, and other critical services.
{
"status": "success",
"message": "System health check completed",
"data": {
"status": "healthy",
"timestamp": "2024-01-15 10:30:00",
"services": {
"database": {
"status": "connected",
"response_time_ms": 5
},
"cache": {
"status": "connected",
"response_time_ms": 2
},
"storage": {
"status": "accessible",
"disk_usage_percent": 45
},
"queue": {
"status": "running",
"pending_jobs": 3
}
},
"version": "1.0.0",
"uptime_seconds": 86400
}
}
Retrieve system information including version, PHP version, database version, and other system details.
{
"status": "success",
"message": "System information retrieved successfully",
"data": {
"application": {
"name": "Zealdash CRM",
"version": "1.0.0",
"environment": "production",
"timezone": "America/New_York"
},
"server": {
"php_version": "8.1.0",
"server_software": "Apache/2.4.41",
"operating_system": "Linux",
"server_time": "2024-01-15 10:30:00"
},
"database": {
"type": "MySQL",
"version": "8.0.28",
"charset": "utf8mb4",
"collation": "utf8mb4_unicode_ci"
},
"features": {
"multitenancy": true,
"api_enabled": true,
"webhooks_enabled": true,
"audit_logs_enabled": true
},
"limits": {
"max_upload_size": "10M",
"max_execution_time": 300,
"memory_limit": "256M"
}
}
}
Support
Support endpoints.
Submit a support request or contact support team.
{
"_comment": "Required fields: subject, message",
"subject": "Issue with invoice generation",
"_comment_subject": "Required - Support request subject (max 200 characters)",
"message": "I'm experiencing an issue where invoices are not being generated correctly. The PDF format seems corrupted.",
"_comment_message": "Required - Support request message/description",
"priority": "medium",
"_comment_priority": "Optional - Priority level: 'low', 'medium', 'high', 'urgent' (default: 'medium')",
"category": "technical",
"_comment_category": "Optional - Category: 'technical', 'billing', 'feature_request', 'bug_report', 'other' (default: 'other')",
"attachments": [],
"_comment_attachments": "Optional - Array of attachment file IDs or URLs",
"contact_email": "[email protected]",
"_comment_contact_email": "Optional - Contact email (default: authenticated user's email)",
"contact_phone": "+1234567890",
"_comment_contact_phone": "Optional - Contact phone number"
}
{
"status": "success",
"message": "Support request submitted successfully",
"data": {
"ticket_id": "SUP-12345",
"reference_number": "REF-20240115-001",
"estimated_response_time": "24 hours"
}
}
{
"status": "error",
"message": "Validation failed",
"errors": {
"subject": "The subject field is required",
"message": "The message field is required"
},
"code": 422
}
Retrieve list of support tickets submitted by the current user or tenant.
Query Parameters
| Param | Description |
status | Filter by status: 'open', 'pending', 'resolved', 'closed' |
page | Page number |
per_page | Items per page |
search | Search by subject or ticket ID |
{
"status": "success",
"message": "Support tickets retrieved successfully",
"data": {
"tickets": [
{
"id": "SUP-12345",
"reference_number": "REF-20240115-001",
"subject": "Issue with invoice generation",
"message": "I'm experiencing an issue where invoices are not being generated correctly.",
"status": "open",
"priority": "medium",
"category": "technical",
"created_at": "2024-01-15 10:30:00",
"updated_at": "2024-01-15 10:30:00",
"resolved_at": null,
"response_count": 0
},
{
"id": "SUP-12344",
"reference_number": "REF-20240114-002",
"subject": "Feature request: Export functionality",
"message": "Would like to request export functionality for reports.",
"status": "resolved",
"priority": "low",
"category": "feature_request",
"created_at": "2024-01-14 14:20:00",
"updated_at": "2024-01-15 09:15:00",
"resolved_at": "2024-01-15 09:15:00",
"response_count": 3
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 5,
"total_pages": 1
}
}
}
Locations
Countries/states/cities/timezones endpoints.
Retrieve list of countries.
Query Parameters
| Param | Description |
search | Search countries by name or code |
{
"status": "success",
"message": "Countries retrieved successfully",
"data": {
"countries": [
{
"id": 1,
"name": "United States",
"iso_code": "US",
"iso_code_3": "USA",
"phone_code": "+1",
"currency_code": "USD"
},
{
"id": 2,
"name": "United Kingdom",
"iso_code": "GB",
"iso_code_3": "GBR",
"phone_code": "+44",
"currency_code": "GBP"
},
{
"id": 3,
"name": "Canada",
"iso_code": "CA",
"iso_code_3": "CAN",
"phone_code": "+1",
"currency_code": "CAD"
}
],
"total": 195
}
}
Retrieve list of states/provinces for a specific country.
Query Parameters
| Param | Description |
country_id | Filter by country ID |
search | Search states by name or code |
{
"status": "success",
"message": "States retrieved successfully",
"data": {
"states": [
{
"id": 1,
"name": "California",
"code": "CA",
"country_id": 1,
"country_name": "United States"
},
{
"id": 2,
"name": "New York",
"code": "NY",
"country_id": 1,
"country_name": "United States"
},
{
"id": 3,
"name": "Texas",
"code": "TX",
"country_id": 1,
"country_name": "United States"
}
],
"total": 50
}
}
Retrieve list of cities, optionally filtered by country and/or state.
Query Parameters
| Param | Description |
country_id | Filter by country ID |
state_id | Filter by state/province ID |
search | Search cities by name |
page | Page number |
per_page | Items per page |
{
"status": "success",
"message": "Cities retrieved successfully",
"data": {
"cities": [
{
"id": 1,
"name": "New York",
"state_id": 2,
"state_name": "New York",
"state_code": "NY",
"country_id": 1,
"country_name": "United States",
"country_code": "US"
},
{
"id": 2,
"name": "Los Angeles",
"state_id": 1,
"state_name": "California",
"state_code": "CA",
"country_id": 1,
"country_name": "United States",
"country_code": "US"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8
}
}
}
Retrieve list of available timezones.
Query Parameters
| Param | Description |
search | Search timezones by name or identifier |
{
"status": "success",
"message": "Timezones retrieved successfully",
"data": {
"timezones": [
{
"identifier": "America/New_York",
"name": "Eastern Time (US & Canada)",
"offset": "-05:00",
"offset_seconds": -18000,
"abbreviation": "EST"
},
{
"identifier": "America/Chicago",
"name": "Central Time (US & Canada)",
"offset": "-06:00",
"offset_seconds": -21600,
"abbreviation": "CST"
},
{
"identifier": "America/Los_Angeles",
"name": "Pacific Time (US & Canada)",
"offset": "-08:00",
"offset_seconds": -28800,
"abbreviation": "PST"
},
{
"identifier": "Europe/London",
"name": "Greenwich Mean Time",
"offset": "+00:00",
"offset_seconds": 0,
"abbreviation": "GMT"
},
{
"identifier": "Asia/Dubai",
"name": "Gulf Standard Time",
"offset": "+04:00",
"offset_seconds": 14400,
"abbreviation": "GST"
}
],
"total": 425
}
}
API Version
API version endpoint.
Retrieve the current API version and related information.
{
"status": "success",
"message": "API version retrieved successfully",
"data": {
"api_version": "v1",
"version": "1.0.0",
"release_date": "2024-01-01",
"changelog_url": "https://docs.example.com/api/v1/changelog",
"documentation_url": "https://docs.example.com/api/v1",
"deprecation_date": null,
"end_of_life_date": null,
"supported_versions": [
"v1"
],
"features": {
"pagination": true,
"filtering": true,
"sorting": true,
"webhooks": true,
"rate_limiting": true
},
"rate_limits": {
"requests_per_minute": 60,
"requests_per_hour": 1000,
"requests_per_day": 10000
}
}
}
Postman Collection Downloads
Import these Postman collections into your workspace to explore and test Zealdash Tenant APIs.
In the next stage we will wire each download link to the corresponding JSON collection file.
Tenant APIs 1.1 – 5.5
Authentication, Dashboard, Clients and core Finance/Projects endpoints.
Download Postman Collection
Tenant APIs 5.6 – 12.5
Projects, Tasks, Todos, Activity Logs, Departments, Email Templates, Estimate Requests and Filters.
Download Postman Collection
Tenant APIs 13.1 – 18.3
Currencies, Boards, Categories/Knowledgebase, Leads, Notes and Notifications.
Download Postman Collection
Tenant APIs 19.1 – 25.4
Tags, Reminders, Files, Announcements, Roles and part of the Tickets module.
Download Postman Collection
Tenant APIs 25.5 – 31.3
Tickets (continued), Time Logs, Users, Webhooks, Import and Export APIs.
Download Postman Collection
Tenant APIs 32.1 – 35.1
System Health, System Info, Countries, States, Cities, Timezones and API Version.
Download Postman Collection