# API Usage Guide Practical examples for using the Geutebruck Cross-Switching API. --- ## Getting Started ### 1. Login First, authenticate to get your access token: **Request:** ```bash curl -X POST http://localhost:8000/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "username": "admin", "password": "admin123" }' ``` **Response:** ```json { "access_token": "eyJhbGciOiJIUzI1NiIs...", "refresh_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "bearer", "expires_in": 3600 } ``` **Save the access token** for subsequent requests. --- ## Common Operations ### Discover Available Cameras ```bash curl -X GET http://localhost:8000/api/v1/cameras \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` **Response:** ```json { "cameras": [ { "id": 1, "name": "Entrance Camera", "status": "online", "has_ptz": true }, { "id": 2, "name": "Parking Lot Camera", "status": "online", "has_ptz": false } ], "total": 2 } ``` ### Discover Available Monitors ```bash curl -X GET http://localhost:8000/api/v1/monitors \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` **Response:** ```json { "monitors": [ { "id": 1, "name": "Control Room Monitor 1", "status": "idle", "current_camera_id": null }, { "id": 2, "name": "Control Room Monitor 2", "status": "active", "current_camera_id": 5 } ], "total": 2 } ``` ### Find Available (Idle) Monitors ```bash curl -X GET http://localhost:8000/api/v1/monitors/filter/available \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` Returns only monitors with no camera currently assigned. --- ## Cross-Switching Operations ### Route Camera to Monitor **⚠️ Requires Operator role or higher** ```bash curl -X POST http://localhost:8000/api/v1/crossswitch \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "camera_id": 1, "monitor_id": 1, "mode": 0 }' ``` **Response:** ```json { "success": true, "message": "Successfully switched camera 1 to monitor 1", "route": { "id": "uuid", "camera_id": 1, "monitor_id": 1, "executed_at": "2025-12-09T12:00:00Z", "executed_by_username": "operator" } } ``` ### Clear Monitor **⚠️ Requires Operator role or higher** ```bash curl -X POST http://localhost:8000/api/v1/crossswitch/clear \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "monitor_id": 1 }' ``` ### Get Current Routing State ```bash curl -X GET http://localhost:8000/api/v1/crossswitch/routing \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` **Response:** ```json { "routes": [ { "camera_id": 1, "monitor_id": 1, "executed_at": "2025-12-09T12:00:00Z", "is_active": true } ], "total": 1 } ``` ### Get Routing History ```bash curl -X GET "http://localhost:8000/api/v1/crossswitch/history?limit=10&offset=0" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` **Filter by camera:** ```bash curl -X GET "http://localhost:8000/api/v1/crossswitch/history?camera_id=1" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` **Filter by monitor:** ```bash curl -X GET "http://localhost:8000/api/v1/crossswitch/history?monitor_id=1" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` --- ## Use Case Examples ### Use Case 1: Quick Camera Check **Scenario**: Operator wants to quickly view entrance camera on their monitor. **Steps:** 1. Find available monitor 2. Route entrance camera to that monitor ```bash # Step 1: Find available monitors curl -X GET http://localhost:8000/api/v1/monitors/filter/available \ -H "Authorization: Bearer $TOKEN" # Step 2: Route camera 1 to monitor 1 curl -X POST http://localhost:8000/api/v1/crossswitch \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"camera_id": 1, "monitor_id": 1}' ``` ### Use Case 2: Monitor Rotation **Scenario**: Automatically rotate through cameras on a monitor. **Script (PowerShell):** ```powershell $token = "YOUR_ACCESS_TOKEN" $monitor_id = 1 $cameras = @(1, 2, 3, 4) # Camera IDs to rotate foreach ($camera_id in $cameras) { # Switch camera Invoke-RestMethod -Uri "http://localhost:8000/api/v1/crossswitch" ` -Method POST ` -Headers @{ "Authorization" = "Bearer $token" } ` -ContentType "application/json" ` -Body (@{ camera_id = $camera_id; monitor_id = $monitor_id } | ConvertTo-Json) # Wait 10 seconds Start-Sleep -Seconds 10 } ``` ### Use Case 3: Incident Response **Scenario**: Security incident detected, switch multiple cameras to control room monitors. ```bash # Cameras 1-4 to monitors 1-4 for i in {1..4}; do curl -X POST http://localhost:8000/api/v1/crossswitch \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"camera_id\": $i, \"monitor_id\": $i}" done ``` ### Use Case 4: Audit Trail Review **Scenario**: Review who accessed which cameras today. ```bash # Get routing history for today curl -X GET "http://localhost:8000/api/v1/crossswitch/history?limit=100" \ -H "Authorization: Bearer $TOKEN" \ | jq '.history[] | select(.executed_at | startswith("2025-12-09"))' ``` --- ## Python Client Example ```python import requests class GeutebruckAPI: def __init__(self, base_url="http://localhost:8000", username="admin", password="admin123"): self.base_url = base_url self.token = None self.login(username, password) def login(self, username, password): """Authenticate and get token""" response = requests.post( f"{self.base_url}/api/v1/auth/login", json={"username": username, "password": password} ) response.raise_for_status() self.token = response.json()["access_token"] def _headers(self): return {"Authorization": f"Bearer {self.token}"} def list_cameras(self): """Get all cameras""" response = requests.get( f"{self.base_url}/api/v1/cameras", headers=self._headers() ) return response.json() def list_monitors(self): """Get all monitors""" response = requests.get( f"{self.base_url}/api/v1/monitors", headers=self._headers() ) return response.json() def crossswitch(self, camera_id, monitor_id, mode=0): """Execute cross-switch""" response = requests.post( f"{self.base_url}/api/v1/crossswitch", headers=self._headers(), json={ "camera_id": camera_id, "monitor_id": monitor_id, "mode": mode } ) return response.json() def clear_monitor(self, monitor_id): """Clear monitor""" response = requests.post( f"{self.base_url}/api/v1/crossswitch/clear", headers=self._headers(), json={"monitor_id": monitor_id} ) return response.json() def get_routing_state(self): """Get current routing state""" response = requests.get( f"{self.base_url}/api/v1/crossswitch/routing", headers=self._headers() ) return response.json() # Usage Example api = GeutebruckAPI() # List cameras cameras = api.list_cameras() print(f"Found {cameras['total']} cameras") # Route camera 1 to monitor 1 result = api.crossswitch(camera_id=1, monitor_id=1) print(f"Cross-switch: {result['message']}") # Get routing state routing = api.get_routing_state() print(f"Active routes: {routing['total']}") ``` --- ## C# Client Example ```csharp using System; using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; public class GeutebruckApiClient { private readonly HttpClient _client; private string _accessToken; public GeutebruckApiClient(string baseUrl = "http://localhost:8000") { _client = new HttpClient { BaseAddress = new Uri(baseUrl) }; } public async Task LoginAsync(string username, string password) { var response = await _client.PostAsJsonAsync("/api/v1/auth/login", new { username, password }); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync(); _accessToken = result.AccessToken; _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _accessToken); } public async Task ListCamerasAsync() { var response = await _client.GetAsync("/api/v1/cameras"); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync(); } public async Task ExecuteCrossSwitchAsync(int cameraId, int monitorId, int mode = 0) { var response = await _client.PostAsJsonAsync("/api/v1/crossswitch", new { camera_id = cameraId, monitor_id = monitorId, mode }); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync(); } } // Usage var api = new GeutebruckApiClient(); await api.LoginAsync("admin", "admin123"); var cameras = await api.ListCamerasAsync(); Console.WriteLine($"Found {cameras.Total} cameras"); var result = await api.ExecuteCrossSwitchAsync(cameraId: 1, monitorId: 1); Console.WriteLine($"Cross-switch: {result.Message}"); ``` --- ## Testing with Postman 1. **Import Collection**: Import the OpenAPI spec from http://localhost:8000/openapi.json 2. **Set Environment Variable**: Create `access_token` variable 3. **Login**: Run POST /api/v1/auth/login, save token to environment 4. **Test Endpoints**: All subsequent requests will use the token automatically --- ## Troubleshooting ### 401 Unauthorized **Problem**: Token expired or invalid. **Solution**: Re-authenticate: ```bash # Get new token curl -X POST http://localhost:8000/api/v1/auth/login \ -d '{"username":"admin","password":"admin123"}' ``` ### 403 Forbidden **Problem**: User role insufficient (e.g., Viewer trying to execute cross-switch). **Solution**: Use account with Operator or Administrator role. ### 404 Not Found **Problem**: Camera or monitor ID doesn't exist. **Solution**: List cameras/monitors to find valid IDs. ### 500 Internal Server Error **Problem**: SDK Bridge communication failure or database error. **Solution**: 1. Check health endpoint: `/health` 2. Verify SDK Bridge is running 3. Check API logs --- ## Best Practices 1. **Always check health before operations** 2. **Cache camera/monitor lists** (refreshed every 60s) 3. **Handle 401 errors** by re-authenticating 4. **Use refresh tokens** to extend sessions 5. **Log all cross-switch operations** to external system 6. **Implement retry logic** for transient failures 7. **Monitor audit logs** for security events --- ## Next Steps - Explore interactive documentation: http://localhost:8000/docs - Review API reference: `docs/api-reference.md` - Check deployment guide: `docs/deployment.md` - Review architecture: `docs/architecture.md`