# REST API

HTTP REST API for vCon ingestion and operations.

## Overview

The vCon MCP Server exposes a RESTful HTTP API alongside the MCP transport layer. This API provides endpoints for vCon CRUD operations, designed for programmatic integration with external systems.

### Key Features

* **HTTP/JSON** - Standard REST conventions
* **API Key Authentication** - Secure access with configurable API keys
* **CORS Support** - Configurable cross-origin resource sharing
* **Plugin Integration** - Full lifecycle hooks (beforeCreate, afterCreate, etc.)
* **Batch Operations** - Ingest up to 100 vCons in a single request
* **Discovery-Backed Reads** - Discover live attachment and analysis categories, then read by `type` or `purpose`
* **Health Checks** - Built-in health endpoint for monitoring

***

## Configuration

### REST API Variables

| Variable             | Default   | Description                      |
| -------------------- | --------- | -------------------------------- |
| `REST_API_BASE_PATH` | `/api/v1` | Base path for REST API endpoints |
| `REST_API_ENABLED`   | `true`    | Enable/disable REST API          |

### Authentication Variables

| Variable            | Default         | Description                                                                                                         |
| ------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
| `API_KEYS`          | (none)          | Comma-separated list of valid API keys                                                                              |
| `API_KEY_HEADER`    | `authorization` | Header for API key; default expects `Authorization: Bearer <token>`. Set to `x-api-key` to use that header instead. |
| `API_AUTH_REQUIRED` | `true`          | Set to `false` to disable authentication                                                                            |

### HTTP Transport Variables

The REST API requires HTTP transport mode to be enabled:

| Variable        | Default     | Description                         |
| --------------- | ----------- | ----------------------------------- |
| `MCP_TRANSPORT` | `stdio`     | Set to `http` to enable HTTP server |
| `MCP_HTTP_HOST` | `127.0.0.1` | HTTP host to bind                   |
| `MCP_HTTP_PORT` | `3000`      | HTTP port to listen on              |
| `CORS_ORIGIN`   | `*`         | CORS allowed origins                |

### Example Configuration

```bash
# Enable HTTP transport
MCP_TRANSPORT=http
MCP_HTTP_HOST=0.0.0.0
MCP_HTTP_PORT=3000

# Configure REST API (optional - defaults work for most cases)
REST_API_BASE_PATH=/api/v1
REST_API_ENABLED=true

# Configure authentication
API_KEYS=key1-abc123,key2-def456
API_AUTH_REQUIRED=true
```

***

## Authentication

All REST API endpoints (except `/health`) require API key authentication.

### Request Headers

By default, send your API key in the `Authorization` header:

```http
Authorization: Bearer your-api-key-here
```

You can use a different header by setting `API_KEY_HEADER` (e.g. `x-api-key`).

### Authentication Responses

**401 Unauthorized - Missing API Key:**

```json
{
  "error": "Unauthorized",
  "message": "Missing Authorization: Bearer <token> header"
}
```

**401 Unauthorized - Invalid API Key:**

```json
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

**503 Service Unavailable - Auth Not Configured:**

```json
{
  "error": "Service Unavailable",
  "message": "API authentication is required but not configured. Please contact the administrator.",
  "hint": "Set API_KEYS env var, or set API_AUTH_REQUIRED=false"
}
```

> **Note:** The `hint` field is only included in non-production environments.

***

## Endpoints

### Discovery-First Reads

When a classification is stored in attachments or analysis, prefer this sequence:

1. Discover available values first. For attachments, prefer `purpose`; use attachment `type` only for legacy compatibility. For analysis, use `type`.
2. Read the matching filtered vCon subresource.
3. Use tags when the classification genuinely lives in the tags attachment.

Examples:

```bash
# Discover live attachment purposes
curl "http://localhost:3000/api/v1/discovery/attachments/purposes" \
  -H "Authorization: Bearer your-api-key"

# Read one vCon's dealer info attachments
curl "http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000/attachments?purpose=dealer_info" \
  -H "Authorization: Bearer your-api-key"

# Read one vCon's summary analysis through the generic type filter
curl "http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000/analysis?type=summary" \
  -H "Authorization: Bearer your-api-key"
