# WinkSocial API Documentation

WinkSocial is a dating and social platform running on a self-hosted C++ (Oat++) backend on Contabo.

## Base URLs

| Service | URL |
|---------|-----|
| Main API | `https://api.joinwink.app` |
| AI Agents | `https://agents.joinwink.app` |
| Auth (Keycloak) | `https://auth.joinwink.app` |
| Web App | `https://joinwink.app` |
| Admin Panel | `https://admin.joinwink.app` |
| Blog | `https://blog.joinwink.app` |

> `agents.joinwink.app` and `api.joinwink.app` are served by the same C++ backend.
> `agents.joinwink.app` is restricted to the backend AI controller paths under `/api/v1/ai-agents/*`.

## Authentication

All protected endpoints require a Bearer token obtained via Keycloak OIDC (Authorization Code + PKCE):

```bash
Authorization: Bearer <access_token>
```

The web app uses `wink_session` / `wink_refresh` httpOnly cookies managed by the Next.js auth routes (`/api/auth/login`, `/api/auth/callback`, `/api/auth/logout`).

---

## AI Agents API

WinkSocial currently deploys AI across three runtime surfaces:

- The C++ backend exposes the authenticated product AI endpoints at `/api/v1/ai-agents/*`.
- The web app proxies `/api/agent` to the separate `apps/platform-agent` FastAPI/LangGraph service.
- Voice inference is handled by the dedicated Node voice-agent services under `deploy/voice/voice-agent` and `deploy/thundercompute/voice-agent`, with the C++ backend proxying `/api/v1/voice/*`.

The backend AI endpoints below are accessible at both `agents.joinwink.app` and `api.joinwink.app`.

### Base path: `/api/v1/ai-agents`

| Endpoint | Model | Use case |
|----------|-------|----------|
| `POST /api/v1/ai-agents/chat/response` | `llama3.1:8b` | Real-time dating assistant chat |
| `POST /api/v1/ai-agents/bio/rewrite` | `qwen2.5:7b` | Profile bio optimisation |
| `POST /api/v1/ai-agents/match/predict` | `mistral:7b` | Compatibility analysis |
| `POST /api/v1/ai-agents/support/chat` | Self-hosted support model mesh | KB-grounded support chat with citations |
| `GET /api/v1/ai-agents/context/stats` | — | Admin: user context cache stats |
| `POST /api/v1/ai-agents/context/invalidate/{userId}` | — | Admin: clear user context cache |

#### Chat Response
```
POST /api/v1/ai-agents/chat/response
```
Generates an AI suggestion for the next chat message. Uses conversation history (ConversationContextService) and user profile context (UserContextService).

**Request:**
```json
{ "message": "string", "context": "optional string", "language": "en", "userId": "string" }
```

#### Bio Rewrite
```
POST /api/v1/ai-agents/bio/rewrite
```
Rewrites a user's profile bio. Grounded in the user's own profile context (interests, age, location).

**Request:**
```json
{ "currentBio": "string", "style": "engaging" }
```

#### Match Predict
```
POST /api/v1/ai-agents/match/predict
```
Scores compatibility between two user profiles (0–1). Uses the self-hosted match-analysis model for multi-factor reasoning.

**Request:**
```json
{ "user1Profile": "string", "user2Profile": "string" }
```

#### Support Chat
```
POST /api/v1/ai-agents/support/chat
```
KB-grounded support agent. Knowledge base is editable at `admin.joinwink.app/help-articles` and stored in MinIO (`winksocial-kb/platform-kb.md`). Cache TTL: 10 minutes.
The agent now grounds answers from the platform KB, uploaded KB assets, and authenticated user context. Responses include source citations where grounding material is available and fall back to a deterministic support response when the LLM path is unavailable.

**Request:**
```json
{ "message": "string", "language": "en", "topic": "billing|account|matching|safety|technical" }
```

**Response:**
```json
{
  "success": true,
  "response": "string",
  "category": "billing",
  "escalate": false,
  "ticketHint": "",
  "citations": [
    { "title": "Platform KB", "source": "platform-kb.md" }
  ]
}
```
When `escalate: true`, route the user to human support and pre-fill a ticket with `ticketHint`.

### Platform Agent
```
POST /api/agent
```
The web app calls this Next.js proxy, which forwards the user's `wink_session` access token to the separately deployed `platform-agent` service (`PLATFORM_AGENT_BASE_URL`, default `http://platform-agent:8090`). The platform agent is not hosted behind `agents.joinwink.app`.

### Voice Agent
```
POST /api/v1/voice/agent
POST /api/v1/voice/stt
POST /api/v1/voice/tts
```
Voice routes terminate in the C++ backend and proxy to the dedicated voice-agent runtime.

---

## Knowledge Base API (admin)

