API Endpoints
Reference for all Conduits API endpoints — syncs, digests, contacts, settings, and Telegram management.
Sync
Trigger Sync
POST /api/sync/trigger
Queues an immediate sync job for the authenticated user. Returns the BullMQ job ID for status polling.
Response:
{
"jobId": "sync:clxxx:manual:1"
}
Sync Status
GET /api/sync/status?jobId=sync:clxxx:manual:1
Returns the current state of a sync job.
Response:
{
"state": "completed",
"progress": 100,
"result": {
"dialogsProcessed": 12,
"digestsCreated": 8,
"notesCreated": 3,
"errors": []
}
}
Possible states: waiting, active, completed, failed, not_found.
Digests
List Digests
GET /api/digests
Returns the 50 most recent digests for the authenticated user, ordered by date descending.
Response:
{
"digests": [
{
"id": "clxxx",
"digestDate": "2026-03-20T00:00:00.000Z",
"messageCount": 14,
"status": "COMPLETE",
"summary": "Discussed Series A timeline...",
"structuredData": {
"topics": ["Series A", "Climate tech"],
"action_items": [...],
"sentiment": "positive",
"urgency": "high"
},
"dialog": {
"peerName": "Sarah Chen",
"peerUsername": "sarahchen"
}
}
]
}
Digest statuses: PENDING, SUMMARIZING, SYNCING, COMPLETE, FAILED, SKIPPED.
Contacts
List Contacts
GET /api/hubspot/contacts/search
Returns all tracked Telegram dialogs with their HubSpot match status.
Response:
{
"contacts": [
{
"id": "clxxx",
"peerName": "Sarah Chen",
"peerUsername": "sarahchen",
"peerPhone": "+14155551234",
"matchStatus": "CONFIRMED",
"matchConfidence": 1.0,
"hubspotContactId": "12345",
"hubspotContactName": null
}
]
}
Match statuses: UNMATCHED, AUTO_PHONE, AUTO_USERNAME, AUTO_NAME, CONFIRMED, IGNORED, CREATED.
Confirm or Ignore Match
PATCH /api/hubspot/contacts/search
Content-Type: application/json
{
"dialogId": "clxxx",
"action": "confirm"
}
Actions: confirm (sets status to CONFIRMED), ignore (sets status to IGNORED and clears the HubSpot link).
Suggest HubSpot Matches
GET /api/hubspot/contacts/suggest?name=Sarah+Chen
Searches HubSpot for contacts matching the given name. Splits on separators (|, -, /), searches first name and last name independently, and deduplicates results.
Response:
{
"suggestions": [
{
"id": "12345",
"firstname": "Sarah",
"lastname": "Chen",
"email": "sarah@company.com",
"company": "Acme Inc"
}
]
}
Returns up to 5 results. Returns empty array if name is empty or "Unknown".
Confirm Match with Specific Contact
PATCH /api/hubspot/contacts/match
Content-Type: application/json
{
"dialogId": "clxxx",
"hubspotContactId": "12345",
"matchStatus": "CONFIRMED"
}
Links a Telegram dialog to a specific HubSpot contact. Sets confidence to 1.0.
Create HubSpot Contact
POST /api/hubspot/contacts/create
Content-Type: application/json
{
"dialogId": "clxxx",
"firstname": "Sarah",
"lastname": "Chen",
"email": "sarah@company.com",
"phone": "+14155551234"
}
Creates a new contact in HubSpot with the provided details plus the Telegram username (if available). Links the dialog to the new contact with status CREATED.
Response:
{
"success": true,
"contactId": "12345",
"contact": {
"id": "12345",
"firstname": "Sarah",
"lastname": "Chen",
"email": "sarah@company.com"
}
}
Telegram
Start Authentication
POST /api/telegram/connect
Content-Type: application/json
{
"phone": "+14155551234"
}
Sends a verification code to the given phone number via Telegram. Returns an auth token for the next step.
Response:
{
"authToken": "a1b2c3..."
}
Verify Code
POST /api/telegram/verify
Content-Type: application/json
{
"authToken": "a1b2c3...",
"code": "12345"
}
Response (success):
{
"success": true,
"accountId": "clxxx",
"telegramUser": {
"firstName": "Sebastian",
"lastName": "Frankel",
"username": "sfrankel"
}
}
Response (2FA required):
{
"needs2FA": true
}
Verify 2FA Password
POST /api/telegram/verify-2fa
Content-Type: application/json
{
"authToken": "a1b2c3...",
"password": "my-cloud-password"
}
Same response format as verify code.
List Dialogs
GET /api/telegram/dialogs
Returns all Telegram dialogs for the authenticated user, merged with tracking state from the database.
Disconnect
POST /api/telegram/disconnect
Content-Type: application/json
{
"accountId": "clxxx"
}
Revokes the Telegram session (calls auth.LogOut), wipes encrypted credentials from the database, and sets the account to inactive.
Settings
Get Settings
GET /api/settings
Returns the user's sync configuration.
Response:
{
"config": {
"syncTime": "21:00",
"timezone": "America/New_York",
"includeGroups": false,
"minMessages": 1,
"summaryStyle": "BUSINESS",
"autoCreateContacts": false
}
}
Update Settings
POST /api/settings
Content-Type: application/json
{
"syncTime": "21:00",
"timezone": "America/New_York",
"includeGroups": false,
"minMessages": 1,
"summaryStyle": "BUSINESS"
}
Uses upsert — creates the config if it doesn't exist, updates if it does.
Admin
System Status
GET /api/admin/status?key=YOUR_ADMIN_API_KEY
Returns system health metrics. Requires the ADMIN_API_KEY environment variable.
Response:
{
"users": { "total": 42, "paying": 18 },
"syncs_24h": { "COMPLETE": 156, "FAILED": 3, "PENDING": 12 },
"uptime": 86400,
"timestamp": "2026-03-21T12:00:00.000Z"
}
HubSpot OAuth
Start OAuth Flow
GET /api/hubspot/connect
Redirects to HubSpot's OAuth authorization page with the correct scopes and a CSRF-preventing state parameter. After authorization, HubSpot redirects back to /api/hubspot/callback.
OAuth Callback
GET /api/hubspot/callback?code=xxx&state=xxx
Exchanges the authorization code for tokens, validates the state parameter, stores encrypted tokens, creates custom contact properties in HubSpot, and redirects to the settings page.