```

***

### Health Check

Check API and database health status.

**Endpoint:** `GET /api/v1/health`

**Authentication:** Not required

**Response (200 OK):**

```json
{
  "status": "healthy",
  "timestamp": "2025-01-02T10:30:00.000Z",
  "database": "connected"
}
```

**Response (503 Service Unavailable):**

```json
{
  "status": "unhealthy",
  "timestamp": "2025-01-02T10:30:00.000Z",
  "database": "error",
  "error": "Connection refused"
}
```

**Example:**

```bash
curl http://localhost:3000/api/v1/health
```

***

### Create vCon

Create/ingest a single vCon.

**Endpoint:** `POST /api/v1/vcons`

**Authentication:** Required

**Request Headers:**

```http
Content-Type: application/json
Authorization: Bearer your-api-key
```

**Request Body:**

The request body should be the vCon object directly:

```json
{
  "vcon": "0.4.0",
  "uuid": "optional-custom-uuid",
  "subject": "Customer Support Call",
  "parties": [
    {
      "name": "Agent Smith",
      "mailto": "smith@company.com",
      "role": "agent"
    },
    {
      "name": "John Doe",
      "tel": "+1-555-1234",
      "role": "customer"
    }
  ],
  "dialog": [
    {
      "type": "text",
      "start": "2025-01-02T10:00:00Z",
      "parties": [0, 1],
      "originator": 1,
      "body": "Hello, I need help with my account."
    }
  ],
  "analysis": [],
  "attachments": []
}
```

**Response (201 Created):**

```json
{
  "success": true,
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "id": "42",
  "message": "vCon created successfully",
  "duration_ms": 45
}
```

**Response (400 Bad Request - Validation Error):**

```json
{
  "error": "Validation Error",
  "message": "Missing required field: parties; Invalid party: must have at least one identifier"
}
```

**Example:**

```bash
curl -X POST http://localhost:3000/api/v1/vcons \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "vcon": "0.4.0",
    "subject": "Sales Call",
    "parties": [
      {"name": "Sales Rep", "mailto": "rep@company.com"},
      {"name": "Customer", "tel": "+1-555-9876"}
    ]
  }'
```

***

### Batch Create vCons

Ingest multiple vCons in a single request (up to 100).

**Endpoint:** `POST /api/v1/vcons/batch`

**Authentication:** Required

**Request Headers:**

```http
Content-Type: application/json
Authorization: Bearer your-api-key
```

**Request Body:**

Array of vCon objects:

```json
[
  {
    "vcon": "0.4.0",
    "subject": "Call 1",
    "parties": [{"name": "Agent A", "mailto": "a@example.com"}]
  },
  {
    "vcon": "0.4.0",
    "subject": "Call 2",
    "parties": [{"name": "Agent B", "mailto": "b@example.com"}]
  }
]
```

**Response (201 Created - All Successful):**

```json
{
  "success": true,
  "total": 2,
  "created": 2,
  "failed": 0,
  "results": [
    {
      "uuid": "uuid-1",
      "success": true,
      "id": "42"
    },
    {
      "uuid": "uuid-2",
      "success": true,
      "id": "43"
    }
  ],
  "duration_ms": 120
}
```

**Response (207 Multi-Status - Partial Success):**

```json
{
  "success": false,
  "total": 3,
  "created": 2,
  "failed": 1,
  "results": [
    {
      "uuid": "uuid-1",
      "success": true,
      "id": "42"
    },
    {
      "uuid": "uuid-2",
      "success": true,
      "id": "43"
    },
    {
      "uuid": "unknown",
      "success": false,
      "error": "Validation failed: Missing required field: parties"
    }
  ],
  "duration_ms": 150
}
```

**Response (400 Bad Request):**

```json
{
  "error": "Validation Error",
  "message": "Request body must be an array of vCons"
}
```

```json
{
  "error": "Validation Error",
  "message": "Maximum 100 vCons per batch"
}
```

**Example:**

```bash
curl -X POST http://localhost:3000/api/v1/vcons/batch \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '[
    {"vcon": "0.4.0", "subject": "Call 1", "parties": [{"name": "A", "tel": "+1111"}]},
    {"vcon": "0.4.0", "subject": "Call 2", "parties": [{"name": "B", "tel": "+2222"}]}
  ]'
