Platform Integrations

Platform Integrations connect external services like Discord, Slack, and Microsoft Teams to LVNG workspaces. All endpoints enforce multi-tenant isolation -- integrations are scoped to the customer's workspaces via customer_id verification. Sensitive configuration data (tokens, webhook secrets) is masked in responses. Supported platforms are registered dynamically via the PlatformRegistry.

Base path: /api/v2/platform-integrations|Auth: JWT|Tenant isolation: customer_id / workspace ownership

List Integrations

GET/api/v2/platform-integrationsAuthenticated

Returns all platform integrations across all workspaces owned by the authenticated customer. Sensitive fields (config, webhook_secret) are masked -- config shows {configured: true|false} and webhook_secret shows '***' or null.

Request

cURL
400">curl -X 400">GET https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"integrations": [
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      400">class="text-emerald-400">"workspace_id": 400">class="text-emerald-400">"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
      400">class="text-emerald-400">"platform": 400">class="text-emerald-400">"discord",
      400">class="text-emerald-400">"config": { 400">class="text-emerald-400">"configured": true },
      400">class="text-emerald-400">"webhook_secret": 400">class="text-emerald-400">"***",
      400">class="text-emerald-400">"enabled": true,
      400">class="text-emerald-400">"connected": true,
      400">class="text-emerald-400">"last_connected_at": 400">class="text-emerald-400">"2026-03-19T09:00:00.000Z",
      400">class="text-emerald-400">"connection_error": null,
      400">class="text-emerald-400">"api_key": null,
      400">class="text-emerald-400">"api_key_created_at": null,
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-01-20T08:00:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T09:00:00.000Z"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"b2c3d4e5-f6a7-8901-bcde-f12345678901",
      400">class="text-emerald-400">"workspace_id": 400">class="text-emerald-400">"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
      400">class="text-emerald-400">"platform": 400">class="text-emerald-400">"slack",
      400">class="text-emerald-400">"config": { 400">class="text-emerald-400">"configured": true },
      400">class="text-emerald-400">"webhook_secret": 400">class="text-emerald-400">"***",
      400">class="text-emerald-400">"enabled": true,
      400">class="text-emerald-400">"connected": true,
      400">class="text-emerald-400">"last_connected_at": 400">class="text-emerald-400">"2026-03-18T22:00:00.000Z",
      400">class="text-emerald-400">"connection_error": null,
      400">class="text-emerald-400">"api_key": null,
      400">class="text-emerald-400">"api_key_created_at": null,
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-02-10T14:30:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-18T22:00:00.000Z"
    }
  ]
}

Get Integration

GET/api/v2/platform-integrations/:idAuthenticated

Returns a single platform integration. Config and webhook_secret are masked. Returns 404 if the integration does not exist or does not belong to a workspace owned by the customer.

Path Parameters

idstring (UUID)required

The unique identifier of the integration.

Request

cURL
400">curl -X 400">GET https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"integration": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    400">class="text-emerald-400">"workspace_id": 400">class="text-emerald-400">"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
    400">class="text-emerald-400">"platform": 400">class="text-emerald-400">"discord",
    400">class="text-emerald-400">"config": { 400">class="text-emerald-400">"configured": true },
    400">class="text-emerald-400">"webhook_secret": 400">class="text-emerald-400">"***",
    400">class="text-emerald-400">"enabled": true,
    400">class="text-emerald-400">"connected": true,
    400">class="text-emerald-400">"last_connected_at": 400">class="text-emerald-400">"2026-03-19T09:00:00.000Z",
    400">class="text-emerald-400">"connection_error": null,
    400">class="text-emerald-400">"api_key": null,
    400">class="text-emerald-400">"api_key_created_at": null,
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-01-20T08:00:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T09:00:00.000Z"
  }
}

Create Integration

POST/api/v2/platform-integrationsAuthenticated

Creates a new platform integration for a workspace. The workspace must belong to the authenticated customer. A webhook_secret is auto-generated. Returns 409 if the workspace already has an integration for that platform. Valid platforms are registered dynamically via PlatformRegistry.

Body Parameters

workspace_idstring (UUID)required

The workspace to attach this integration to. Must be owned by the authenticated customer.

platformstringrequired

Platform identifier (e.g., discord, slack, teams). Validated against PlatformRegistry.

configobject

Platform-specific configuration object (tokens, server IDs, etc.).

enabledboolean
Default: true

Whether the integration is active.

Request

cURL
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY" \
  -H 400">class="text-emerald-400">"Content-Type: application/json" \
  -d '{
    400">class="text-emerald-400">"workspace_id": 400">class="text-emerald-400">"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
    400">class="text-emerald-400">"platform": 400">class="text-emerald-400">"slack",
    400">class="text-emerald-400">"config": {
      400">class="text-emerald-400">"bot_token": 400">class="text-emerald-400">"xoxb-xxxxxxxxxxxx-xxxxxxxxxxxx",
      400">class="text-emerald-400">"team_id": 400">class="text-emerald-400">"T0123456789"
    },
    400">class="text-emerald-400">"enabled": true
  }'

Response 201

