### Configuration via .env Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Example of setting the DEEPGRAM_API_KEY in a sample.env template and starting the server with 'make start'. The key is read from the environment at module level. ```bash # sample.env template (also honored if set as a real env var): DEEPGRAM_API_KEY=your_api_key_here make start ``` -------------------------------- ### Quick Start Commands Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/AGENTS.md Initializes the project by cloning submodules and installing dependencies, sets up the environment by copying sample.env to .env, and starts both the backend and frontend servers. The backend runs on port 8081 and the frontend on port 8080. ```bash # Initialize (clone submodules + install deps) make init # Set up environment test -f .env || cp sample.env .env # then set DEEPGRAM_API_KEY # Start both servers make start # Backend: http://localhost:8081 # Frontend: http://localhost:8080 ``` -------------------------------- ### GET /api/metadata - curl example with output Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/endpoints.md Curl command to fetch metadata from /api/metadata, with the expected JSON response shown as commented output. ```bash curl -s http://localhost:8081/api/metadata | python3 -m json.tool # { # "title": "C# Text-to-Speech", # "description": "Get started using Deepgram's Text-to-Speech with this C# demo app", # "author": "Deepgram DX Team (https://developers.deepgram.com)", # "repository": "https://github.com/deepgram-starters/csharp-text-to-speech", # "useCase": "text-to-speech", # "language": "csharp", # "framework": "dotnet", # "sdk": "6.9.0", # "tags": ["text-to-speech", "tts", "audio-generation", "csharp", "dotnet"] # } ``` -------------------------------- ### Start Backend and Frontend Separately Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/AGENTS.md Starts the backend with 'dotnet run' in one terminal and the frontend with 'corepack pnpm run dev' in another. The frontend command specifies port 8080 and disables opening a browser. ```bash # Terminal 1 — Backend dotnet run # Terminal 2 — Frontend cd frontend && corepack pnpm run dev -- --port 8080 --no-open ``` -------------------------------- ### GET /health - curl example Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/endpoints.md Curl command to test the /health endpoint, piping output through python3 -m json.tool for pretty printing. ```bash curl -s http://localhost:8081/health | python3 -m json.tool ``` -------------------------------- ### Server-side validation example Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Example from Program.cs:247-257 showing how ValidateTextInput is used to return a 400 error with an EMPTY_TEXT code when text is null or whitespace. ```csharp if (text == null) { var (errCode, errBody) = FormatErrorResponse( "Text parameter is required", 400, "EMPTY_TEXT"); return HttpResults.Json(errBody, statusCode: errCode); } if (!ValidateTextInput(text)) { var (errCode, errBody) = FormatErrorResponse( "Text must be a non-empty string", 400, "EMPTY_TEXT"); return HttpResults.Json(errBody, statusCode: errCode); } ``` -------------------------------- ### Consumer error handling example Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Shows how a client can trigger and observe the validation error. Sends a POST with whitespace-only text and receives a 400 response with an EMPTY_TEXT error. ```bash TOKEN=$(curl -s http://localhost:8081/api/session | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])") curl -s -X POST http://localhost:8081/api/text-to-speech \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"text":" "}' -w "\nHTTP %{http_code}" # {"error":{"type":"ValidationError","code":"EMPTY_TEXT", # "message":"Text must be a non-empty string", # "details":{"originalError":"Text must be a non-empty string"}}} # HTTP 400 ``` -------------------------------- ### GET /health - JSON response Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/endpoints.md Returns a 200 OK with a JSON object containing status and service fields. No parameters are required. ```json { "status": "ok", "service": "text-to-speech" } ``` -------------------------------- ### GET /api/metadata Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/endpoints.md Returns the [meta] table of deepgram.toml as a JSON object. This endpoint is unprotected but rate-limited like other /api/* routes (120 req/min). ```APIDOC ## GET /api/metadata ### Description Returns the [meta] table of deepgram.toml as a JSON object. The file is read from the current directory, and the response shape is determined by the file contents. ### Method GET ### Endpoint /api/metadata ### Parameters No parameters. ### Request Example No request body or parameters. ### Response #### Success Response (200) - **title** (string) - The title of the application - **description** (string) - Description of the application - **author** (string) - Author information - **repository** (string) - Repository URL - **useCase** (string) - Use case identifier - **language** (string) - Programming language - **framework** (string) - Framework used - **sdk** (string) - SDK version - **tags** (array of string) - List of tags #### Response Example { "title": "C# Text-to-Speech", "description": "Get started using Deepgram's Text-to-Speech with this C# demo app", "author": "Deepgram DX Team (https://developers.deepgram.com)", "repository": "https://github.com/deepgram-starters/csharp-text-to-speech", "useCase": "text-to-speech", "language": "csharp", "framework": "dotnet", "sdk": "6.9.0", "tags": ["text-to-speech", "tts", "audio-generation", "csharp", "dotnet"] } #### Error Responses (500) - **error** (string) - Error code, always "INTERNAL_SERVER_ERROR" - **message** (string) - Error message describing the failure #### Error Response Example { "error": "INTERNAL_SERVER_ERROR", "message": "Missing [meta] section in deepgram.toml" } ``` -------------------------------- ### GET /health Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/endpoints.md Liveness/heartbeat endpoint that returns a simple JSON status object. It is unprotected and not rate-limited, allowing infrastructure like Fly.io to poll it freely. ```APIDOC ## GET /health ### Description Liveness/heartbeat endpoint, unprotected, and proxied without rate limiting in the production Caddy config, so Fly.io can poll it freely. ### Method GET ### Endpoint /health ### Parameters No parameters. ### Request Example No request body or parameters. ### Response #### Success Response (200) - **status** (string) - always "ok" - **service** (string) - always "text-to-speech" #### Response Example { "status": "ok", "service": "text-to-speech" } ``` -------------------------------- ### Server-side token validation in TTS route (C#) Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Example of using ValidateSessionToken in the TTS route. Checks for Bearer prefix, returns 401 with MISSING_TOKEN if absent, and INVALID_TOKEN if validation fails. ```csharp var authHeader = request.Headers.Authorization.FirstOrDefault() ?? ""; if (!authHeader.StartsWith("Bearer ")) { return HttpResults.Json(new Dictionary { ["error"] = new Dictionary { ["type"] = "AuthenticationError", ["code"] = "MISSING_TOKEN", ["message"] = "Authorization header with Bearer token is required", } }, statusCode: 401); } if (!ValidateSessionToken(authHeader[7..])) { return HttpResults.Json(new Dictionary { ["error"] = new Dictionary { ["type"] = "AuthenticationError", ["code"] = "INVALID_TOKEN", ["message"] = "Invalid or expired session token", } }, statusCode: 401); } ``` -------------------------------- ### Run conformance tests and manual endpoint checks Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/AGENTS.md Run conformance tests with 'make test' (requires the app to be running). Then manually check the /api/metadata and /api/session endpoints using curl and format the JSON output with python3 -m json.tool. ```bash # Run conformance tests (requires app to be running) make test # Manual endpoint check curl -sf http://localhost:8081/api/metadata | python3 -m json.tool curl -sf http://localhost:8081/api/session | python3 -m json.tool ``` -------------------------------- ### sample.env template Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/configuration.md Committed template for environment configuration. Required DEEPGRAM_API_KEY; optional PORT (default 8081) and HOST (default 0.0.0.0); SESSION_SECRET for production nonce validation. Copied to .env by make init. ```dotenv # Required DEEPGRAM_API_KEY=%api_key% # Optional (defaults shown) PORT=8081 HOST=0.0.0.0 # Session auth (set in production to enable nonce validation) SESSION_SECRET=%session_secret% ``` -------------------------------- ### Client flow with curl (bash) Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Bash script showing how to obtain a token and test the TTS endpoint. Valid token returns 200, missing header returns 401 with MISSING_TOKEN. ```bash # 1. Obtain a token TOKEN=$(curl -s http://localhost:8081/api/session | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])") # 2. Valid token succeeds curl -s -o /dev/null -w "%{http_code}\n" \ -X POST http://localhost:8081/api/text-to-speech \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"text":"hello"}' # 200 # 3. Missing header yields MISSING_TOKEN curl -s -o /dev/null -w "%{http_code}\n" \ -X POST http://localhost:8081/api/text-to-speech \ -H "Content-Type: application/json" -d '{"text":"hello"}' # 401 ``` -------------------------------- ### Clean Rebuild Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/AGENTS.md Removes build artifacts and node_modules, then reinitializes the project. This is useful for a fresh build after dependency changes or corruption. ```bash rm -rf bin obj frontend/node_modules frontend/.vite make init ``` -------------------------------- ### Stop All Servers Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/AGENTS.md Kills processes listening on ports 8080 and 8081 using lsof and xargs. This forcefully stops both the backend and frontend servers. ```bash lsof -ti:8080,8081 | xargs kill -9 2>/dev/null ``` -------------------------------- ### ValidateSessionToken signature (C#) Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Exact method signature for ValidateSessionToken. Takes a raw JWT string and returns true if valid, false otherwise. ```csharp bool ValidateSessionToken(string token) ``` -------------------------------- ### Failure mode without API key Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Demonstrates the failure when DEEPGRAM_API_KEY is not set. Running 'dotnet run' prints an error banner to stderr and exits with code 1, as shown by 'echo $?'. ```bash # With no DEEPGRAM_API_KEY anywhere: dotnet run # stderr: # ❌ ERROR: Deepgram API key not found! # Please set your API key using one of these methods: ... echo $? # 1 ``` -------------------------------- ### LoadApiKey signature Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Exact signature of the LoadApiKey static method from Program.cs:91. Returns the DEEPGRAM_API_KEY environment variable as a non-empty string, or terminates the process with exit code 1 if missing. ```csharp static string LoadApiKey() ``` -------------------------------- ### Error envelope and auth shape Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/types.md Shows the dictionary shapes for the error envelope produced by FormatErrorResponse and the reduced auth error shape. The envelope includes type, code, message, and details; the auth shape omits details. ```csharp Dictionary // FormatErrorResponse shape "error" => Dictionary "type" => string // "ValidationError" | "GenerationError" "code" => string // "EMPTY_TEXT" | "MODEL_NOT_FOUND" | "TEXT_TOO_LONG" | "INVALID_TEXT" "message" => string "details" => Dictionary "originalError" => string Dictionary // auth shape (Program.cs:213-230) "error" => Dictionary "type" => "AuthenticationError" "code" => "MISSING_TOKEN" | "INVALID_TOKEN" "message" => string // no "details" key ``` -------------------------------- ### ValidateTextInput signature Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Exact signature of the ValidateTextInput static method from Program.cs:140. Returns true for non-null, non-whitespace text; false otherwise. ```csharp static bool ValidateTextInput(string? text) ``` -------------------------------- ### ValidateSessionToken Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/api-reference/functions.md Validates a JWT against the module-level sessionSecretKey. Returns true if the token is valid, false otherwise. Never throws exceptions; all validation failures return false. ```APIDOC ## ValidateSessionToken ### Description Validates a JWT against the module-level `sessionSecretKey`. Returns `true` when the token validates, `false` otherwise. Never throws exceptions; all validation failures (bad signature, expired token, malformed token, wrong algorithm) surface as `false`. ### Signature ```csharp bool ValidateSessionToken(string token) ``` ### Parameters - **token** (string) - Required - The raw JWT string. The TTS route passes the text after the `"Bearer "` prefix (`authHeader[7..]`). ### Return Type - **bool** - `true` when the token validates, `false` otherwise. ### Validation Parameters - `ValidateIssuerSigningKey = true` with `IssuerSigningKey = sessionSecretKey` - the HS256 signature is verified. - `ValidateIssuer = false`, `ValidateAudience = false` - no issuer/audience checks. - `ClockSkew = TimeSpan.Zero` - expiry is enforced exactly; any `exp` in the past fails. ### Throws Never - the entire body is wrapped in `try { ... } catch { return false; }`. Every validation failure surfaces as `false`, not as an exception. ### Example - Server-side use in the TTS route ```csharp var authHeader = request.Headers.Authorization.FirstOrDefault() ?? ""; if (!authHeader.StartsWith("Bearer ")) { return HttpResults.Json(new Dictionary { ["error"] = new Dictionary { ["type"] = "AuthenticationError", ["code"] = "MISSING_TOKEN", ["message"] = "Authorization header with Bearer token is required", } }, statusCode: 401); } if (!ValidateSessionToken(authHeader[7..])) { return HttpResults.Json(new Dictionary { ["error"] = new Dictionary { ["type"] = "AuthenticationError", ["code"] = "INVALID_TOKEN", ["message"] = "Invalid or expired session token", } }, statusCode: 401); } ``` ### Example - Client flow with error handling ```bash # 1. Obtain a token TOKEN=$(curl -s http://localhost:8081/api/session | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])") # 2. Valid token succeeds curl -s -o /dev/null -w "%{http_code}\n" \ -X POST http://localhost:8081/api/text-to-speech \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"text":"hello"}' # 200 # 3. Missing header yields MISSING_TOKEN curl -s -o /dev/null -w "%{http_code}\n" \ -X POST http://localhost:8081/api/text-to-speech \ -H "Content-Type: application/json" -d '{"text":"hello"}' # 401 ``` ``` -------------------------------- ### FormatErrorResponse tuple return type Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/types.md Declared in Program.cs:146. Returns a tuple with an HTTP status code and an error envelope object. The status code is 400 for validation errors, otherwise 500 or the caller's value. ```csharp static (int statusCode, object body) FormatErrorResponse(string message, ...) ``` -------------------------------- ### Error response envelope: auth failure shape Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/errors.md JSON shape for authentication failures, returned inline in the route at Program.cs:213-230. Contains a three-field error object with no details key. ```json { "error": { "type": "AuthenticationError", "code": "MISSING_TOKEN", "message": "Authorization header with Bearer token is required" } } ``` -------------------------------- ### Error response envelope: generic error shape Source: https://github.com/deepgram-starters/csharp-text-to-speech/blob/main/_autodocs/errors.md JSON shape for all non-auth errors, produced by FormatErrorResponse at Program.cs:146-182. Includes a details object with the original error message. ```json { "error": { "type": "ValidationError", "code": "EMPTY_TEXT", "message": "Text must be a non-empty string", "details": { "originalError": "Text must be a non-empty string" } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.