```

***

### Get vCon

Retrieve a vCon by UUID.

**Endpoint:** `GET /api/v1/vcons/:uuid`

**Authentication:** Required

**URL Parameters:**

| Parameter | Type   | Description          |
| --------- | ------ | -------------------- |
| `uuid`    | string | vCon UUID (required) |

**Response (200 OK):**

```json
{
  "success": true,
  "vcon": {
    "vcon": "0.4.0",
    "uuid": "123e4567-e89b-12d3-a456-426614174000",
    "created_at": "2025-01-02T10:00:00.000Z",
    "subject": "Customer Support Call",
    "parties": [...],
    "dialog": [...],
    "analysis": [...],
    "attachments": [...]
  }
}
```

**Response (404 Not Found):**

```json
{
  "error": "Not Found",
  "message": "vCon with UUID 123e4567-e89b-12d3-a456-426614174000 not found"
}
```

**Example:**

```bash
curl http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000 \
  -H "Authorization: Bearer your-api-key"
```

***

### List vCons

List recent vCons with optional limit.

**Endpoint:** `GET /api/v1/vcons`

**Authentication:** Required

**Query Parameters:**

| Parameter | Type   | Default | Description                          |
| --------- | ------ | ------- | ------------------------------------ |
| `limit`   | number | 10      | Number of vCons to return (max: 100) |

**Response (200 OK):**

```json
{
  "success": true,
  "count": 10,
  "limit": 10,
  "vcons": [
    {
      "vcon": "0.4.0",
      "uuid": "uuid-1",
      "created_at": "2025-01-02T10:00:00.000Z",
      "subject": "Call 1",
      "parties": [...]
    },
    {
      "vcon": "0.4.0",
      "uuid": "uuid-2",
      "created_at": "2025-01-02T09:00:00.000Z",
      "subject": "Call 2",
      "parties": [...]
    }
  ]
}
```

**Example:**

```bash
# Get last 10 vCons (default)
curl http://localhost:3000/api/v1/vcons \
  -H "Authorization: Bearer your-api-key"

# Get last 50 vCons
curl "http://localhost:3000/api/v1/vcons?limit=50" \
  -H "Authorization: Bearer your-api-key"
```

***

### Delete vCon

Delete a vCon by UUID.

**Endpoint:** `DELETE /api/v1/vcons/:uuid`

**Authentication:** Required

**URL Parameters:**

| Parameter | Type   | Description          |
| --------- | ------ | -------------------- |
| `uuid`    | string | vCon UUID (required) |

**Response (200 OK):**

```json
{
  "success": true,
  "message": "vCon 123e4567-e89b-12d3-a456-426614174000 deleted successfully"
}
```

**Response (404 Not Found):**

```json
{
  "error": "Not Found",
  "message": "vCon with UUID 123e4567-e89b-12d3-a456-426614174000 not found"
}
```

**Example:**

```bash
curl -X DELETE http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000 \
  -H "Authorization: Bearer your-api-key"
```

***

## Error Handling

All errors follow a consistent format:

```json
{
  "error": "Error Type",
  "message": "Human-readable error description",
  "timestamp": "2025-01-02T10:30:00.000Z"
}
```

### HTTP Status Codes

| Status | Description                               |
| ------ | ----------------------------------------- |
| `200`  | Success                                   |
| `201`  | Created (new vCon)                        |
| `207`  | Multi-Status (batch with partial success) |
| `400`  | Bad Request (validation error)            |
| `401`  | Unauthorized (authentication failed)      |
| `404`  | Not Found                                 |
| `500`  | Internal Server Error                     |
| `503`  | Service Unavailable                       |

### Error Examples

**Internal Server Error (500):**

```json
{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred",
  "timestamp": "2025-01-02T10:30:00.000Z"
}
```

> **Note:** In non-production environments, more detailed error messages are included.

***

## Plugin Integration

The REST API integrates with the vCon MCP Server's plugin system. All vCon operations trigger the appropriate lifecycle hooks:

| Operation         | Hooks Triggered               |
| ----------------- | ----------------------------- |
| Create vCon       | `beforeCreate`, `afterCreate` |
| Get vCon          | `beforeRead`, `afterRead`     |
| Update vCon       | `beforeUpdate`, `afterUpdate` |
| List/Search vCons | `beforeSearch`, `afterSearch` |
| Delete vCon       | `beforeDelete`, `afterDelete` |

This ensures consistent behavior between MCP tools and REST API operations, including:

* Privacy filtering
* Access control
* Audit logging
* Data transformation

See the [Plugin Development Guide](/development/plugins.md) for more information.

***

## Request Logging

All requests are logged with the following information:

```json
{
  "level": "info",
  "msg": "REST API request",
  "method": "POST",
  "path": "/api/v1/vcons",
  "remote_address": "192.168.1.100",
  "user_agent": "curl/7.79.1"
}
```

Response logging includes duration:

```json
{
  "level": "info",
  "msg": "REST API response",
  "method": "POST",
  "path": "/api/v1/vcons",
  "status": 201,
  "duration_ms": 45
}
```

***

## CORS Configuration

The REST API supports CORS with configurable options:

**Allowed Methods:** `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`

**Allowed Headers:** `Content-Type`, `Authorization` (Bearer), `x-api-key` (if `API_KEY_HEADER=x-api-key`)

**Configure CORS Origin:**

```bash
# Allow all origins (default)
CORS_ORIGIN=*