Manages the support agent knowledge base stored in MinIO. Edit via `admin.joinwink.app/help-articles`.

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/kb` | Fetch current KB Markdown content |
| `PUT` | `/api/v1/kb` | Replace full KB document (admin only) |
| `GET` | `/api/v1/kb/assets` | List uploaded KB assets and grounding manifests |
| `POST` | `/api/v1/kb/assets` | Upload a KB file or URL-derived asset with optional grounding text |
| `DELETE` | `/api/v1/kb/assets/{assetId}` | Remove a KB asset and its grounding manifest |

Support agent picks up changes within 10 minutes (cache TTL).

---

## Admin Operations API

These endpoints require an admin bearer token. The admin app should call same-origin Next.js proxies, which forward the token to the C++ backend.

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/admin/messaging/observability` | Messaging channel health, delivery rates, route scores |
| `GET` | `/api/v1/admin/support/stats` | Support queue and ticket aggregates |
| `GET` | `/api/admin/finance/metrics` | Platform finance and revenue metrics |
| `GET` | `/api/v1/admin/coins/mint/state` | Coin minting state |
| `GET` | `/api/v1/admin/vouchers` | Voucher inventory and status |
| `GET` | `/api/v1/admin/observability/vms` | Latest VM capacity telemetry |
| `POST` | `/api/v1/admin/observability/vms/{vmId}/heartbeat` | VM agent heartbeat with `X-Observability-Token` |
| `GET` | `/api/v1/admin/observability/bugsink` | Bugsink project rollups and unresolved issue samples |
| `GET` | `/api/v1/admin/config/maps/regions` | Maps country catalog and enabled-country config |
| `PUT` | `/api/v1/admin/config/maps/regions` | Update maps country rollout config |

---

## Messaging Workflows API

Backs `admin.joinwink.app/campaigns/flow-builder` and syncs React Flow campaigns into self-hosted n8n.

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/messaging/workflows` | List saved workflows |
| `POST` | `/api/v1/messaging/workflows` | Save a workflow draft and compile n8n preview |
| `GET` | `/api/v1/messaging/workflows/{workflowId}` | Fetch workflow nodes, edges, and compiled n8n payload |
| `POST` | `/api/v1/messaging/workflows/{workflowId}/sync` | Upsert workflow into n8n |
| `POST` | `/api/v1/messaging/workflows/{workflowId}/run` | Trigger a workflow run in n8n |
| `GET` | `/api/v1/messaging/workflows/{workflowId}/runs` | List persisted run history |
| `POST` | `/api/v1/messaging/workflows/status` | n8n callback for run state updates |

---

## Partner API

Partner dashboard surfaces, including `partner.joinwink.app/webhooks`, should be documented because partners need a stable contract.

| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/api/v1/partners/apply` | Submit a partner application |
| `GET` | `/api/v1/partner/profile` | Fetch authenticated partner profile and webhook config |
| `PUT` | `/api/v1/partner/profile` | Update partner profile and webhook config |

---

## Matching API

### Base path: `/api/v1`

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/profiles/discover` | Discovery feed (swipe cards) |
| `POST` | `/api/matching/swipe` | Record swipe (`action: like\|pass\|wink`) |
| `GET` | `/api/v1/matches` | List current matches |
| `GET` | `/api/v1/matches/events` | SSE stream for match events |

---

## Winks API

| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/api/v1/winks` | Send a wink (rate-limited: 10/day free) |
| `GET` | `/api/v1/winks/received` | Pending winks for badge count |
| `POST` | `/api/v1/winks/{winkId}/accept` | Accept wink → creates match |
| `POST` | `/api/v1/winks/{winkId}/decline` | Decline wink |

---

## Profile API

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/profile` | Current user's profile |
| `GET` | `/api/v1/profile/{userId}` | Another user's profile |
| `PUT` | `/api/v1/profile` | Update profile |

---

## Translations API

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/translations/{namespace}` | Fetch translation bundle (CDN-cached 1h) |
| `POST` | `/api/v1/translations/{namespace}/seed` | Admin: batch translate via self-hosted open-model routing |
| `POST` | `/api/v1/translations/message` | Translate a chat message (cached by contextId) |
| `POST` | `/api/v1/translations/profile` | Translate profile bio/tagline/interests |

---

## Subscriptions API

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/subscriptions/plans` | Available plans (min 500 coins/$5) |
| `GET` | `/api/v1/subscriptions/current` | Current user's subscription |
| `POST` | `/api/v1/subscriptions` | Subscribe to a plan |

---

## Development

### Test the API
```bash
# Health check
curl https://api.joinwink.app/health

# AI chat response
curl -X POST "https://agents.joinwink.app/api/v1/ai-agents/chat/response" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"Any tips for starting a conversation?","language":"en","userId":"uid"}'

# Bio rewrite
curl -X POST "https://agents.joinwink.app/api/v1/ai-agents/bio/rewrite" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"currentBio":"I like travel","style":"engaging"}'

# Support chat (KB-grounded)
curl -X POST "https://agents.joinwink.app/api/v1/ai-agents/support/chat" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"How do I cancel my subscription?","language":"en","topic":"billing"}'

# Update knowledge base (admin)
curl -X PUT "https://api.joinwink.app/api/v1/kb" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"# WinkSocial KB\n\nYour markdown here..."}'
```

### Smoke test suite
```bash
API_BASE_URL=https://api.joinwink.app scripts/testing/test-backend-endpoints.sh
```

---

## Stack

| Layer | Technology |
|-------|-----------|
| API | C++ Oat++ 1.3.0 (CAF actors) |
| Auth | Keycloak 26.1 (OIDC, PKCE) |
| DB | SurrealDB v2, PostgreSQL 16 (PostGIS) |
| Cache | Redis 7 |
| Object storage | MinIO |
| Messaging | NATS 2 JetStream |
| AI | Self-hosted open-model mesh via C++ AI controllers, CAF actors, platform-agent (FastAPI/LangGraph), voice-agent services, Ollama, and ThunderCompute GPU workers |
| Web | Next.js 15 |
| Mobile | React Native (Expo) |
| Reverse proxy | Caddy 2.8 (auto TLS) |
