POST

Client.Login

Alias of Customer.Login. Same customer portal login as client.

Permissions

  • This function can be called without a bearer token.

Action

  • Runs the Client.Login function and returns JSON.

Push Service

No push is sent because this function only reads data or returns helper information.

Automation

No automation is run for this function.

Special Instructions

  • This is NOT staff Login. Staff use /app/Login. Customers use this route.
  • On an org subdomain (https://user.bull36.com/app/Customer.Login) you do not need user_name. The org is loaded from user_detail.user_domain = first host label ("user"), same as the dashboard hidden user_name field.
  • On that subdomain send only client_id (or email) + password. Then otp on the second call.
  • On shared domains (bull36.com with no org subdomain) send user_name as the organization user id or username, plus client_id or email, plus password.
  • On a custom org domain the org is loaded from user_detail.domain = Host. You may still send domain_name.
  • Password is checked against contactus.password like the dashboard.
  • Dashboard always emails OTP after a valid password. Send otp on the second call.
  • The returned token is auth_type=client. Staff routes reject it.
  • After login, call Customer.Welcome then Customer.Tickets.List, Customer.Projects.List, Customer.Invoices.List, Customer.Orders.List, Customer.Entries.FormData / List, Customer.DynamicContent.List, Customer.Products.List, Customer.Appointments.Doctors, Customer.Appointments.Types, Customer.Appointments.List, Customer.Appointments.Add, Customer.Appointments.Coupons, Customer.Appointments.Coupon.Add / Edit / Delete, Customer.Files.List, Customer.Rooms.List. Those routes auto-scope to token c_id.
  • Alias: Client.Login.

Required Parameters

No body parameters are required for this function.

Optional Parameters

NameTypeSampleWhat it gives
user_name
post
string24552Organization user id or username. Not required on an org subdomain (user.bull36.com); that host is matched to user_detail.user_domain. Required on shared bull36.com. Aliases: username, org_id.
domain_name
post
stringshop.example.comOrganization domain when user_name is omitted and Host is not an org subdomain. On custom domains Host is used automatically. Alias: domain.
client_id
post
string12614595Customer id (contactus.id). If not numeric, treated as email. Aliases: customer_id, c_id, email.
email
post
string[email protected]Customer email when client_id is not the numeric id.
password
post
stringCUSTOMER PASSWORDRequired unless token is sent. contactus.password, same as dashboard.
otp
post
string1234566-digit email OTP from step 1. Alias: email_otp.

Sample Request

{
    "url": "\/app\/Client.Login",
    "method": "POST",
    "headers": [],
    "body": {
        "client_id": "12614595",
        "password": "CUSTOMER PASSWORD"
    },
    "url_user": "https:\/\/{user}.bull36.com\/app\/Client.Login",
    "url_domain": "https:\/\/{domain}\/app\/Client.Login"
}

Endpoint

POST /app/Client.Login
POST https://{user}.bull36.com/app/Client.Login
POST https://{domain}/app/Client.Login

Sample Output

{
    "success": "3",
    "otp_required": true,
    "message": "OTP send in your email...!",
    "expires_in": 600
}

JavaScript Example

const domain = 'https://user.bull36.com';

async function customerLogin({ client_id, password, otp, user_name }) {
  const body = new URLSearchParams({ client_id, password });
  if (user_name) body.set('user_name', user_name);
  if (otp) body.set('otp', otp);
  const res = await fetch(`${domain}/app/Customer.Login`, { method: 'POST', body });
  const data = await res.json();
  if (data.otp_required) return { otpRequired: true, message: data.message, data };
  if (data.token) return { token: data.token, tokenType: data.token_type, expiresAt: data.expires_at, customer: data.customer, redirectTo: data.redirect_to };
  throw new Error(data.message || 'Customer.Login failed');
}

Error Example

{
    "success": "0",
    "message": "Login Failed Your Email Or Password Was Incorrect Please Try Again"
}