Truto — Unified API Platform
Use this skill when writing code in the user's application that calls the Truto API. This skill helps you build integration features — API calls, webhook handlers, connection UIs, and data-access layers — that run as part of the user's product.
This skill is about code that lives in the user's codebase. For admin setup, one-time debugging, and data exploration in the terminal, see the Truto CLI skill instead.
Important: The Truto API token (
) must only be used on the backend. Never expose it to the browser or include it in client-side code.
When to Use
- Writing API calls to read or write data through Truto (unified, proxy, or custom APIs)
- Building a connection flow for end-users using Truto Link
- Adding webhook handlers to receive real-time events from Truto
- Implementing pagination, error handling, or retry logic for Truto API calls
- Choosing between unified, proxy, and custom APIs for a use case
Install the Truto CLI (recommended)
Before writing any code, install the Truto CLI — it's the fastest way to discover what an integration supports, connect a sandbox account, and try a unified API call without touching your application. Every workflow in this skill (calling the unified API, customizing mappings, overriding integrations per environment, debugging webhooks) has a CLI shortcut you can run in a single line, then port into code once it works.
bash
curl -fsSL https://cli.truto.one/install.sh | bash
truto login --token "$TRUTO_API_TOKEN"
truto whoami -o json
For the full command surface, output formats, and admin workflows, see the Truto CLI skill. For a guided Day-1 walkthrough that combines the CLI with the code in this skill, see Getting Started.
Core Concepts
| Concept | Description | Reference |
|---|
| Environment | Isolated workspace scoping all resources. API tokens are tied to one environment. | Core Resources |
| Integration | A third-party tool definition (e.g., Salesforce, Jira, Slack). | Core Resources |
| Environment Integration | An integration installed into a specific environment with optional config overrides. | Core Resources |
| Integrated Account | A connected instance of an integration for a specific tenant (end-user). | Core Resources |
| Tenant | Your end-user or customer, identified by on integrated accounts. | Core Resources |
| Unified API | Standardized CRUD endpoints across integrations using a common schema. | Unified API |
| Proxy API | Pass-through to the native API of the underlying tool. | Proxy & Custom API |
| Custom API | User-defined API endpoints with custom routing logic. | Proxy & Custom API |
| Sync Job | Scheduled or on-demand data synchronization from integrated accounts. | Sync Jobs |
| Webhook | HTTP callbacks for real-time event notifications. | Webhooks & Notifications |
| Datastore | External storage destinations (MongoDB, GCS, S3, Qdrant) for sync job output. | Datastores |
| Workflow | Event-driven automation triggered by Truto events. | Workflows |
Getting Started
Day 0 — install the CLI first (see
Install the Truto CLI above). Most of what's described below is faster to
try through the
Truto CLI before wiring it into code, then port the same call into your application. The full Day-1 walkthrough lives at
Getting Started; the steps below are the canonical flow you'll port into your application.
1. Get an API Token
Create an API token in the
Truto Dashboard. API tokens can only be created through the dashboard — not via the API or CLI.
Store it as a server-side environment variable (
). This token must
only be used on the backend — never send it to the browser.
2. Create a Backend Route for Link Tokens
Your backend needs an endpoint that generates link tokens for the Truto Link connection flow. This route should handle both new connections and reconnections from the start — this prevents users from creating duplicate accounts when an existing connection fails.
typescript
app.post("/api/truto/link-token", async (req, res) => {
const { tenantId, integratedAccountId } = req.body;
// Reconnect an existing account, or create a new one
const body = integratedAccountId
? { integrated_account_id: integratedAccountId, persist_previous_context: true }
: { tenant_id: tenantId };
const response = await fetch("https://api.truto.one/link-token", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRUTO_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
const { link_token } = await response.json();
res.json({ linkToken: link_token });
});
The shape is the same in every framework — a server-side
to
carrying the API token.
Getting Started has the same route written for
Next.js Route Handlers and
Hono / Cloudflare Workers; pick the variant that matches your stack and adapt the snippet.
When reconnecting, pass
instead of
. This updates the existing account's credentials in place — the same
is preserved, so all sync jobs, webhooks, and references remain intact. Setting
persist_previous_context: true
keeps any custom context from the previous connection.
3. Embed Truto Link in Your Frontend
Install the
Truto Link SDK to embed the connection flow in your UI:
bash
npm install @truto/truto-link-sdk
Then use it in your frontend. The same
call works for both new connections and reconnections — the difference is in the link token your backend generates:
typescript
import authenticate from "@truto/truto-link-sdk";
async function getLinkToken(body: Record<string, string>) {
const res = await fetch("/api/truto/link-token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const { linkToken } = await res.json();
return linkToken;
}
async function openTrutoLink(linkToken: string) {
try {
const result = await authenticate(linkToken);
console.log("Connected:", result.integrated_account_id);
return result;
} catch (err) {
if (err === "closed") {
console.log("User closed the connection dialog");
} else {
console.error("Connection failed:", err);
}
throw err;
}
}
// New connection
const linkToken = await getLinkToken({ tenantId: "tenant-123" });
await openTrutoLink(linkToken);
// Reconnect an existing account (e.g., expired OAuth token)
const reconnectToken = await getLinkToken({ integratedAccountId: "existing-account-id" });
await openTrutoLink(reconnectToken);
See the Truto Link SDK skill for the full SDK reference, including popup mode, same-window redirects, RapidForm, file pickers, and error handling.
4. Listen for the Account to Become Active
After a user connects, the account goes through post-install and validation steps before it's ready. Set up a
webhook to listen for the
integrated_account:active
event — this tells you the account is connected and ready for API calls. See
Connection Flow for the full lifecycle and all events.
typescript
// Backend webhook handler
app.post("/webhooks/truto", async (req, res) => {
const event = req.body;
switch (event.event_type) {
case "integrated_account:active":
// Account is ready — store the integrated_account_id,
// start syncing data, enable features for this tenant
await onAccountReady(event.payload);
break;
case "integrated_account:post_install_error":
case "integrated_account:validation_error":
// Connection failed — notify the user or retry
await onAccountError(event.payload);
break;
}
res.sendStatus(200);
});
You can also use Truto Workflows to automatically trigger actions (like starting a sync job) when an account becomes active. See Workflows for details.
Tip while developing. You don't need to wait for the webhook to grab a working
— list connected accounts from the CLI with
truto accounts list -o json
(or filter to sandboxes with
) and copy one out. Use that ID to test the unified-API steps below before the webhook plumbing is in place.
5. Read Data via the Unified API
Once an account is active, fetch normalized data:
typescript
const accountId = "<integrated_account_id>";
const response = await fetch(
`https://api.truto.one/unified/crm/contacts?integrated_account_id=${accountId}`,
{
headers: {
"Authorization": `Bearer ${process.env.TRUTO_API_TOKEN}`,
},
}
);
const { result, next_cursor } = await response.json();
6. Write Data
typescript
const response = await fetch(
`https://api.truto.one/unified/crm/contacts?integrated_account_id=${accountId}`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRUTO_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
first_name: "Jane",
last_name: "Doe",
email: "jane@example.com",
}),
}
);
7. Use the Proxy API for Native Access
When you need integration-specific fields not in the unified schema:
typescript
const response = await fetch(
`https://api.truto.one/proxy/contacts?integrated_account_id=${accountId}`,
{
headers: {
"Authorization": `Bearer ${process.env.TRUTO_API_TOKEN}`,
},
}
);
When to Use Unified vs Proxy vs Custom API
| Use Case | API | Why |
|---|
| Standardized CRUD across integrations | Unified | Same request/response schema regardless of the underlying tool |
| Access native API features not in unified schema | Proxy | Full access to the tool's native endpoints |
| Custom business logic or transformations | Custom | Define your own endpoints with custom routing |
| Bulk data operations with dependencies | Batch Request | Execute multiple API calls with dependency graph in one request |
Authentication
All API requests use Bearer token authentication. The API token must only be used server-side. See Authentication for details on API tokens, link tokens, and integrated account tokens.
References
Start here
| Document | Topics |
|---|
| Getting Started | Day-1 tutorial: CLI install → login → connect a sandbox → write the link-token route → first unified API call → port the same call into code |
Customization (the most-used "extend the platform" surfaces)
| Document | Topics |
|---|
| Authoring Integrations | Author a brand-new integration definition from scratch: full schema, all five credential formats, resources/methods, pagination, rate-limit, inbound webhook receiver, lifecycle actions, plus truto integrations init/validate/create
workflow and an Acme CRM worked example |
| Customizing Integrations | Per-environment HTTP-layer overrides on an existing integration: auth header, pagination, rate-limit detection, inbound webhook verification/transform |
| Unified API Customization | Modifying existing unified API mappings per environment, per-account overrides, creating your own custom unified models |
Core API surface
| Document | Topics |
|---|
| Unified API | Unified CRUD, meta endpoints, pagination, SuperQuery |
| Proxy & Custom API | Proxy pass-through, custom endpoints, authoring custom-API handlers, batch requests |
| Authentication | API tokens, link tokens, integrated account tokens, auth patterns |
| MCP Tokens | MCP protocol tokens for AI agents, tool filtering, expiration |
| Connection Flow | Connection lifecycle, reconnecting accounts, webhook events, post-connection automation |
| Core Resources | Environments, integrations, integrated accounts, teams |
| Integrated Account Context | Context field lifecycle, credentials, instance config, usage in APIs/sync/workflows |
Automation & data movement
| Document | Topics |
|---|
| Sync Jobs | Sync jobs, runs, cron triggers, templates, run state |
| Webhooks & Notifications | Webhooks, notification destinations, inbound webhooks |
| Datastores | External storage destinations (MongoDB, GCS, S3, Qdrant) for sync job output |
| Workflows | Event-driven automations triggered by Truto events |
| Daemon Jobs | Background processing tasks and runs |
Operational
| Document | Topics |
|---|
| Files & Logs | File uploads and API/operation log queries |
| Static Gates | Embeddable connection entry points |
Companion Skills
- Truto CLI — for setup tasks (creating integrations, connecting test accounts, exploring resources, debugging API calls). The CLI is an admin and debugging tool you run in the terminal; this skill is for the integration code that lives in your application.
- Truto Link SDK — for embedding the Truto connection UI in a frontend application using (popup mode, RapidForm, file pickers, error handling).
- truto-jsonata — for writing JSONata expressions inside Truto config: unified API mapping overrides (, , , , etc.), custom unified model definitions, per-account overrides, environment integration overrides (auth/pagination/rate-limit/webhooks), sync job templates, workflows, daemon jobs, and scheduled actions. Documents the custom functions added by on top of standard JSONata. Pair with Unified API Customization when modifying unified mappings.