Architecture
Truto is middleware. Your app talks to one URL — api.truto.one — with one bearer token, and Truto holds every vendor credential and forwards each call to the right vendor.
flowchart LR
yourApp["Your app"] -->|"TRUTO_API_TOKEN"| trutoApi["Truto API<br/>api.truto.one"]
trutoApi -->|"vendor credentials"| vendor["Vendor API"]
Two consequences fall out of that:
- Truto handles vendor credentials for you. Your customer connects through Truto Link — whether that's an OAuth handoff, an API key prompt, or whatever flow the integration needs. Truto stores the credentials securely, refreshes OAuth tokens when the vendor supports refresh, and uses the right credential when forwarding calls to the vendor. Your app keeps using the same
TRUTO_API_TOKEN. - Pass-through, not cache. Each call hits the vendor live. Truto does not store the response. The trade-offs that follow — rate limits, latency, filter availability — are written up in Realtime data model.
The named entities
These are the nouns you'll see in the API, the SDKs, and app.truto.one. Each one links to the page that owns it.
| Entity | What it is |
|---|---|
| Team | Your Truto account. Owns environments, billing, and members. Manage at Settings → Team Members. |
| Environment | A logical group of installed integrations, integrated accounts, API tokens, and webhooks. Production, staging, and development are usually separate environments. |
| Integration | A vendor connector — hubspot, salesforce, gmail. Installed once per environment from the catalog. |
| Integrated account | One end-customer's connection to one integration in one environment. Has an integrated_account_id and a tenant_id you choose. Every data-plane call carries ?integrated_account_id=.... |
tenant_id |
Your grouping key for connected accounts. Pick whatever string fits how you model customers — for example, team:<team_id> if you group by end-customer org, user:<user_id> if you group by individual user, or a compound key like team:<team_id>:user:<user_id> when both matter. tenant_id is not unique: one tenant_id can have multiple integrated accounts attached to it. |
| Unified API | A category-level shape (CRM, ATS, ticketing) that one call can target across vendors. Sits at /unified/{model}/{resource}. |
| Proxy and Custom APIs | The escape hatches at /proxy/{resource} (raw vendor shape) and /custom/{resource} (your own server-side handlers). Use when the unified shape doesn't carry a field you need. |
| Link token | Short-lived, single-use credential your backend mints and your frontend hands to Truto Link. Created at POST /link-token. |
| API token | Server-side bearer for api.truto.one. Scoped to one environment. Never ship this to the browser. |
| Webhooks | Outbound events Truto sends your backend — connection lifecycle (integrated_account:active, :authentication_error), sync runs, and webhook events from the underlying product when Truto receives and forwards them to your app. |
What you see, what your customer sees
Two surfaces sit outside the diagram:
- You see the Truto Dashboard — install integrations, install Unified APIs, mint API tokens, register webhooks, inspect integrated accounts. Every action there is also an HTTP route, so anything you do by hand can be automated. See API reference.
- Your customers see Truto Link — the connection UI your frontend embeds with
@truto/truto-link-sdk. It runs the OAuth dance or collects API keys, then hands the result back to Truto. It is the only Truto surface end customers ever interact with.
Next
Read Getting started for the runnable version of the request flow above — install an integration, mint a link token, open Truto Link, and make the first Unified API call. Read Why Truto if you're still deciding whether the pass-through model is the right fit.