Begin Login with Zoho
const url = 'https://api.sloose.com/auth/zoho/start?dc=au&mode=redirect&crm=7000000009&prove=crm';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.sloose.com/auth/zoho/start?dc=au&mode=redirect&crm=7000000009&prove=crm'Redirects to Zoho’s consent screen. Two ways back, by mode:
popup(the default), opened in a window of its own — what a CRM tab does: when the user finishes,/auth/zoho/doneposts{ type: "sloose:session", token, … }back towindow.openerand closes.redirect, the app’s own sign-in page going there itself:/auth/zoho/donesends the page back toreturn+/sign-in/zoho, with a one-use hand-off code and the noncenin the address’s fragment — never the session token — and the page trades the code atPOST /auth/zoho/handoff, through its own host, for the session’s cookie there.nis the nonce the page left in its own tab, which the page checks the fragment against, so a hand-off address opened anywhere else is refused.
Either way the API’s own host keeps no session cookie afterwards.
Signing in with Zoho says who you are and nothing more. It creates no organisation, admits nobody to one and connects no CRM: the session opens in the organisation the person was last in, or in none (orgId: null), and an organisation is made with POST /orgs, joined by invitation, and connected to a CRM with POST /auth/orgs/{org}/connect. A CRM tab asks POST /auth/session/frame which organisation its own CRM belongs to.
Only the app’s own origins — its hostname and the widget’s — may receive a session: return is checked against them, and localhost is additionally allowed in development. Anything else is refused, because the return origin is where a session would be delivered.
The session is a Better Auth session token: send it as Authorization: Bearer. It lasts thirty days from its last use (eight hours for a Sloose staff member) and can be ended with POST /auth/ba/sign-out.
Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Zoho data centre: us, eu, in, au, cn, jp, ca, uk, sa, ae, sg. Defaults to us.
Example
auZoho data centre: us, eu, in, au, cn, jp, ca, uk, sa, ae, sg. Defaults to us.
Where the session goes: one of the app’s own origins (its hostname, or the widget’s).
Where the session goes: one of the app’s own origins (its hostname, or the widget’s).
popup (the default): the completion page posts to its opener. redirect: it sends the page back with a hand-off code.
Example
redirectpopup (the default): the completion page posts to its opener. redirect: it sends the page back with a hand-off code.
With mode=redirect: the nonce the page keeps in its own tab, 16 to 64 of A–Z, a–z, 0–9, - and _, handed back beside the code.
With mode=redirect: the nonce the page keeps in its own tab, 16 to 64 of A–Z, a–z, 0–9, - and _, handed back beside the code.
From a CRM tab: the Zoho organisation id of the CRM around it. The sign-in’s proof of which CRM the person belongs to reads that CRM by name, so a person in several CRM organisations is proved for the one they are in, and an answer for another organisation proves nothing. Up to 20 digits.
Example
7000000009From a CRM tab: the Zoho organisation id of the CRM around it. The sign-in’s proof of which CRM the person belongs to reads that CRM by name, so a person in several CRM organisations is proved for the one they are in, and an answer for another organisation proves nothing. Up to 20 digits.
crm for a sign-in that PROVES which CRM the person is in (#2194): it asks Zoho for the CRM’s organisation and the person’s user in it, besides who they are, so Zoho asks which CRM organisation, and the session is stamped with the CRM it proved. Any other sign-in asks who the person is and nothing of a CRM, so Zoho shows no organisation list after the first. A CRM tab asks for a proving sign-in only where its CRM belongs to no organisation the person is in.
Example
crmcrm for a sign-in that PROVES which CRM the person is in (#2194): it asks Zoho for the CRM’s organisation and the person’s user in it, besides who they are, so Zoho asks which CRM organisation, and the session is stamped with the CRM it proved. Any other sign-in asks who the person is and nothing of a CRM, so Zoho shows no organisation list after the first. A CRM tab asks for a proving sign-in only where its CRM belongs to no organisation the person is in.
Responses
Section titled “Responses”Redirect to Zoho’s consent screen.
dc is not a known Zoho data centre, return is not one of the app’s origins, a redirect names no nonce n (code: BAD_NONCE), crm is not a Zoho organisation id of up to 20 digits (code: BAD_CRM), or prove is anything but crm (code: BAD_PROVE).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}ZOHO_CLIENT_ID is not configured on this deployment.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The sign-in could not be started.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The restore switch is on (code: MAINTENANCE): every route but /health and /robots.txt is refused before anything is read, except the operator’s own POST /staff/people/{id}/delete with the ADMIN_TOKEN. Sloose is down for maintenance. Please try again in a few minutes.
object
Example
{ "code": "MAINTENANCE"}Headers
Section titled “Headers”Seconds until asking again is worth it (300 while the switch is on).