Integrations

Overview
Integrations are the connections to foreign systems — the place where credentials for external services live.
They differ from API tokens in direction: a token lets a foreign system in to us, an integration lets us out. Both directions are managed separately because they have to be revoked separately.
Core tasks
Create an integration. New integration requires a name, a provider and the configuration as key/value pairs.
Use a provider preset. For known services — LinkedIn, Meta (Facebook/Instagram) and X — a preset pre-fills the provider and the expected configuration keys. That saves looking up exactly what a key has to be called. The free route without a preset remains available for everything else.
Store credentials. Token keys such as access_token or page_access_token are stored encrypted and write-only: on reloading they appear masked as ********. You can overwrite them but not read them back — not even as an administrator.
Activate. The active state decides whether the connection is used. The list shows name, provider, status and modification date.
Keep an eye on the connection. The Connection column shows the result of the latest check per integration: Connected, Error or Never checked — plus when it was checked and, on an error, the message of the remote side. Secrets never appear there; a provider quoting the key in its error message shows up redacted. Every active integration is checked hourly; Check connection now (heart icon) checks immediately. Deactivated integrations are not checked — nobody uses them, their last state stays.
How deep the check goes. For every connection with its own plugin the check calls the remote side — with the cheapest call that proves the credentials: renew a token, fetch the profile, the account or the model list. This covers Google, Microsoft, the AI providers, lexoffice, Slack, the social networks (LinkedIn, Meta, X, TikTok, YouTube), HubSpot, awork, all shipping carriers, the sales channels, Stripe, PayPal, finAPI, Twilio, Zoom, Calendly, Postmark, Google Workspace, the geocoder (geocoder, search for a fixed place) and the license server (license_server, first page of activations). Nothing is created, sent or booked. Carriers without a "who am I" call look up a deliberately unknown tracking number: only a rejected login counts as an error. A sales channel login is checked through the channel that uses it — without a channel the shop address is missing (Credential missing: salesChannel). For the remaining logins (CalDAV calendars, ICS subscriptions, Shopware account) it checks the credentials: readable (not lost to a key rotation), not expired, stored at all. Below the status it says which of the two checks applies.
Read the sync log. The list icon opens the integration's sync log: the latest runs with time, kind (connection check, contact, calendar and channel sync, mailbox and transaction fetch, HubSpot and awork import, lexoffice transfer and payment matching, license server reconciliation …), result, number of records transferred, duration and message. The latest 50 runs are kept per integration and kind — an hourly check never pushes out a sync.
Twilio for WhatsApp and SMS. The integration with provider twilio carries account_sid, your own numbers sms_from/whatsapp_from and the credential auth_token. Incoming messages arrive via the Messages webhook https://<your-domain>/api/v1/sms/public/twilio-inbound (optionally inbound_webhook_url if the signed address differs) and become tickets. Images and files of a message (MMS, WhatsApp media) are stored as attachments on the ticket — a message with only a photo becomes a ticket too. Media are only fetched from Twilio addresses. Alternatively you can connect the Conversations API: conversations_service_sid (the Conversations service, IS…), the address the same address as above, https://<your-domain>/api/v1/sms/public/twilio-inbound, as post-event webhook onMessageAdded (optionally conversations_webhook_url) and conversations_author as the sender name of replies (default support). Each conversation becomes a ticket, further messages are added to it, and replies from the ticket go into the same conversation. Delivery feedback: when an SMS or WhatsApp message is sent, the system asks Twilio for a status callback to the same address as above, https://<your-domain>/api/v1/sms/public/twilio-inbound (from inbound_webhook_url, otherwise the app address) — there is nothing to set up. The thread entry then shows Delivered or Bounced with the Twilio code. Without a public address (for example on a test system under localhost) it stays Sent.
Slack support channels. In the Slack integration, support_channels lists the channel IDs that create tickets (comma-separated) — see Connect Slack.
Set up an incoming webhook. Next to outgoing webhooks (we report something outwards) there is the other direction: a foreign system reports something to us. Such a webhook gets the direction incoming and a secret; the address is https://<your-domain>/api/v1/platform/public/webhooks/<id>. The sender signs the body with it (HMAC-SHA256, header X-Octibiz-Signature) — without a valid signature the call is rejected. The route needs no sign-in and is therefore guarded three times: a rate limit per sender address, a size cap on the body, and the signature. An accepted call answers immediately with accepted and only then raises the automation trigger Webhook received — the sender never waits for our processing. If the same call arrives twice, the answer says duplicate and nothing happens a second time. The secret can be reissued at any time; the sender then has to adopt it.
Mind the connection notices. Above the list, connections report a setup that no longer works — for example Sendcloud while the shipping method is still a number from the old interface: no labels are created with it any more. The notice names the number and what to enter instead; the same notice appears in the log after a system update. Shipping cost rules that prescribe such a number as the shipping method are reported the same way (with identifier, zone and carrier — fix them under Settings → Shipping, field Shipping method), as are shipments without a label carrying such a number: buying their label again fails, so cancel them and create them again with the code of the shipping option. Likewise OctiConnect flows whose shipping building block stored such a number — the notice names the flow and links to it.
Fields in detail
| Field | Required | Values / format | What it does |
|---|---|---|---|
Provider provider | yes | an available provider, max. 100 characters | What is connected to. The provider determines which settings appear below and which login is needed. |
Name name | yes | text, max. 255 characters | What the connection is called. With several accounts at the same provider it is the only distinction — "Google Workspace accounting" rather than "Google". |
Settings config | no | depending on the provider | Credentials, keys, targets. Secrets are stored encrypted and never shown again; entering them anew replaces them. |
Brand brandId | no | one of your brands | Which brand the connection applies to. A separate account per brand is possible and often necessary. |
Active active | no | yes/no | Whether the connection is used. Off pauses it without losing the setup — the first move when a provider misbehaves. |
If a login expires, the connection rests visibly and reports itself instead of quietly doing nothing. That is the difference between "nothing has arrived for three weeks" and a message on day one.
Settings & permissions
- No route permission of its own. The page is reachable; creating and changing is checked by the
server.
- Credentials cannot be read back. Whoever needs the value fetches it from the provider, not from
here.
- AI providers do not belong here. Their access lives under AI settings.
- A provider may appear several times — per brand or per account, for instance.
FAQ & troubleshooting
The connection fails although the key is correct. Check the key names in the configuration. A provider preset names them correctly; entered by hand, typos creep in that look like a wrong password from the outside.
A token has expired. Renew it at the provider and enter the new value. The old one cannot be inspected — so a comparison is not possible.
I can no longer see the stored value. By design. Credentials are stored encrypted and displayed masked.
The connection says "Error" although everything worked yesterday. Open the sync log: the message names the reason — expired access, rejected key, unreachable remote side. After fixing it, use Check connection now instead of waiting for the next hourly check.
We want to stop a connection temporarily. Deactivate it rather than deleting the credentials.