Ticket.Add
Create a ticket like the Biz1 dashboard support / Contact Us form (dashboard/tickets/new_ticket). Accepts App names and dashboard aliases (topic, messages, ticket_department, team_member_ticket_department, from_time_ticket, to_time_ticket, phone_two, product_id[], image_upload). Custom fields must use dashboard field ids a-{numeric_id} (same keys as the ticket form POST). Uploaded files are stored and appended as message entries. Runs ticket.created automation and realtime. Existing simple topic+messages calls still work.
Permissions
- User must be logged in with a valid bearer token.
- Returned or changed records are limited by the user permissions, team access, folder access, and account settings.
Action
- Creates a Ticket record or sends the requested data after validation.
Push Service
Pushes event ticket.created to users who should see this change.
Automation
Runs automation event ticket.created with the record id and submitted parameters after the action succeeds.
Special Instructions
- Ticket custom fields are NOT the English/Hebrew label. In Tickets settings each field is stored with name = a-{unix timestamp}, e.g. a-1731562297. The dashboard form posts that id (checkbox/multi-select: a-1731562778[]).
- Keys like a-YES_NO_EN or a-SELECT_EN do not match the form and are rejected. Look up ids in Settings → Tickets custom fields (field name column) or from a dashboard new_ticket payload.
- Send either top-level POST keys ([email protected]) or custom_fields JSON {"a-1731562297":"[email protected]"}. Stored JSON keys never include [].
- Validation matches the dashboard form: email fields must be a valid email, number fields must be numeric, select/radio/checkbox values must be an option_value from settings, and a required field that is sent empty is rejected. Topic+messages without custom fields still works (same as API before).
- With customer_id/cust_id: phone, email, name, address, ticket_name are optional (dashboard auto-fills from contactus). Do NOT send phone=-- or other dash-only placeholders; omit phone or leave it empty so auto-fill runs. A real phone number is fine when you want to override.
- ticket_name is the dashboard TICKET NAME column (separate from customer_name). When cust_id is sent and ticket_name is omitted, it is filled from the customer name (same as picking a customer in the create form).
- Sets last_status_time and last_assign_time to open_date (ticket automation timers for in_status / not_assigned rules).
- owner_id is set automatically to the organization owner (user_detail.id / JWT owner_id), same as dashboard Tickets::new_ticket ($Org[id]). Do not send owner_id in the body — it is ignored. Response includes owner_id for verification.
- Dates: Y-m-d H:i:s. Bearer token required.
Required Parameters
| Name | Type | Sample | Explanation |
|---|---|---|---|
topicpost | string | Payment issue | Ticket subject. Alias: subject. |
Optional Parameters
| Name | Type | Sample | What it gives |
|---|---|---|---|
messagespost | string | Customer needs help with invoice. | Problem / first message text (PROBLEM field). Alias: message. Required unless a file is uploaded. |
cust_idpost | int | 123 | Customer id. Alias: customer_id. When set, Ticket.Add loads contactus (same as dashboard ticket modal) and auto-fills customername, ticket_name, email, phone, mobile/phone_two, address, and city_id when those fields are empty. Explicit values you send still win. type defaults to my_tickets. |
customernamepost | string | John Demo | Customer display name (CUSTOMER NAME column). Optional when cust_id is sent (auto-filled from contactus). Use when creating without customer id. |
ticket_namepost | string | John Demo | Ticket Name column on customer-tickets (tickets.ticket_name). Optional; with cust_id defaults to contactus name like the dashboard picker. Send explicitly to override. |
emailpost | string | [email protected] | Customer email. Auto-filled from cust_id when omitted. |
phonepost | string | 0500000000 | Customer phone. Auto-filled from cust_id when omitted or empty. Do not send "--" / dash-only placeholders (omit the field instead). |
phone_twopost | string | 0520000000 | Second phone (dashboard phone_two → mobile). Auto-filled from cust_id when omitted. |
mobilepost | string | 0520000000 | Customer mobile. Auto-filled from cust_id when omitted. |
addresspost | string | Main street 5 | Address. Auto-filled from cust_id when omitted. |
city_idpost | int | 10 | City id. Auto-filled from cust_id when omitted. |
ratingpost | int | 3 | Urgency stars 1-5. Default 1. |
due_datepost | datetime | 2026-07-20 09:00:00 | Due datetime Y-m-d H:i:s. Default now. With assignees, status becomes 3 (like dashboard). Send UTC date/time as Y-m-d H:i:s, for example 2026-07-20 10:00:00. The SDK converts user local Date/local datetime input to UTC before posting. |
from_time_ticketpost | time | 09:00 | Start time (dashboard from_time_ticket). Alias: ticket_from_time. Send time values as H:i:s. If the route also has a date field, send that date as UTC Y-m-d H:i:s. |
to_time_ticketpost | time | 11:00 | End time (dashboard to_time_ticket). Alias: ticket_to_time. Send time values as H:i:s. If the route also has a date field, send that date as UTC Y-m-d H:i:s. |
ticket_departmentpost | int | 2 | Department id (CHOOSE DEPARTMEN). Alias: department. |
assign_member_id[]post | array|string | 211 | Assigned team member ids (same as dashboard team_member_ticket_department[]). Stored in DB as JSON string ids like ["211","212"] (dashboard format). How to pass: (1) multipart/form-data — repeat the field: assign_member_id[]=211 and assign_member_id[]=212 (Postman: key assign_member_id[], type Text, add row per id; curl: --form 'assign_member_id[]=211' --form 'assign_member_id[]=212' — do not wrap the number in extra quotes). (2) x-www-form-urlencoded — assign_member_id=211,212 or assign_member_id=["211","212"]. (3) JSON body — "assign_member_id": ["211","212"]. Aliases: assign_member_id, team_member_ticket_department, team_member_ticket_department[], team_member, team_member_id, organizations_user. |
team_member_ticket_departmentpost | array|string | 211,212 | Dashboard alias for assignees. Same rules as assign_member_id[]. |
product_idpost | array|string | 12,Custom service | Related products (product_id[]). Use values from Ticket.ProductsByCustomer / Ticket.Get products[].value: catalog id when iteeeem_id != 0, or item_name when iteeeem_id = 0 (free-text). |
mission_idpost | int | 555 | Related mission id. |
statuspost | int | 1 | Ticket status id from all_status (type=ticket). System defaults: 1=Opened, 2=Closed, 3=Assigned. If omitted: 1, or 3 when due_date + assignees (dashboard). Custom statuses (e.g. pending): list via Statuses.List with type=ticket. |
typepost | string | my_tickets | my_tickets or company_tickets. Default my_tickets when cust_id set, else company_tickets. |
custom_fieldspost | object|string | {"a-1731562297":"[email protected]"} | Custom fields object keyed by dashboard field id. Same as posting a-{id} keys. Do not use labels. |
image_uploadfile | file | screenshot.png | FILES upload (dashboard image_upload). Also: file, image, cop_paste_image3. Uploaded via the same FTP path as dashboard new_ticket: biz1upload/tickets/{user}-{random}{time}.{ext}. The path is stored in the ticket messages[] entry so dashboard chat can open it. Use multipart/form-data. |
a-{field_id}post | string | [email protected] | One custom field. Key MUST be the settings field id, e.g. a-1731562297 (email), a-1731562578 (number), a-1731562778[] (checkbox/multi-select form-data). Copy the id from Tickets settings or from the dashboard new_ticket request. |
Authentication
Send the bearer token returned by Login in the request header.
Authorization: Bearer YOUR TOKEN
Sample Request
{
"url": "\/app\/Ticket.Add",
"method": "POST",
"headers": {
"Authorization": "Bearer YOUR TOKEN"
},
"body": {
"topic": "Payment issue",
"messages": "Customer needs help.",
"cust_id": "123",
"ticket_name": "John Demo",
"ticket_department": "2",
"assign_member_id[]": [
"211",
"212"
],
"due_date": "2026-07-20 09:00:00",
"from_time_ticket": "09:00",
"to_time_ticket": "11:00",
"rating": "3",
"a-1731562297": "[email protected]",
"a-1731562578": "10",
"a-1731562778[]": "2"
},
"curl_multipart": "curl --location 'https:\/\/YOUR_HOST\/app\/Ticket.Add' \\\n--header 'Authorization: Bearer YOUR_TOKEN' \\\n--form 'topic=Payment issue' \\\n--form 'messages=Customer needs help.' \\\n--form 'cust_id=123' \\\n--form 'due_date=2026-07-20 09:00:00' \\\n--form 'assign_member_id[]=211' \\\n--form 'assign_member_id[]=212' \\\n--form 'image_upload=@\/path\/to\/file.png'",
"url_user": "https:\/\/{user}.bull36.com\/app\/Ticket.Add",
"url_domain": "https:\/\/{domain}\/app\/Ticket.Add"
}Endpoint
POST /app/Ticket.Add
POST https://{user}.bull36.com/app/Ticket.Add
POST https://{domain}/app/Ticket.AddSample Output
{
"success": 1,
"output": "1",
"message": "Success",
"insert_id": 900,
"ticket_id": 900,
"owner_id": 14,
"u_id": 14,
"cust_id": 123,
"customer_name": "John Demo",
"ticket_name": "John Demo",
"assign_member_id": [
"211",
"212"
],
"files": [],
"automation_event": "ticket.created",
"socket_event": "ticket.created"
}JavaScript Example
const token = 'YOUR TOKEN';
// Custom field keys must be a-{numeric_id} from Tickets settings (same as dashboard new_ticket), not labels.
const body = new URLSearchParams({
topic: 'Payment issue',
messages: 'Customer needs help.',
cust_id: '123',
ticket_department: '2',
assign_member_id: '211,212',
due_date: '2026-07-20 09:00:00',
'a-1731562297': '[email protected]'
});
const res = await fetch('/app/Ticket.Add', {
method: 'POST',
headers: { Authorization: 'Bearer ' + token },
body
});
const data = await res.json();
console.log(data.ticket_id, data.assign_member_id); // ["211","212"]
// With file (multipart) — repeat assign_member_id[]
const form = new FormData();
form.append('topic', 'Payment issue');
form.append('messages', 'Customer needs help.');
form.append('cust_id', '123');
form.append('due_date', '2026-07-20 09:00:00');
form.append('assign_member_id[]', '211');
form.append('assign_member_id[]', '212');
form.append('a-1731562297', '[email protected]');
form.append('image_upload', fileInput.files[0]);
const res2 = await fetch('/app/Ticket.Add', {
method: 'POST',
headers: { Authorization: 'Bearer ' + token },
body: form
});Error Example
{
"missing": {
"success": 0,
"message": "Missing required parameter: topic, messages"
},
"request_blocked_example": {
"success": "0",
"error": "request_blocked",
"message": "Request blocked by security rules",
"reasons": [
{
"type": "sql_comment_injection",
"field": "body.phone"
}
],
"note": "Usually caused by phone=--. Omit phone or send a real number \/ empty value when using customer_id."
}
}