Conduits Docs

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.

On this page