App Functions
Choose a function from the menu. The help page opens on the right side without leaving this screen.
SDK
Use the JavaScript SDK when building web, React, Vue, Flutter WebView, or Android WebView screens. Define the domain once, login once, then reuse the same client for REST calls and realtime.
- Include
https://{domain}/app/sdk/biz1-sdk.jsin the UI. - Create one
Biz1SDK.Biz1Clientat app startup withdomainand a storage object. - Call
client.login(). The SDK saves the bearer token inbiz1_sdk_bearer_token. - After login, call
client.account.basic()and store user, organization, folders, statuses, team members, and field settings for the UI. - Use route helpers like
client.customers.list(), dynamic helpers likeclient.routes.Customer.List(), or genericclient.request(). - For lists, send filters and paging, but keep
length,limit, orper_pageat25or less. - Pass JavaScript
Dateobjects or local datetime strings for date fields. The SDK posts UTCY-m-d H:i:s; the server stores the value according to the table column type. - Store ids returned from list/add calls, then reuse them for single, update, remove, documents, chat, recordings, missions, tickets, and related calls.
- If any request returns
401, the SDK clears the token. Show login again.
Include SDK
<script src="https://{domain}/app/sdk/biz1-sdk.js"></script>Basic SDK Flow
const client = new Biz1SDK.Biz1Client({
domain: 'https://{user}.bull36.com',
storage: localStorage
});
await client.login({
username: 'USER EMAIL',
password: 'USER PASSWORD'
});
const user = await client.account.basic();
const customers = await client.customers.list({ folder_id: 1, length: 25 });
const total = await client.customers.count({ folder_id: 1 });
const single = await client.customers.get(customers.rows[0].customer_id || customers.rows[0].id);
console.log({ user, customers, total, single });Any Route
const result = await client.request('Customer.List', {
folder_id: 1,
length: 25
});
const sameResult = await client.routes.Customer.List({
folder_id: 1,
length: 25
});Date/Time Fields
await client.customers.add({
name: 'John Demo',
phone: '0500000000',
followup: new Date(2026, 6, 20, 10, 0, 0)
});
// The SDK posts followup as UTC Y-m-d H:i:s.
const utcValue = Biz1SDK.toUtcDateTime(new Date(2026, 6, 20, 10, 0, 0));Realtime
<script src="https://{domain}/realtime/socket.io/socket.io.js"></script>
<script src="https://{domain}/app/sdk/biz1-sdk.js"></script>
const socket = client.realtime.connect({
platform: 'web',
path: '/realtime/socket.io'
});
client.realtime.on('biz1:ready', function (payload) {
console.log('socket ready', payload);
});
client.realtime.on('*', function (event) {
console.log('realtime event', event);
});Socket
Use the socket after login to update open screens without polling. The same bearer token used for API calls is used to register the socket device.
- Login with
/app/Loginorclient.login()and keep the bearer token in app state. - Connect to
https://{domain}with path/realtime/socket.io. - Wait for
biz1:ready. The payload includes the user id and enabled event list. - Listen to
biz1:eventor use SDKclient.realtime.on('*')for all enabled events. - For better performance, listen to specific event keys and refresh only the affected list, customer, mission, message, calendar, or settings cache.
Connect Sample
<script src="https://{domain}/realtime/socket.io/socket.io.js"></script>
<script src="https://{domain}/app/sdk/biz1-sdk.js"></script>
const client = new Biz1SDK.Biz1Client({
domain: 'https://{domain}',
storage: localStorage
});
await client.login({
username: 'USER EMAIL',
password: 'USER PASSWORD'
});
const socket = client.realtime.connect({
path: '/realtime/socket.io',
platform: 'web'
});
client.realtime.on('biz1:ready', function (payload) {
console.log('Socket ready', payload.userId, payload.events);
});
client.realtime.on('*', function (event) {
console.log('Any socket event', event.key, event.payload);
});Specific Listeners
client.realtime.on('crm.lead.created', function (event) {
const customerId = event.payload.customer_id;
refreshCustomerList();
openCustomerBadge(customerId);
});
client.realtime.on('mission.created', function (event) {
refreshMissionList({ customer_id: event.payload.customer_id });
});
client.realtime.on('message.created', function (event) {
refreshCustomerMessages(event.payload.customer_id);
});
client.realtime.on('customer.followup', function (event) {
refreshCustomer(event.payload.customer_id);
});Receive JSON: New Customer
{
"id": 1784268468521,
"key": "crm.lead.created",
"createdAt": "2026-07-21T08:30:00.000Z",
"source": "server",
"payload": {
"customer_id": 13745935,
"event": "add_lead",
"customer": {
"id": 13745935,
"name": "John Demo",
"email": "[email protected]",
"mobile": "0500000000"
},
"socket_registered_user_ids": [47]
}
}Receive JSON: Mission
{
"id": 1784268468522,
"key": "mission.created",
"createdAt": "2026-07-21T08:31:00.000Z",
"source": "app-node",
"payload": {
"mission_id": 500,
"customer_id": 13745935
}
}Receive JSON: Status Or Internal Status
{
"id": 1784268468523,
"key": "statuses.edit.updated",
"createdAt": "2026-07-21T08:32:00.000Z",
"source": "app-node",
"payload": {
"id": 12,
"route": "Statuses.Edit",
"table": "all_status",
"changed": ["name_he", "color"],
"data": {
"name_he": "In Progress",
"color": "#2f80ed",
"type": "internal_status"
}
}
}Main Event Groups
- New customer and follow-up:
crm.lead.created, customer.updated, customer.followup, customer.restored - Messages and email:
chat.message.received, message.created, mission.message.created, project.message.created, message.mark_read, message.replied, message.forwarded, message.deleted, email.created, email.deleted - Mission and reminder:
mission.created, mission.updated, mission.done, mission.reopened, mission.deleted, mission.reminder, mission.open_popup, automation.reminder.popup - Meeting and appointment:
meeting.created, meeting.updated, meeting.deleted, automation.appointment.open_popup, appointment.created, appointment.updated, appointment.deleted - Calls:
call.incoming, call.status.popup - Tabs and statuses:
entries.created, entries.updated, entries.deleted, statuses.add.created, statuses.edit.updated, statuses.delete.deleted - Internal status:
Use the statuses.* events where payload.data.type is internal_status or the route help says it changes internal status.
When a route response contains socket_event, the same key can be used in client.realtime.on(socket_event, handler).
Prompt Date Rule
When using the prompt below, also tell the AI that every date/time field must be sent to the API as UTC Y-m-d H:i:s. The Biz1 SDK converts user local Date values and local datetime strings before POST.
Prompt
How To Call
POST /app/{Route.Name}
POST https://{user}.bull36.com/app/{Route.Name}
POST https://{domain}/app/{Route.Name}
Authorization: Bearer YOUR TOKENInstructions
- Call
/app/Loginwith the user login details from your UI. - If the response asks for OTP, show an OTP screen and finish login with the required code.
- When login returns a bearer token, save it in your app session storage or secure app state.
- For every protected function, send
Authorization: Bearer YOUR TOKENin the request header. - Send function parameters as POST body fields. List routes allow paging and never return more than 25 rows per call.
- For every date/time field, work in the user local time in the UI, then send UTC
Y-m-d H:i:sto the API. The SDK does this automatically for JavaScriptDatevalues and known date fields. - If a call returns 401, clear the saved token and send the user back to login.
Async Login Sample
async function getBearerToken({ domain = 'https://{domain}', username, password, otp = '' }) {
const body = new URLSearchParams({ username, password });
if (otp) body.set('otp', otp);
const res = await fetch(`${domain}/app/Login`, {
method: 'POST',
body
});
const data = await res.json();
if (data.otp_required) return { otpRequired: true, message: data.message, data };
if (!data.token) throw new Error(data.message || 'Login failed');
return {
token: data.token,
tokenType: data.token_type || 'Bearer',
expiresAt: data.expires_at || null,
raw: data
};
}
const auth = await getBearerToken({
domain: 'https://{user}.bull36.com',
username: 'USER EMAIL',
password: 'USER PASSWORD'
});
const token = auth.token;
// Use on every protected call:
// headers: { Authorization: `Bearer ${token}` }