in inTouch Docs
Get your key
Embed

Embed API

What the frame tells your page, what your page can tell the frame, and the JavaScript surface of <intouch-chat>.

Events

Every event arrives as a normal DOM event on the element, and as a postMessage if you use a raw iframe.

EventDetailWhen
intouch:ready{ version }The frame is up and will accept commands
intouch:themeApplied{ warnings[] }After every theme application
intouch:paired{}A visitor linked their account
intouch:unpaired{ reason }Signed out, or the session expired
intouch:unread{ count }The number of unread chats changed
intouch:activeChat{ hasActive }A chat was opened or closed
intouch:error{ code }storage_blocked, pair_rate_limited, peer_not_found, peer_rate_limited

This list is exhaustive and it is a promise. No event carries a name, a phone number, a chat id, an avatar, a token or any message content. Your page can know that somebody is linked and how many unread chats they have. Nothing beyond that leaves the frame.

Commands

CommandEffect
setTheme(theme)Applies a theme live, no reload
colorScheme propertyauto, light, dark or host
lang attributeInterface language
logout()Signs the visitor out of this frame
requestStorageAccess()Asks for unpartitioned storage; needs a user gesture

The frame only accepts commands from the origin it was given at load time. A raw iframe integration sends { source: "intouch-host", type: "intouch:setTheme", theme } via postMessage.

JavaScript

Event listeners can be attached at any time — they survive the element being upgraded. Methods and properties cannot: if you load the script with async, wait for the definition first.

const chat = document.querySelector('intouch-chat');

// works immediately, even before embed.js has loaded
chat.addEventListener('intouch:unread', e => {
  badge.textContent = e.detail.count;   // a number, nothing else
});

// methods need the element to be defined
await customElements.whenDefined('intouch-chat');
await chat.ready;                       // resolves once the frame is up
chat.setTheme({ colors: { accent: '#0a0' } });
chat.colorScheme = 'dark';              // or 'host' to follow your page

If you would rather not think about it, drop the async from the script tag — then the element is defined before your own code runs.

Attributes

AttributeMeaning
themeInline JSON, or a hosted id such as t_9fb2c1a4e803
color-schemeauto · light · dark · host
peerPhone number of the counterpart, international form. Opens that chat; creates it only when the visitor sends
langInterface language, e.g. de
baseAlternative inTouch origin; defaults to where the script came from
unreadWritten by the component, so you can style with [unread]

A theme inside the element as <script type="application/json"> beats the attribute and needs no quote escaping. The color-scheme attribute beats colorScheme inside the theme: it is the more specific instruction, coming from the page that knows whether it is currently dark.

Height

Set it with CSS on the element. A chat has no content-driven height — it fills what it is given, like a map does — so there is no auto-resize event. The default is 620 px.

inTouch API · https://api.in-touch.cc · keep your key private.
# intouch api
base    https://api.in-touch.cc
auth    X-API-Key: itk_<64 hex>   one key per user, no expiry, no scopes
docs    https://docs.in-touch.cc
format  every response is JSON and carries "success"

# embed-api
Events the frame sends, commands it accepts, JS surface of <intouch-chat>.

# events
Each arrives as a DOM event on the element and as a postMessage for raw iframes.

  intouch:ready        { version }      frame is up, accepts commands
  intouch:themeApplied { warnings[] }   after every theme application
  intouch:paired       {}               a visitor linked their account
  intouch:unpaired     { reason }       signed out or session expired
  intouch:unread       { count }        number of unread chats changed
  intouch:activeChat   { hasActive }    a chat was opened or closed
  intouch:error        { code }         storage_blocked | pair_rate_limited
                                       | peer_not_found | peer_rate_limited

THIS LIST IS EXHAUSTIVE AND IT IS A PROMISE. No event carries a name, phone
number, chat id, avatar, token or message content.

# commands
  setTheme(theme)            apply a theme live, no reload
  colorScheme property       auto | light | dark | host
  lang attribute             interface language
  logout()                   sign the visitor out of this frame
  requestStorageAccess()     ask for unpartitioned storage (needs user gesture)

Raw iframe form:
  frame.contentWindow.postMessage(
    { source: 'intouch-host', type: 'intouch:setTheme', theme }, 'https://web.in-touch.cc');

The frame accepts commands only from the origin given at load time.

# js
Event listeners can be attached at any time - they survive the upgrade.
Methods and properties cannot: with an async-loaded script, wait for the
definition first (or drop "async" from the script tag).

const chat = document.querySelector('intouch-chat');

// works immediately, even before embed.js has loaded
chat.addEventListener('intouch:unread', e => { badge.textContent = e.detail.count; });

// methods need the element to be defined
await customElements.whenDefined('intouch-chat');
await chat.ready;
chat.setTheme({ colors: { accent: '#0a0' } });
chat.colorScheme = 'dark';

# attributes
  theme         inline JSON, or a hosted id such as t_9fb2c1a4e803
  color-scheme  auto | light | dark | host
  peer          phone number of the counterpart (international form)
  lang          interface language, e.g. de
  base          alternative inTouch origin (defaults to the script's origin)
  unread        written BY the component, for styling via [unread]

A <script type="application/json"> inside the element beats the attribute.
The color-scheme attribute beats colorScheme inside the theme.

# height
Set it with CSS on the element; default 620px. A chat has no content-driven
height, so there is no auto-resize event.

# pages
/                  overview, capability list
/quickstart        get a key, first request
/authentication    key format, rotation, failure modes
/conventions       envelope, status codes, limits, dates
/recipes           recipes capability
/vocabulary        vocabulary capability
/roadmap           capability anatomy, what is planned
every page is also plain text: append .txt  (e.g. https://docs.in-touch.cc/vocabulary.txt)
all pages at once: /llms.txt (index) and /llms-full.txt (everything)

# for agents
- Use only the endpoints listed here; do not invent paths, fields or values.
- Check "success" in the body, not just the HTTP status.
- Error strings are German and developer-facing; branch on the status code.
- Batches are accepted partially: read "rejected" and "errors[].index".
- Dates are UTC. Calendar days are YYYY-MM-DD, timestamps are ISO 8601.
- The API key is a credential: never log it, never pass it to a third party.
- Ask the user before writing content into their app for the first time.