--- title: Authentication | Formbricks Hub description: Secure your Hub API with Bearer token authentication. --- ## How It Works Hub requires Bearer token authentication. All API endpoints require the `Authorization` header with a Bearer token, except the health check endpoint, which is public. ## Configuring Authentication ### 1. Set Environment Variable Add `API_KEY` to your `.env` file: Terminal window ``` API_KEY=your-secret-key-here ``` Generate a cryptographically secure key: Terminal window ``` # macOS/Linux openssl rand -base64 32 # Or use a password manager's random generator ``` ### 2. Start the Service Terminal window ``` make run ``` ### 3. Include Token in Requests All API requests except `GET /health` require the `Authorization` header: Terminal window ``` curl -H "Authorization: Bearer your-secret-key-here" \ http://localhost:8080/v1/feedback-records ``` ## Protected Endpoints These endpoints require authentication: - `POST /v1/feedback-records` - Create feedback record - `GET /v1/feedback-records` - List feedback records - `GET /v1/feedback-records/{id}` - Get feedback record - `PATCH /v1/feedback-records/{id}` - Update feedback record - `DELETE /v1/feedback-records/{id}` - Delete feedback record - `DELETE /v1/feedback-records?user_identifier=` - Bulk delete feedback records by user Always public (no auth required): - `GET /health` - Health check The OpenAPI spec is maintained in the repo as `openapi.yaml` and used for contract tests (Schemathesis). Serving it at runtime (for example, `GET /openapi.json` or `GET /docs`) is planned. ## Authentication Workflow ### Request Flow ``` Client Request | Has Authorization header? | No -> 401 Unauthorized Yes -> Is format "Bearer "? | No -> 401 Unauthorized Yes -> Token matches API_KEY? | No -> 401 Unauthorized Yes -> Process Request | 200 Success ``` ### Example Requests Without authentication: Terminal window ``` curl http://localhost:8080/v1/feedback-records ``` Response: ``` { "title": "Unauthorized", "status": 401, "detail": "Missing Authorization header" } ``` With authentication: Terminal window ``` curl -H "Authorization: Bearer your-secret-key-here" \ http://localhost:8080/v1/feedback-records ``` Response: ``` { "data": [...], "total": 10 } ``` ## Production Deployment Hub’s built-in Bearer token authentication is ideal for: - Internal services and tools - Server-to-server communication - Quick production deployments For public APIs or multi-tenant systems, consider deploying behind an API gateway (AWS API Gateway, Kong, Traefik) for advanced features like OAuth, JWT, or per-user access control. ### Docker Deployment with Auth Terminal window ``` docker run -d \ -p 8080:8080 \ -e DATABASE_URL=postgres://... \ -e API_KEY=your-secret-key-here \ ghcr.io/formbricks/hub:latest ``` ### Environment Variables Terminal window ``` # Database connection DATABASE_URL=postgres://user:pass@host/db # Authentication (required) API_KEY=your-secret-key-here # Optional LOG_LEVEL=info PORT=8080 ``` [See full environment variable reference ->](/reference/environment-variables/index.md) ## Security Best Practices ### 1. Use HTTPS in Production Always use HTTPS to encrypt tokens in transit: ``` http://api.example.com (insecure) https://api.example.com (secure) ``` ### 2. Store Keys Securely Good practices: - Use environment variables (not hardcoded) - Store in secret management (AWS Secrets Manager, HashiCorp Vault) - Rotate keys regularly Avoid: - Committing keys to Git - Sharing keys via email/Slack - Using the same key for dev and prod ### 3. Rotate Keys Regularly Schedule regular key rotation (for example, every 90 days): 1. Generate new key 2. Update `API_KEY` in production 3. Restart service 4. Update clients with new key ### 4. Monitor for Unauthorized Access Enable structured logging to track failed auth attempts: Terminal window ``` LOG_LEVEL=info ``` Look for 401 responses in logs: ``` { "level": "warn", "msg": "unauthorized request", "path": "/v1/feedback-records", "ip": "203.0.113.1" } ``` ## Troubleshooting ### 401 Unauthorized Error Symptom: ``` { "title": "Unauthorized", "status": 401, "detail": "Missing Authorization header" } ``` Solutions: 1. Check if `API_KEY` is set: Terminal window ``` grep API_KEY .env ``` 2. Verify header format: Terminal window ``` # Correct curl -H "Authorization: Bearer your-key" http://... # Wrong (missing Bearer) curl -H "Authorization: your-key" http://... # Wrong (using X-API-Key instead) curl -H "X-API-Key: your-key" http://... ``` 3. Check key matches `.env`: Terminal window ``` cat .env | grep API_KEY ``` ### Health Check Returns 401 Health checks (`/health`) should never require auth. If you see this, it’s a bug. Please [report it](https://github.com/formbricks/hub/issues). ### Future Spec Endpoint If you add a `/docs` or `/openapi.json` endpoint to serve the API spec, it should remain public (no auth). ## Examples ### cURL Terminal window ``` curl -H "Authorization: Bearer abc123" \ -X POST http://localhost:8080/v1/feedback-records \ -H "Content-Type: application/json" \ -d '{"source_type":"survey","field_id":"q1","field_type":"text","value_text":"Great!"}' ``` ### JavaScript (Node.js) ``` const response = await fetch("http://localhost:8080/v1/feedback-records", { headers: { Authorization: "Bearer abc123", "Content-Type": "application/json", }, method: "POST", body: JSON.stringify({ source_type: "survey", field_id: "q1", field_type: "text", value_text: "Great!", }), }); ``` ### Python ``` import requests headers = { "Authorization": "Bearer abc123", "Content-Type": "application/json", } response = requests.get( "http://localhost:8080/v1/feedback-records", headers=headers ) ``` ### Go ``` client := &http.Client{} req, _ := http.NewRequest("GET", "http://localhost:8080/v1/feedback-records", nil) req.Header.Set("Authorization", "Bearer abc123") resp, err := client.Do(req) ``` ## Next Steps - [Data Model](/core-concepts/data-model/index.md) - Understand the feedback record structure - [API Reference](/api/index.md) - Explore endpoints - [Environment Variables](/reference/environment-variables/index.md) - Configuration reference