{
  400">class="text-emerald-400">"integration": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"c3d4e5f6-a7b8-9012-cdef-123456789012",
    400">class="text-emerald-400">"workspace_id": 400">class="text-emerald-400">"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
    400">class="text-emerald-400">"platform": 400">class="text-emerald-400">"slack",
    400">class="text-emerald-400">"config": { 400">class="text-emerald-400">"configured": true },
    400">class="text-emerald-400">"webhook_secret": null,
    400">class="text-emerald-400">"enabled": true,
    400">class="text-emerald-400">"connected": null,
    400">class="text-emerald-400">"last_connected_at": null,
    400">class="text-emerald-400">"connection_error": null,
    400">class="text-emerald-400">"api_key": null,
    400">class="text-emerald-400">"api_key_created_at": null,
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T10:00:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T10:00:00.000Z"
  }
}

Update Integration

PATCH/api/v2/platform-integrations/:idAuthenticated

Updates an integration's config or enabled status. If config is changed, the cached integration instance is cleared so the next operation uses the new configuration.

Path Parameters

idstring (UUID)required

The unique identifier of the integration.

Body Parameters

configobject

Updated platform-specific configuration. Clears the cached instance when changed.

enabledboolean

Enable or disable the integration.

Request

cURL
400">curl -X 400">PATCH https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/c3d4e5f6-a7b8-9012-cdef-123456789012 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY" \
  -H 400">class="text-emerald-400">"Content-Type: application/json" \
  -d '{
    400">class="text-emerald-400">"enabled": false
  }'

Response 200

{
  400">class="text-emerald-400">"integration": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"c3d4e5f6-a7b8-9012-cdef-123456789012",
    400">class="text-emerald-400">"workspace_id": 400">class="text-emerald-400">"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
    400">class="text-emerald-400">"platform": 400">class="text-emerald-400">"slack",
    400">class="text-emerald-400">"config": { 400">class="text-emerald-400">"configured": true },
    400">class="text-emerald-400">"enabled": false,
    400">class="text-emerald-400">"connected": null,
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T10:00:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T10:20:00.000Z"
  }
}

Delete Integration

DELETE/api/v2/platform-integrations/:idAuthenticated

Permanently deletes a platform integration and disconnects any active instance. The cached integration instance is removed. Returns 404 if the integration does not belong to the customer's workspaces.

Path Parameters

idstring (UUID)required

The unique identifier of the integration to delete.

Request

cURL
400">curl -X 400">DELETE https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/c3d4e5f6-a7b8-9012-cdef-123456789012 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true
}

Test Connection

POST/api/v2/platform-integrations/:id/testAuthenticated

Tests the connection to the external platform using the stored configuration. On success, updates the connected field to true and sets last_connected_at. On failure, stores the error message in connection_error.

Path Parameters

idstring (UUID)required

The unique identifier of the integration to test.

Request

cURL
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/test \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true
}

Sync Channels

POST/api/v2/platform-integrations/:id/sync-channelsAuthenticated

Fetches all channels from the external platform and upserts them into the platform_channels table. Uses the integration instance's fetchChannels method. Existing channels are updated via upsert on integration_id + platform_channel_id.

Path Parameters

idstring (UUID)required

The unique identifier of the integration.

Request

cURL
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/sync-channels \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"channelCount": 5,
  400">class="text-emerald-400">"channels": [
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"1234567890123456789",
      400">class="text-emerald-400">"name": 400">class="text-emerald-400">"general",
      400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"topic": 400">class="text-emerald-400">"General discussion",
      400">class="text-emerald-400">"serverId": 400">class="text-emerald-400">"9876543210987654321"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"2345678901234567890",
      400">class="text-emerald-400">"name": 400">class="text-emerald-400">"engineering",
      400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"topic": 400">class="text-emerald-400">"Engineering team discussions",
      400">class="text-emerald-400">"serverId": 400">class="text-emerald-400">"9876543210987654321"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"3456789012345678901",
      400">class="text-emerald-400">"name": 400">class="text-emerald-400">"product",
      400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"topic": 400">class="text-emerald-400">"Product roadmap and feedback",
      400">class="text-emerald-400">"serverId": 400">class="text-emerald-400">"9876543210987654321"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"4567890123456789012",
      400">class="text-emerald-400">"name": 400">class="text-emerald-400">"design",
      400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"topic": null,
      400">class="text-emerald-400">"serverId": 400">class="text-emerald-400">"9876543210987654321"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"5678901234567890123",
      400">class="text-emerald-400">"name": 400">class="text-emerald-400">"support",
      400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"topic": 400">class="text-emerald-400">"Customer support escalations",
      400">class="text-emerald-400">"serverId": 400">class="text-emerald-400">"9876543210987654321"
    }
  ]
}

List Synced Channels

GET/api/v2/platform-integrations/:id/channelsAuthenticated

Returns all channels previously synced for an integration from the platform_channels table. Channels are ordered alphabetically by name.

Path Parameters

idstring (UUID)required

The unique identifier of the integration.

Request

