Embedded Chat & SSO
Embedded Chat & SSO
This page covers the integration surface used by partners who embed Hutly on their own web properties, or who bridge Hutly identity into a partner application:
- Embedded chat — mint short-lived, chat-scoped tokens so a widget on your own site can talk to a Hutly agent without ever exposing an API key to the browser.
- SSO — exchange a Hutly session for a one-time token that logs the user into a partner app (VicForms, Platform Accounts, PropertyData, and others).
- ABN / ACN lookup — resolve Australian Business / Company numbers against the ABR from your own onboarding or forms flows.
Base URL: https://api.intellia.com.au
"chat", are scoped to a single organization, and
expire 2 hours after minting. They grant no admin, billing, or settings
access.Embedded Chat
Website Chat Token (anonymous widget)
POST /public/website-chat-tokenAuthentication: None (public endpoint). This is the token the public Hutly chat widget calls from an anonymous browser session before opening the agent. No API key is exposed to the client.
Mints a per-visitor, chat-scoped token against the Hutly GTM organization. The
visitor identity is namespaced server-side as visitor:<visitorId>, so a
caller-supplied value can never collide with a real user account.
Request Body:
{
"visitorId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
}visitorId(optional): A browser-generated identifier the widget persists inlocalStorage. Omit it on first visit — the server mints one and returns it so the widget can stash and reuse it (memory and conversation state persist across reloads for the same id). If supplied, it must be 1–64 characters matching[a-zA-Z0-9_-]+; anything else returns400 Invalid visitorId.
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC...",
"expiresAt": "2026-07-13T12:00:00.000Z",
"visitorId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"organizationId": "<hutly-gtm-org-id>"
}token: The assume-role JWT to send asAuthorization: Bearer <token>on subsequent chat calls.expiresAt: ISO-8601 expiry, 2 hours from mint.visitorId: The id the token is bound to (echoed back, or newly minted).organizationId: Always the Hutly GTM org — the widget can only chat with the marketing agent in that org.
Assume-Role Token (authenticated mint for embedded apps)
POST /orgs/{organizationId}/assume-roleAuthentication: Requires either a Hutly user session or an organization API
key. This endpoint is not noAPIKey-gated — an API key can mint tokens,
but only if the key carries the assume_role.write permission. When called with
an API key that lacks that permission, the request returns
403 Unauthorized - API key does not have assume_role write permission.
Capability required: org.assume_role.
Use this to mint an end-user chat token for an embedded application where you
control the identity (for example, your own logged-in customers). If the target
user does not already exist and you supply userEmail, a chat-role member is
created in the organization.
Request Body:
{
"userId": "user-123",
"userEmail": "customer@example.com",
"userName": "Customer Name",
"permissions": []
}userId(required): The user to mint the token for.userEmail(optional): If the user does not exist, provide this to create a chat-role member. Without it, an unknownuserIdreturns404 User not found.userName(optional): Display name for a newly created user (defaults to the local part of the email).permissions(optional): Permission strings embedded in the token.
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC...",
"expiresAt": "2026-07-13T12:00:00.000Z",
"userId": "user-123",
"organizationId": "org-456",
"role": "chat"
}Verify Assume-Role Token
POST /orgs/{organizationId}/assume-role/verifyAuthentication: None (skipAuth). Anyone can submit a token for
verification against the organization in the path — no session or API key is
needed, since verification is a signature check, not a privileged action.
Validates a token’s signature, expiry, and that its audience matches the
{organizationId} in the path.
Request Body:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC..."
}Response:
{
"valid": true,
"userId": "user-123",
"organizationId": "org-456",
"role": "chat",
"permissions": [],
"expiresAt": "2026-07-13T12:00:00.000Z"
}When the token is malformed, expired, or scoped to a different organization,
the endpoint returns 200 with { "valid": false, "error": "<reason>" } rather
than an error status.
Legacy Public Token
GET /buddybee/public-tokenAuthentication: None (public endpoint).
Mints a chat-scoped token for a shared synthetic “unknown” user against the Hutly Internal organization. Retained for existing public-widget callers.
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC...",
"expiresAt": "2026-07-13T12:00:00.000Z",
"userId": "<unknown-user-id>",
"organizationId": "<hutly-internal-org-id>",
"role": "chat"
}POST /public/website-chat-token, which
namespaces each visitor and preserves per-visitor memory. The legacy public
token maps every anonymous caller onto one shared user.SSO
SSO Token Exchange
POST /orgs/{organizationId}/auth/sso/exchangeAuthentication: Requires a Hutly user session. Capability required:
auth.sso_exchange.
Exchanges a Hutly JWT for a single-use exchange token (valid 30 seconds) that a partner app can redeem to establish a logged-in session. The exchange token is stored server-side and auto-expires; the partner app validates and consumes it on redemption.
Request Body:
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVC...",
"targetDomain": "propertydata"
}jwt(required): The Hutly session JWT to bridge.targetDomain(required): One ofbuddybee,intellia,adl,propertydata,vicforms. Any other value returns400 Invalid targetDomain.
Response:
{
"exchangeToken": "3f2a...<64 hex chars>",
"expiresAt": 1752403200
}exchangeToken: The one-time token the partner app redeems.expiresAt: Unix epoch seconds (30 seconds from mint).
targetDomain is propertydata, the exchange is gated server-side: any
unmet PDOL deeds for the user must be signed first, or the request is rejected.
This mirrors the launcher UI’s signature prompt and prevents minting a token
that would bypass the per-query deed checks inside the portal.VicForms SSO
GET /orgs/{organizationId}/buddybee/vicforms/authAuthentication: Requires a Hutly user session. Capability required:
buddybee.use.
Returns a VicForms session token for the calling user, using the VicForms
request token stored in the user’s organization-member metadata. Requires the
caller to be a member of the organization and to have a request_token in their
member metadata (otherwise 400).
Response:
{
"token": "<vicforms-session-token>",
"success": true
}Platform Accounts SSO
GET /orgs/{organizationId}/buddybee/platform/authAuthentication: Requires a Hutly user session. Capability required:
buddybee.use.
Same shape as VicForms SSO, but returns a Platform Accounts session token.
Also requires a request_token in the caller’s member metadata.
Response:
{
"token": "<platform-accounts-session-token>",
"success": true
}ABN / ACN Lookup
Lookup by ABN or ACN
GET /buddybee/abn-lookup/{abn}Authentication: Requires a Hutly user session or API key. Capability
required: abn.lookup. Organization and subscription checks are bypassed, so
this works from any authenticated context.
Resolves an Australian Business Number or Company Number against the ABR. The
path segment is named abn for backwards compatibility, but the handler
dispatches by digit count: an 11-digit value is treated as an ABN, a 9-digit
value as an ACN. Whitespace is stripped. A value that is neither returns
400 Value must be a valid 11-digit ABN or 9-digit ACN.
Response:
{
"entityName": "Example Pty Ltd",
"acn": "123456789",
"legalPostcode": "3000",
"legalState": "VIC",
"legalStreetName": "Collins Street",
"legalStreetNumber": "1",
"legalSuburb": "Melbourne",
"legalUnitNumber": "",
"entityStatus": "Active",
"businessNames": ["Example Trading"],
"isGstRegistered": true,
"isAbnActive": true
}Lookup Availability
GET /buddybee/abn-lookup-availableAuthentication: Requires a Hutly user session or API key. Capability
required: abn.lookup. Organization and subscription checks are bypassed.
Reports whether the ABR lookup service is currently configured and reachable (a valid ABR GUID and base URL are present). Use this to gate lookup UI before prompting for an ABN.
Response:
{
"available": true
}Deprecated Endpoints
| Deprecated | Replacement |
|---|---|
GET /buddybee/user/metadata |
GET /orgs/{organizationId}/buddybee/user/metadata |
PUT /buddybee/user/metadata |
PUT /orgs/{organizationId}/buddybee/user/metadata |
Both deprecated endpoints require a Hutly user session and resolve the target organization by locating the caller’s VicForms membership. New integrations must call the org-scoped paths, which take the organization id explicitly.