# Allow specific origin
CORS_ORIGIN=https://myapp.com

# Allow multiple origins (comma-separated)
CORS_ORIGIN=https://app1.com,https://app2.com
```

***

## Usage Examples

### JavaScript/Node.js

```javascript
const API_URL = 'http://localhost:3000/api/v1';
const API_KEY = 'your-api-key';

// Create a vCon
async function createVCon(vcon) {
  const response = await fetch(`${API_URL}/vcons`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: JSON.stringify(vcon),
  });
  return response.json();
}

// Get a vCon
async function getVCon(uuid) {
  const response = await fetch(`${API_URL}/vcons/${uuid}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` },
  });
  return response.json();
}

// Batch create
async function batchCreate(vcons) {
  const response = await fetch(`${API_URL}/vcons/batch`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: JSON.stringify(vcons),
  });
  return response.json();
}

// Example usage
const result = await createVCon({
  vcon: '0.4.0',
  subject: 'Support Call',
  parties: [
    { name: 'Agent', mailto: 'agent@company.com' },
    { name: 'Customer', tel: '+1-555-1234' },
  ],
});

console.log('Created vCon:', result.uuid);
```

### Python

```python
import requests

API_URL = 'http://localhost:3000/api/v1'
API_KEY = 'your-api-key'

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {API_KEY}',
}

# Create a vCon
def create_vcon(vcon):
    response = requests.post(f'{API_URL}/vcons', json=vcon, headers=headers)
    return response.json()

# Get a vCon
def get_vcon(uuid):
    response = requests.get(f'{API_URL}/vcons/{uuid}', headers=headers)
    return response.json()

# Batch create
def batch_create(vcons):
    response = requests.post(f'{API_URL}/vcons/batch', json=vcons, headers=headers)
    return response.json()

# Example usage
result = create_vcon({
    'vcon': '0.4.0',
    'subject': 'Support Call',
    'parties': [
        {'name': 'Agent', 'mailto': 'agent@company.com'},
        {'name': 'Customer', 'tel': '+1-555-1234'},
    ],
})

print(f"Created vCon: {result['uuid']}")
```

### cURL Examples

```bash
# Health check
curl http://localhost:3000/api/v1/health

# Create vCon
curl -X POST http://localhost:3000/api/v1/vcons \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-key" \
  -d '{"vcon":"0.4.0","subject":"Test","parties":[{"name":"Test","tel":"+1111"}]}'

# Get vCon
curl http://localhost:3000/api/v1/vcons/UUID-HERE \
  -H "Authorization: Bearer your-key"

# List vCons
curl "http://localhost:3000/api/v1/vcons?limit=20" \
  -H "Authorization: Bearer your-key"

# Delete vCon
curl -X DELETE http://localhost:3000/api/v1/vcons/UUID-HERE \
  -H "Authorization: Bearer your-key"

# Batch create
curl -X POST http://localhost:3000/api/v1/vcons/batch \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-key" \
  -d '[{"vcon":"0.4.0","parties":[{"name":"A","tel":"+1"}]},{"vcon":"0.4.0","parties":[{"name":"B","tel":"+2"}]}]'