cURL
400">curl -X 400">GET https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/channels \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"channels": [
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"7b8c9d0e-1f2a-3b4c-5d6e-7f8a9b0c1d2e",
      400">class="text-emerald-400">"integration_id": 400">class="text-emerald-400">"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      400">class="text-emerald-400">"platform_channel_id": 400">class="text-emerald-400">"1234567890123456789",
      400">class="text-emerald-400">"platform_server_id": 400">class="text-emerald-400">"9876543210987654321",
      400">class="text-emerald-400">"channel_name": 400">class="text-emerald-400">"engineering",
      400">class="text-emerald-400">"channel_type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"channel_topic": 400">class="text-emerald-400">"Engineering team discussions",
      400">class="text-emerald-400">"auto_sync_messages": false,
      400">class="text-emerald-400">"sync_direction": null,
      400">class="text-emerald-400">"lvng_conversation_id": null,
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T09:35:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T09:35:00.000Z"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
      400">class="text-emerald-400">"integration_id": 400">class="text-emerald-400">"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      400">class="text-emerald-400">"platform_channel_id": 400">class="text-emerald-400">"2345678901234567890",
      400">class="text-emerald-400">"platform_server_id": 400">class="text-emerald-400">"9876543210987654321",
      400">class="text-emerald-400">"channel_name": 400">class="text-emerald-400">"general",
      400">class="text-emerald-400">"channel_type": 400">class="text-emerald-400">"text",
      400">class="text-emerald-400">"channel_topic": 400">class="text-emerald-400">"General discussion",
      400">class="text-emerald-400">"auto_sync_messages": true,
      400">class="text-emerald-400">"sync_direction": 400">class="text-emerald-400">"both",
      400">class="text-emerald-400">"lvng_conversation_id": 400">class="text-emerald-400">"e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T09:35:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T10:00:00.000Z"
    }
  ]
}

Update Channel Settings

PATCH/api/v2/platform-integrations/channels/:channelIdAuthenticated

Updates sync settings for a platform channel. Verifies that the channel's integration belongs to a workspace owned by the authenticated customer.

Path Parameters

channelIdstring (UUID)required

The LVNG platform_channels table ID (not the external channel ID).

Body Parameters

auto_sync_messagesboolean

Enable or disable automatic message syncing for this channel.

sync_directionstring

Sync direction: inbound, outbound, or both.

lvng_conversation_idstring (UUID)

Map this external channel to an LVNG conversation.

Request

cURL
400">curl -X 400">PATCH https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/channels/7b8c9d0e-1f2a-3b4c-5d6e-7f8a9b0c1d2e \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY" \
  -H 400">class="text-emerald-400">"Content-Type: application/json" \
  -d '{
    400">class="text-emerald-400">"auto_sync_messages": true,
    400">class="text-emerald-400">"sync_direction": 400">class="text-emerald-400">"both",
    400">class="text-emerald-400">"lvng_conversation_id": 400">class="text-emerald-400">"e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b"
  }'

Response 200

{
  400">class="text-emerald-400">"channel": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"7b8c9d0e-1f2a-3b4c-5d6e-7f8a9b0c1d2e",
    400">class="text-emerald-400">"integration_id": 400">class="text-emerald-400">"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    400">class="text-emerald-400">"platform_channel_id": 400">class="text-emerald-400">"1234567890123456789",
    400">class="text-emerald-400">"platform_server_id": 400">class="text-emerald-400">"9876543210987654321",
    400">class="text-emerald-400">"channel_name": 400">class="text-emerald-400">"engineering",
    400">class="text-emerald-400">"channel_type": 400">class="text-emerald-400">"text",
    400">class="text-emerald-400">"channel_topic": 400">class="text-emerald-400">"Engineering team discussions",
    400">class="text-emerald-400">"auto_sync_messages": true,
    400">class="text-emerald-400">"sync_direction": 400">class="text-emerald-400">"both",
    400">class="text-emerald-400">"lvng_conversation_id": 400">class="text-emerald-400">"e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T09:35:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T10:45:00.000Z"
  }
}

Generate API Key

POST/api/v2/platform-integrations/:id/api-keyAuthenticated

Generates a new API key for an integration in the format lvng_plat_{random_hex}. The key is only returned once in this response -- it cannot be retrieved again. Any existing API key for this integration is overwritten.

Path Parameters

idstring (UUID)required

The unique identifier of the integration.

Request

cURL
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/api-key \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 201

{
  400">class="text-emerald-400">"api_key": 400">class="text-emerald-400">"lvng_plat_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4",
  400">class="text-emerald-400">"api_key_created_at": 400">class="text-emerald-400">"2026-03-19T11:00:00.000Z",
  400">class="text-emerald-400">"message": 400">class="text-emerald-400">"API key generated successfully. This key will only be shown once."
}

Revoke API Key

DELETE/api/v2/platform-integrations/:id/api-keyAuthenticated

Revokes the API key for an integration by setting api_key and api_key_created_at to null. Any inbound requests using the old key will fail immediately.

Path Parameters

idstring (UUID)required

The unique identifier of the integration.

Request

cURL
400">curl -X 400">DELETE https:400">class="text-zinc-500">//api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/api-key \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"message": 400">class="text-emerald-400">"API key revoked successfully"
}