Overview
Connect, manage, and use third-party integrations (Slack, Jira, Google Calendar, Zoho Books, Google Sheets)
An integration is a connected third-party app, either an action target usable from a journey node (Slack, Jira, Google Calendar) or a data source kept in sync with your contacts (Zoho Books, Google Sheets). See the Integrations guide for what each provider does and how connecting looks from the dashboard.
Connections are backed by Composio, which manages the OAuth flow and stores provider credentials — Lemu never sees or stores your provider password. There's no endpoint to fetch a raw provider access token; actions run server-side via Composio using the stored connection.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /integration/ | List all integrations for the organization |
POST | /integration/connect | Start a Composio OAuth connection for a provider |
POST | /integration/connect/finalize | Confirm a connection is active and persist it |
POST | /integration/{integration_id}/disconnect | Fully revoke and remove an integration |
PUT | /integration/{integration_id} | Update a Google Sheets integration's selected files (legacy) |
GET | /integration/{provider}/status | Whether the org has an active integration for a provider |
GET | /integration/{integration_id}/zoho-books/organizations | List Zoho organizations available to a connected account |
POST | /integration/{integration_id}/zoho-books/organization | Select which Zoho organization to sync |
GET | /integration/{integration_id}/field-mapping | Read a data-source integration's contact field mapping |
PUT | /integration/{integration_id}/field-mapping | Replace a data-source integration's contact field mapping |
POST | /integration/{integration_id}/contacts/{contact_id}/push | Push one contact's outbound-mapped fields to the connected CRM/sheet |
POST | /integration/{integration_id}/resync | Manually trigger an inbound sync now, instead of waiting for the next poll |
GET | /integration/{integration_id}/google-sheet/search | Search spreadsheets visible to the connected Google account |
GET | /integration/{integration_id}/google-sheet/headers | Preview a spreadsheet's header row and a best-guess field mapping |
POST | /integration/{integration_id}/google-sheet/select | Confirm the sheet, tab, and column mapping to sync |
GET | /integration/slack/channels | List channels in the connected Slack workspace |
GET | /integration/jira/projects | List projects in the connected Jira site |
GET | /integration/jira/issue-types | List issue types available in the connected Jira site |
Most of these endpoints exist to back the dashboard's Integrations page and the journey node config panels, but they're ordinary authenticated API endpoints — anything below works the same way with an X-API-Key header as it does from the dashboard's own session.
List integrations#
curl https://app.lemuai.com/api/v1/integration/ \
-H "X-API-Key: lemu_your_api_key"[
{
"id": 5,
"integration_id": "conn_abc123",
"organisation_id": 7,
"created_by": 3,
"provider": "slack",
"is_active": true,
"created_at": "2026-08-01T12:00:00Z",
"action": "connected",
"provider_data": { "channel": "#general" }
}
]provider_data carries a little provider-specific context: the default channel for slack, and sheet_url / sheet_name / contact_list_name once a sheet has been picked for google-sheet.
Connect a provider#
Starts the OAuth flow. Most providers need no connection_params; Jira requires a subdomain (the part before .atlassian.net).
curl -X POST https://app.lemuai.com/api/v1/integration/connect \
-H "X-API-Key: lemu_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "provider": "jira", "connection_params": { "subdomain": "acme" } }'{
"request_id": "conn_req_xyz789",
"redirect_url": "https://backend.composio.dev/connect/conn_req_xyz789"
}Open redirect_url in a browser to complete the provider's consent screen — this step is inherently interactive and can't be done as a plain API call. redirect_url is null if the organization already has an active connection for this provider; in that case, skip straight to finalize with request_id as the connected_account_id.
Once the user completes the popup, confirm and persist the connection:
curl -X POST https://app.lemuai.com/api/v1/integration/connect/finalize \
-H "X-API-Key: lemu_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "connected_account_id": "conn_req_xyz789", "provider": "jira" }'This re-checks the connection's status directly against Composio rather than trusting client-supplied OAuth callback params, and is idempotent — calling it twice for the same connected_account_id returns the existing integration rather than erroring.
Connecting a new integration enforces your plan's integration-count entitlement — expect a 400 if you're at your plan's limit.
Disconnect a provider#
curl -X POST https://app.lemuai.com/api/v1/integration/5/disconnect \
-H "X-API-Key: lemu_your_api_key"{ "status": "disconnected" }This revokes the underlying Composio connection, not just the row in Lemu's database — reconnecting afterward always shows a fresh consent screen, which is what lets you grant additional scopes that an earlier connection was missing.
Field mapping (data-source integrations)#
For zoho_books, each entry has a direction (inbound, outbound, or bidirectional); for google-sheet, it's a flat { lemu_field: sheet_column_header } map instead, since a spreadsheet has no separate concept of direction per column.
curl -X PUT https://app.lemuai.com/api/v1/integration/5/field-mapping \
-H "X-API-Key: lemu_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"field_mapping": {
"email": { "external_field": "email", "direction": "bidirectional" },
"phone": { "external_field": "mobile", "direction": "inbound" }
}
}'Errors#
| Status | Meaning |
|---|---|
400 | Missing organization context, unknown provider, invalid field mapping, or a data-source-only endpoint called for an action-target provider |
403 | insufficient_permissions: <detail> — the connected account's OAuth grant doesn't cover the requested action. Disconnect and reconnect to get a fresh consent screen |
404 | Integration not found (or not_connected, from the /{provider}/status-style lookups, when no active integration exists for that provider) |
502 | The provider's API rejected the request after a valid connection was found (e.g. a since-deleted sheet or Zoho organization) |
