API Developer Guide
Overview
Welcome to the API Developer Guide. Please use the sandbox URL for testing purposes. When using the production version, ensure you have the production key and access. If you would like to opt into the program, please contact support@ecoachmanager.com.
Authentication
To access the API, you must first log in using your credentials:
POST /api/auth/login
Request
URL: /api/auth/login
Method: POST
Content-Type: application/json
Body Parameters
username(string) - Your usernamepassword(string) - Your password
Example Request
{
"username": "your_username",
"password": "your_password"
}
Example Response
{
"token": "abc123xyz456"
}
Using the Token
Include the token in the header of your API requests:
Authorization: Bearer your_token_here
Example Authenticated Request
GET /api/your_endpoint
Host: api.yourdomain.com
Authorization: Bearer abc123xyz456
IP address is not authorized
{
"error": "Access denied: your IP address is not authorized."
}
Get Tags List
This endpoint retrieves all available tags from the system database
(tb_tags_ecm). Each tag record includes its unique ID and name.
Request
URL: /api/tags
Method: GET
Content-Type: application/json
Headers
Authorization: Bearer your_token_here
AccessKey: your_secret_key_here
Example Request
GET /api/tags
Host: api.ecoachmanager.com
Authorization: Bearer abc123xyz456
AccessKey: your_secret_key_here
Notes
- This endpoint does not require body parameters.
- Returned list is ordered by
tag_idin ascending order. - If no tags exist, an empty array will be returned with a success status.
Example Responses
Success
{
"status": "success",
"count": 66,
"results": [
{ "tag_id": "1", "tag_name": "Verification Needed" },
{ "tag_id": "2", "tag_name": "ECM" },
{ "tag_id": "3", "tag_name": "Verification Completed" },
{ "tag_id": "4", "tag_name": "Imported from DTE" }
]
}
HTTP: 200 OK
No Tags Found
{
"status": "success",
"count": 0,
"results": [],
"message": "No tags found."
}
HTTP: 200 OK
Database Error
{
"status": "error",
"message": "Database error occurred while retrieving tags.",
"error": "SQLSTATE[HY000]: General error",
"code": 500
}
HTTP: 500 Internal Server Error
Unexpected Error
{
"status": "error",
"message": "An unexpected error occurred while retrieving tags.",
"error": "Internal system exception",
"code": 500
}
HTTP: 500 Internal Server Error
Booking Search By Tags
This endpoint allows you to search for bookings using multiple filters such as tags, status, journey type, vehicle type, and date range. The system performs multiple validation layers before executing the query to ensure accurate results.
Request
URL: /api/booking/search
Method: POST
Content-Type: application/json
Headers
Authorization: Bearer your_token_here
AccessKey: your_secret_key_here
Request Body
{
"filter": {
"tags": ["Verification Needed"],
"status": "B",
"journeyType": "Family Event",
"vehicleType": "25-33 Seat Premium Coach",
"date": {
"startDate": "2025-10-31",
"endDate": "2025-11-03"
}
}
}
Body Parameters
tags(array, required) - Tag name(s) used to filter bookings. All tag names will be matched against the eCM tag list.status(string, optional) - Booking status code. For example,Bfor "Booking".journeyType(string, optional) - Type of journey such as "Family Event", "School", etc. Must exist in the system.vehicleType(string, optional) - Vehicle name or category to match. Must exist in the system.date(object, required) - Defines the search period.startDate(string, format: YYYY-MM-DD)endDate(string, format: YYYY-MM-DD)
Validation Rules
- User Authentication: The system checks for a valid
user_idinuserPermission. If missing, request is denied. - Date Validation: Both
startDateandendDateare verified for correct format (YYYY-MM-DDorYYYY-MM-DD HH:MM:SS). - Tags: Required field. Each tag is converted to its corresponding ID via
getTagEcmID(). - Journey & Vehicle Type: If provided, validated against
tb_journy_typeandtb_cartables. - Query Construction: SQL filters applied dynamically based on provided parameters and date range.
- Data Encryption: Customer phone numbers are encrypted using
URLencryptionYmd(). - Flight Details: Journey legs with flight data return a nested
flightDetailsobject; otherwise return "No Flight Details".
Example Request
POST /api/booking/search
Host: api.ecoachmanager.com
Authorization: Bearer abc123xyz456
AccessKey: your_secret_key_here
Example Responses
Success
{
"status": "success",
"count": 1,
"results": [
{
"quoteId": 1015066,
"tags": "Verification Needed",
"customerName": "Gagg-contract-v69",
"customerPhone": "VFdwQmVVNVRNSGhOVXpCM1RuYzlQUT09Zkh4WlRFTlRVREF4TlRZM09Ea3dNelExT1E9PQ==",
"journeyType": "Family Event",
"numOfPassenger": "10",
"vehicleType": "25-33 Seat Premium Coach",
"luggage": "Luggage space required",
"journeyInfo": [
{
"journeyOrder": "1",
"pickupDate": "2025-10-31",
"pickupTime": "08:01:00",
"collectionAddress": "chinatown",
"destinationAddress": "TETS location",
"flightDetails": "No Flight Details"
},
{
"journeyOrder": "1",
"pickupDate": "2025-11-02",
"pickupTime": "08:01:00",
"collectionAddress": "Mo Chit station",
"destinationAddress": "Arrival Hall, Larnaca Airport",
"flightDetails": {
"flightArrival": "AK - Airasia_1000",
"flightArrivalTime": "2025-11-03 08:45:00",
"airportArrival": "A",
"terminalArrival": "B",
"flightDeparture": "",
"flightDepartureTime": "0000-00-00 00:00:00",
"airportDeparture": "",
"terminalDeparture": ""
}
}
]
}
]
}
HTTP: 200 OK
No Results Found
{
"status": "success",
"count": 0,
"results": [],
"message": "No bookings match the given filters."
}
Invalid Date Format
{
"status": "error",
"error": "Invalid date format: '2025/11/03'. Please use YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.",
"code": 400
}
Missing Required Field
{
"status": "error",
"error": "Missing required field: tags.",
"code": 400
}
No Tags Found
{
"status": "error",
"error": "No tags found in the system.",
"code": 404
}
Journey or Vehicle Type Not Found
{
"status": "error",
"error": "Journey type not found in the system.",
"code": 404
}
Authentication Failed
{
"status": "error",
"error": "Authentication failed: User ID not found or not linked to account.",
"code": 401
}
HTTP: 401 Unauthorized
Replace Tag & Update Contact Log
This endpoint replaces an existing tag (oldTag) with a new one (newTag) for
multiple bookings.
Optionally, it also inserts a contact log entry for each updated booking when
contactlog data is provided.
Request
URL: /api/tags/replace
Method: POST
Content-Type: application/json
Headers
Authorization: Bearer your_token_here
AccessKey: your_secret_key_here
Request Body
{
"bookingIds": [1015437, 1015433],
"oldTag": "Verification Needed",
"newTag": "Verification Confirmed",
"contactlog": {
"operation": "AI Verification",
"calledTime": "2025-11-12 03:33:33",
"note": "Verification completed successfully. Customer confirmed details by phone.",
"callTranscript": "AI: Hello, confirming your booking.\nCustomer: Yes, correct.\n..."
}
}
Body Parameters
bookingIds(array, required) - List of booking (quote) IDs to update. Must be a non-empty array.oldTag(string, required) - Existing tag name that will be replaced.newTag(string, required) - Target tag name that will replace the old tag.contactlog(object, optional) - If provided, a contact log entry will be created for each updated booking.operation(string, default: "AI Verification") - Type of action or operation name.calledTime(string, format: "YYYY-MM-DD HH:MM:SS") - The timestamp of the contact call. If missing, current time is used.note(string) - Description or summary of the call.callTranscript(string) - Detailed conversation text between AI and customer.
Validation Rules
- Authentication: Requires a valid user with
user_idfromuserPermission. - Booking IDs: Must be an array and not empty. Otherwise, request fails with code
400. - Tag Names: Both
oldTagandnewTagmust exist intb_tags_ecm. - Contact Log Format: Must be a JSON object if present; otherwise error
400. - Date Validation:
calledTimemust follow formatYYYY-MM-DD HH:MM:SS. If invalid, the system rolls back and returns an error. - Atomicity: All updates and logs are executed within a database transaction. Any failure rolls back all changes.
Example Request
POST /api/tags/replace
Host: api.ecoachmanager.com
Authorization: Bearer abc123xyz456
AccessKey: your_secret_key_here
Example Responses
Success
{
"status": "success",
"message": "Processed 2 booking(s). Updated: 2, Skipped: 0",
"updated": 2,
"skipped": 0,
"results": [
{
"quote_id": 1015437,
"cust_id": 41828,
"old_tag": "Verification Needed",
"new_tag": "Verification Confirmed",
"rows_updated": 1,
"status": "updated",
"contact_log_result": {
"operation": "AI Verification",
"dateTime": "2025-11-12 19:37:03",
"calledTime": "2025-11-12 03:33:33",
"note": "Verification completed successfully. Customer confirmed details by phone.",
"callTranscript": "AI: Hello, confirming your booking.\nCustomer: Yes, correct.\n..."
}
}
]
}
HTTP: 200 OK
Partial Success (Some Skipped)
{
"status": "success",
"message": "Processed 3 booking(s). Updated: 2, Skipped: 1",
"results": [
{
"quote_id": 1015401,
"status": "skipped",
"reason": "Old tag 'Verification Needed' not found."
}
]
}
Missing Required Fields
{
"status": "error",
"error": "Missing required fields: oldTag or newTag.",
"code": 400
}
Booking IDs Invalid
{
"status": "error",
"error": "Field bookingIds must be a non-empty array.",
"code": 400
}
Tag Not Found
{
"status": "error",
"error": "Old tag or new tag not found in tb_tags_ecm.",
"code": 400
}
Invalid calledTime Format
{
"status": "error",
"error": "Invalid calledTime format '2025/11/12 08:00'. Please use 'YYYY-MM-DD HH:MM:SS' (example: 2025-11-12 19:37:03).",
"code": 400
}
Contactlog Must Be Object
{
"status": "error",
"error": "Field contactlog must be an object.",
"code": 400
}
Internal Server Error (Rollback)
{
"status": "error",
"message": "Failed to update tags or insert contact logs.",
"error": "SQLSTATE[HY000]: General error: ...",
"code": 500
}
HTTP: 500 Internal Server Error




