# Platform Integrations API

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

## GET /api/v2/platform-integrations

List Integrations -- 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.

**Authentication required**

### Example Request

```bash
curl -X GET https://api.lvng.ai/api/v2/platform-integrations \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

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

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

Get Integration -- 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.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration. |

### Example Request

```bash
curl -X GET https://api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

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

## POST /api/v2/platform-integrations

Create Integration -- 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.

**Authentication required**

### Body Parameters

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| workspace_id | string (UUID) | Yes | -- | The workspace to attach this integration to. Must be owned by the authenticated customer. |
| platform | string | Yes | -- | Platform identifier (e.g., discord, slack, teams). Validated against PlatformRegistry. |
| config | object | No | -- | Platform-specific configuration object (tokens, server IDs, etc.). |
| enabled | boolean | No | true | Whether the integration is active. |

### Example Request

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

### Response (201)

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

## PATCH /api/v2/platform-integrations/:id

Update Integration -- 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.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration. |

### Body Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| config | object | No | Updated platform-specific configuration. Clears the cached instance when changed. |
| enabled | boolean | No | Enable or disable the integration. |

### Example Request

```bash
curl -X PATCH https://api.lvng.ai/api/v2/platform-integrations/c3d4e5f6-a7b8-9012-cdef-123456789012 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": false
  }'
```

### Response (200)

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

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

Delete Integration -- 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.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration to delete. |

### Example Request

```bash
curl -X DELETE https://api.lvng.ai/api/v2/platform-integrations/c3d4e5f6-a7b8-9012-cdef-123456789012 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

```json
{
  "success": true
}
```

## POST /api/v2/platform-integrations/:id/test

Test Connection -- 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.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration to test. |

### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/test \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

```json
{
  "success": true
}
```

## POST /api/v2/platform-integrations/:id/sync-channels

Sync Channels -- Fetches all channels from the external platform and upserts them into the platform_channels table. Existing channels are updated via upsert on integration_id + platform_channel_id.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration. |

### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/sync-channels \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

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

## GET /api/v2/platform-integrations/:id/channels

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

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration. |

### Example Request

```bash
curl -X GET https://api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/channels \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

```json
{
  "channels": [
    {
      "id": "7b8c9d0e-1f2a-3b4c-5d6e-7f8a9b0c1d2e",
      "integration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "platform_channel_id": "1234567890123456789",
      "platform_server_id": "9876543210987654321",
      "channel_name": "engineering",
      "channel_type": "text",
      "channel_topic": "Engineering team discussions",
      "auto_sync_messages": false,
      "sync_direction": null,
      "lvng_conversation_id": null,
      "created_at": "2026-03-19T09:35:00.000Z",
      "updated_at": "2026-03-19T09:35:00.000Z"
    }
  ]
}
```

## PATCH /api/v2/platform-integrations/channels/:channelId

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

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| channelId | string (UUID) | Yes | The LVNG platform_channels table ID (not the external channel ID). |

### Body Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| auto_sync_messages | boolean | No | Enable or disable automatic message syncing for this channel. |
| sync_direction | string | No | Sync direction: inbound, outbound, or both. |
| lvng_conversation_id | string (UUID) | No | Map this external channel to an LVNG conversation. |

### Example Request

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

### Response (200)

```json
{
  "channel": {
    "id": "7b8c9d0e-1f2a-3b4c-5d6e-7f8a9b0c1d2e",
    "integration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "platform_channel_id": "1234567890123456789",
    "channel_name": "engineering",
    "auto_sync_messages": true,
    "sync_direction": "both",
    "lvng_conversation_id": "e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
    "updated_at": "2026-03-19T10:45:00.000Z"
  }
}
```

## POST /api/v2/platform-integrations/:id/api-key

Generate API Key -- 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.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration. |

### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/api-key \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (201)

```json
{
  "api_key": "lvng_plat_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4",
  "api_key_created_at": "2026-03-19T11:00:00.000Z",
  "message": "API key generated successfully. This key will only be shown once."
}
```

## DELETE /api/v2/platform-integrations/:id/api-key

Revoke API Key -- 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.

**Authentication required**

### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string (UUID) | Yes | The unique identifier of the integration. |

### Example Request

```bash
curl -X DELETE https://api.lvng.ai/api/v2/platform-integrations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/api-key \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response (200)

```json
{
  "success": true,
  "message": "API key revoked successfully"
}
```
