# REST API & Web UI

Learn to use PyCharter's REST API and interactive web interface.

## What You'll Learn

- [x] Start the API server
- [x] Use API endpoints for validation, contracts, and quality
- [x] Launch the web UI
- [x] Navigate the UI features
- [x] Integrate API in your applications

## Prerequisites

```bash
pip install pycharter[api,ui]
```

## Part 1: Starting the API Server

### Basic Start

```bash
# Start with default settings (localhost:8000)
pycharter api
```

### Custom Configuration

```bash
# Custom host and port
pycharter api --host 0.0.0.0 --port 8080

# With specific database
export DATABASE_URL="postgresql://user:pass@localhost/pycharter"
pycharter api

# With reload for development
pycharter api --reload
```

### Using Uvicorn Directly

```bash
uvicorn pycharter.api.main:app --host 0.0.0.0 --port 8000 --reload
```

### API Documentation

Once running, access:

- **Swagger UI**: http://localhost:8000/docs
- **ReDoc**: http://localhost:8000/redoc
- **OpenAPI JSON**: http://localhost:8000/openapi.json

## Part 2: Core API Endpoints

### Health Check

```bash
curl http://localhost:8000/health
```

```json
{
  "status": "healthy",
  "version": "0.0.25"
}
```

### Schema Endpoints

#### Store a Schema

```bash
curl -X POST http://localhost:8000/api/v1/schemas \
  -H "Content-Type: application/json" \
  -d '{
    "name": "user",
    "version": "1.0.0",
    "schema": {
      "type": "object",
      "properties": {
        "name": {"type": "string"},
        "email": {"type": "string", "format": "email"}
      },
      "required": ["name", "email"]
    }
  }'
```

#### Get a Schema

```bash
curl http://localhost:8000/api/v1/schemas/user
```

#### List Schemas

```bash
curl http://localhost:8000/api/v1/schemas
```

### Validation Endpoints

#### Validate Single Record

```bash
curl -X POST http://localhost:8000/api/v1/validation/validate \
  -H "Content-Type: application/json" \
  -d '{
    "schema_id": "user",
    "data": {
      "name": "Alice",
      "email": "alice@example.com"
    }
  }'
```

Response:

```json
{
  "is_valid": true,
  "data": {
    "name": "Alice",
    "email": "alice@example.com"
  },
  "errors": []
}
```

#### Batch Validation

```bash
curl -X POST http://localhost:8000/api/v1/validation/validate-batch \
  -H "Content-Type: application/json" \
  -d '{
    "schema_id": "user",
    "data": [
      {"name": "Alice", "email": "alice@example.com"},
      {"name": "", "email": "invalid"},
      {"name": "Charlie", "email": "charlie@example.com"}
    ]
  }'
```

Response:

```json
{
  "results": [
    {"is_valid": true, "data": {...}, "errors": []},
    {"is_valid": false, "data": null, "errors": [...]},
    {"is_valid": true, "data": {...}, "errors": []}
  ],
  "summary": {
    "total": 3,
    "valid": 2,
    "invalid": 1
  }
}
```

### Contract Endpoints

#### Parse Contract

```bash
curl -X POST http://localhost:8000/api/v1/contracts/parse \
  -H "Content-Type: application/json" \
  -d '{
    "contract": {
      "schema": {
        "type": "object",
        "version": "1.0.0",
        "properties": {"name": {"type": "string"}}
      },
      "metadata": {"title": "User Contract"}
    }
  }'
```

#### Build Contract from Store

```bash
curl -X POST http://localhost:8000/api/v1/contracts/{schema_id}/build
```

### Quality Endpoints

#### Run Quality Check

```bash
curl -X POST http://localhost:8000/api/v1/quality/check \
  -H "Content-Type: application/json" \
  -d '{
    "schema_id": "user",
    "data": [
      {"name": "Alice", "email": "alice@example.com"},
      {"name": "", "email": "invalid"}
    ],
    "options": {
      "calculate_metrics": true,
      "record_violations": true,
      "thresholds": {
        "min_overall_score": 90.0
      }
    }
  }'
```

#### Get Quality Metrics

```bash
curl http://localhost:8000/api/v1/quality/metrics?schema_id=user&limit=10
```

### ETL Endpoints

#### Run Pipeline

```bash
curl -X POST http://localhost:8000/api/v1/etl/run \
  -H "Content-Type: application/json" \
  -d '{
    "extract_yaml": "type: http\nurl: https://api.example.com/users",
    "load_yaml": "type: file\nfile_path: /tmp/output.json\nformat: json",
    "variables": {"API_KEY": "secret"}
  }'
```

## Part 3: Using the Web UI

### Starting the UI

```bash
# Production mode (pre-built static files)
pycharter ui serve

# Development mode (with hot reload)
pycharter ui dev
```

Access at http://localhost:3000

### UI Features

#### Dashboard

The main dashboard shows:

- Active schemas count
- Recent validations
- Quality score trends
- System health

#### Schema Browser

Navigate to **Schemas** to:

- View all stored schemas
- Search and filter schemas
- View schema details and versions
- Edit schema metadata

#### Contract Management

Navigate to **Contracts** to:

- Upload contract files (YAML/JSON)
- Parse and validate contracts
- View contract components
- Build consolidated contracts

#### Validation Workspace