```

***

## Full Endpoint Reference

The REST API now has full parity with MCP tools. All endpoints use `/api/v1` as the default base path.

### vCon CRUD & Sub-resources

| Method | Path                       | Description                                                                                     |
| ------ | -------------------------- | ----------------------------------------------------------------------------------------------- |
| POST   | `/vcons`                   | Create a vCon                                                                                   |
| POST   | `/vcons/batch`             | Batch create (up to 100)                                                                        |
| GET    | `/vcons`                   | List/search vCons (filter with query params)                                                    |
| GET    | `/vcons/:uuid`             | Get vCon by UUID (`?format=full\|summary\|metadata`)                                            |
| GET    | `/vcons/:uuid/analysis`    | Read analysis, optionally filtered by `?type=`                                                  |
| GET    | `/vcons/:uuid/attachments` | Read attachments, preferably filtered by `?purpose=`; `?type=` remains for legacy compatibility |
| PATCH  | `/vcons/:uuid`             | Update vCon metadata (subject, extensions, critical)                                            |
| DELETE | `/vcons/:uuid`             | Delete a vCon                                                                                   |
| POST   | `/vcons/:uuid/dialog`      | Add dialog to a vCon                                                                            |
| POST   | `/vcons/:uuid/analysis`    | Add analysis to a vCon                                                                          |
| POST   | `/vcons/:uuid/attachments` | Add attachment to a vCon                                                                        |

### Discovery

| Method | Path                              | Description                                                                 |
| ------ | --------------------------------- | --------------------------------------------------------------------------- |
| GET    | `/discovery/attachments/purposes` | Discover live attachment purposes (`?include_counts=false`, `?min_count=2`) |
| GET    | `/discovery/attachments/types`    | Discover legacy attachment types (`?include_counts=false`, `?min_count=2`)  |
| GET    | `/discovery/analysis/types`       | Discover live analysis types (`?include_counts=false`, `?min_count=2`)      |

### Tags

| Method | Path                     | Description                                    |
| ------ | ------------------------ | ---------------------------------------------- |
| GET    | `/vcons/:uuid/tags`      | Get all tags (or single via `?key=`)           |
| PUT    | `/vcons/:uuid/tags/:key` | Set a tag (body: `{"value": "..."}`)           |
| DELETE | `/vcons/:uuid/tags/:key` | Remove a tag                                   |
| DELETE | `/vcons/:uuid/tags`      | Remove all tags                                |
| GET    | `/tags`                  | Discover unique tags across DB                 |
| GET    | `/tags/search`           | Search vCons by tags (`?tags={"key":"value"}`) |

### Search

| Method | Path                     | Description                                |
| ------ | ------------------------ | ------------------------------------------ |
| GET    | `/vcons/search/content`  | Keyword/full-text search (`?q=`)           |
| GET    | `/vcons/search/semantic` | Semantic/embedding search (`?q=`)          |
| GET    | `/vcons/search/hybrid`   | Combined keyword + semantic search (`?q=`) |

### Database & Analytics

| Method | Path                     | Description                   |
| ------ | ------------------------ | ----------------------------- |
| GET    | `/database/shape`        | Database schema shape         |
| GET    | `/database/stats`        | Performance statistics        |
| GET    | `/database/size`         | Size info and recommendations |
| GET    | `/database/health`       | Health metrics                |
| POST   | `/database/analyze`      | Analyze a SQL query plan      |
| GET    | `/analytics`             | Full analytics dashboard      |
| GET    | `/analytics/growth`      | Growth trends                 |
| GET    | `/analytics/content`     | Content analytics             |
| GET    | `/analytics/tags`        | Tag analytics                 |
| GET    | `/analytics/attachments` | Attachment analytics          |

### Infrastructure

| Method | Path              | Description                |
| ------ | ----------------- | -------------------------- |
| GET    | `/health`         | Health check (no auth)     |
| GET    | `/version`        | Version info (no auth)     |
| GET    | `/schema`         | vCon JSON Schema (no auth) |
| GET    | `/examples/:type` | Example vCons (no auth)    |

***

## Comparison: REST API vs MCP Tools

| Feature    | REST API                                  | MCP Tools               |
| ---------- | ----------------------------------------- | ----------------------- |
| Protocol   | HTTP/JSON                                 | MCP (stdio/HTTP)        |
| Auth       | API Key (Bearer)                          | MCP client auth         |
| Best for   | External integrations, scripts            | AI assistants           |
| Operations | Full CRUD + sub-resources                 | Full toolkit (35 tools) |
| Search     | 4 modes (list, keyword, semantic, hybrid) | 4 search modes          |
| Tags       | Full tag management                       | Full tag management     |
| Analytics  | Full analytics suite                      | Full analytics suite    |
| Batch      | Yes (100 max)                             | No                      |
| Streaming  | No                                        | Yes (SSE)               |

Both interfaces share the same `VConService` business logic layer, plugin hooks, and database queries. Choose based on your integration pattern.

***

## Next Steps

* See [MCP Tools](/api-reference/tools.md) for the full MCP toolkit
* See [Resources](/api-reference/resources.md) for URI-based access
* See [Docker Deployment](/deployment/docker.md) for production setup
* See [Plugin Development](/development/plugins.md) for extending the API


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mcp.conserver.io/api-reference/rest-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