Navigate to **Validation** to:

- Select a schema
- Paste or upload data
- Run validation
- View detailed errors
- Export results

#### Quality Dashboard

Navigate to **Quality** to:

- View quality metrics over time
- Set and monitor thresholds
- Browse violations
- Generate reports

#### ETL Monitor

Navigate to **ETL** to:

- View pipeline runs
- Monitor execution progress
- Check pipeline results
- View error logs

## Part 4: API Client Integration

### Python Client

```python
import httpx

class PyCharterClient:
    def __init__(self, base_url="http://localhost:8000"):
        self.base_url = base_url
        self.client = httpx.Client(base_url=base_url)
    
    def validate(self, schema_id: str, data: dict) -> dict:
        response = self.client.post(
            "/api/v1/validation/validate",
            json={"schema_id": schema_id, "data": data}
        )
        response.raise_for_status()
        return response.json()
    
    def validate_batch(self, schema_id: str, data: list) -> dict:
        response = self.client.post(
            "/api/v1/validation/validate-batch",
            json={"schema_id": schema_id, "data": data}
        )
        response.raise_for_status()
        return response.json()
    
    def get_schema(self, schema_id: str) -> dict:
        response = self.client.get(f"/api/v1/schemas/{schema_id}")
        response.raise_for_status()
        return response.json()
    
    def quality_check(self, schema_id: str, data: list, thresholds: dict = None) -> dict:
        response = self.client.post(
            "/api/v1/quality/check",
            json={
                "schema_id": schema_id,
                "data": data,
                "options": {
                    "calculate_metrics": True,
                    "thresholds": thresholds or {}
                }
            }
        )
        response.raise_for_status()
        return response.json()

# Usage
client = PyCharterClient()
result = client.validate("user", {"name": "Alice", "email": "alice@example.com"})
print(f"Valid: {result['is_valid']}")
```

### Async Python Client

```python
import httpx

class AsyncPyCharterClient:
    def __init__(self, base_url="http://localhost:8000"):
        self.base_url = base_url
    
    async def validate(self, schema_id: str, data: dict) -> dict:
        async with httpx.AsyncClient(base_url=self.base_url) as client:
            response = await client.post(
                "/api/v1/validation/validate",
                json={"schema_id": schema_id, "data": data}
            )
            response.raise_for_status()
            return response.json()

# Usage
import asyncio

async def main():
    client = AsyncPyCharterClient()
    result = await client.validate("user", {"name": "Alice", "email": "alice@example.com"})
    print(f"Valid: {result['is_valid']}")

asyncio.run(main())
```

### JavaScript/TypeScript Client

```typescript
class PyCharterClient {
  constructor(private baseUrl: string = 'http://localhost:8000') {}

  async validate(schemaId: string, data: Record<string, any>) {
    const response = await fetch(`${this.baseUrl}/api/v1/validation/validate`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ schema_id: schemaId, data })
    });
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return response.json();
  }

  async validateBatch(schemaId: string, data: Record<string, any>[]) {
    const response = await fetch(`${this.baseUrl}/api/v1/validation/validate-batch`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ schema_id: schemaId, data })
    });
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return response.json();
  }
}

// Usage
const client = new PyCharterClient();
const result = await client.validate('user', { name: 'Alice', email: 'alice@example.com' });
console.log(`Valid: ${result.is_valid}`);
```

## Part 5: Authentication & Security

### API Key Authentication

```python
# Configure API key in environment
export PYCHARTER_API_KEY="your-secret-key"

# Start server with auth enabled
pycharter api --auth
```

Using API key:

```bash
curl -H "X-API-Key: your-secret-key" \
  http://localhost:8000/api/v1/schemas
```

### CORS Configuration

```python
# In your custom FastAPI app
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
```

## Part 6: Production Deployment

### Docker

```dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY . .
RUN pip install pycharter[api]

EXPOSE 8000

CMD ["pycharter", "api", "--host", "0.0.0.0"]
```

```bash
docker build -t pycharter-api .
docker run -p 8000:8000 pycharter-api
```

### Docker Compose

```yaml
version: '3.8'

services:
  api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db/pycharter
    depends_on:
      - db
  
  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=pycharter
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
```

### Kubernetes

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pycharter-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pycharter-api
  template:
    metadata:
      labels:
        app: pycharter-api
    spec:
      containers:
      - name: api
        image: pycharter-api:latest
        ports:
        - containerPort: 8000
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: pycharter-secrets
              key: database-url
---
apiVersion: v1
kind: Service
metadata:
  name: pycharter-api
spec:
  selector:
    app: pycharter-api
  ports:
  - port: 80
    targetPort: 8000
```

## Exercises

1. **API Basics**: Start the API server and use curl to store a schema and validate data.

2. **Client Library**: Create a Python client class that wraps the validation endpoints.

3. **UI Exploration**: Launch the UI and explore all features (schemas, validation, quality).

4. **Integration**: Build a FastAPI app that uses PyCharter API for input validation.

5. **Deployment**: Create a Docker setup for PyCharter API with PostgreSQL.

## Next Steps

- [Production Deployment Guide](../guides/production.md) - Full deployment instructions
- [API Reference](../api/index.md) - Complete API documentation
- [Custom Validators Guide](../guides/custom-validators.md) - Extend validation
