Getting started / Build with AI agents

Build with AI agents

Turnix is AI ready: integrate it in seconds. Coding agents such as Claude Code, Cursor or GitHub Copilot can do a Turnix integration for you, if they get accurate facts about the API. The prompts on this page give them exactly that: the endpoint, the auth rules, the response shape and the errors, plus a step-by-step task.

You have Prompt
A web app with any backend Integrate Turnix into an existing WebRTC app (below)
A self-hosted coturn Migrate from self-hosted coturn (below)
Turnix running, want per-call tracking Add per-room client tracking (below)
A Flutter app Flutter integration
A Node.js backend JavaScript / Node.js SDK
Nextcloud Talk Nextcloud Talk (agent runs on your server)
Jitsi Meet Jitsi Meet (agent runs on your server)

How to use these prompts#

  1. Claude Code: click Copy for Claude Code on one of the cards below and run the copied command in your project directory. It starts Claude Code with the prompt already loaded, for example:
bash
   claude "$(curl -fsSL https://turnix.io/docs/prompts/integrate-turnix-into-an-existing-webrtc-app.txt)"
  1. Cursor, GitHub Copilot or another agent: open your project in the agent, click Copy prompt and paste it into the agent chat.
  2. Set TURNIX_API_TOKEN in your local environment first if you want the agent to verify the integration with a real API call. Create a token under API Tokens.
  3. Review the diff. In particular, check that the token is read only on the server and never logged.
Do not paste your token into the chat

The prompts refer to the TURNIX_API_TOKEN environment variable on purpose. Never paste the token itself into a prompt.

Integrate Turnix into an existing WebRTC app#

The standard integration: a backend endpoint that requests credentials and a client that uses them. This is the same prompt as in the Quickstart.

Integrate Turnix into an existing WebRTC app
Add Turnix (managed TURN/STUN servers) to the WebRTC app in this repository.

Context about Turnix:
- Endpoint: POST https://turnix.io/api/v1/credentials/ice
- Auth header: "Authorization: Bearer <token>". The token is a secret project API token. Read it from the environment variable TURNIX_API_TOKEN. Never send it to the browser or mobile client, never log it, never commit it.
- Optional body fields (JSON or form-encoded): ttl (integer seconds, digits only), room, initiator_client, receiver_client (letters, digits, "-" and "_" only), preferred_region or fixed_region (a region slug).
- Optional header X-TURN-CLIENT-IP: the end user's public IP. Set it, because otherwise Turnix picks the TURN region closest to the backend server instead of the user.
- Success (200) response: {"iceServers":[{"urls":["stun:stun.turnix.io:3478"]},{"username":"<uuid>","credential":"<hex>","urls":["turn:<region>.turnix.io:3478?transport=udp","turn:<region>.turnix.io:3478?transport=tcp","turns:<region>.turnix.io:443?transport=udp","turns:<region>.turnix.io:443?transport=tcp"]}],"expiresAt":"<ISO 8601 UTC timestamp>"}
- Errors are JSON with an "error" field: 401 (missing or unknown token), 422 (invalid parameter, unknown or offline region), 429 (the organization's data usage limit is reached; body also has "message", "limit" and "used").
- Docs: https://turnix.io/docs/api-reference/credentials

Do the following:
1. Inspect the repository. Find the backend framework, where the client creates RTCPeerConnection, and how the client already calls the backend (auth, fetch helper, base URL). Follow the existing conventions. If there is no backend, stop and ask me where the endpoint should live.
2. Backend: add an authenticated endpoint (for example GET /api/turn-credentials) that only signed-in users of this app can call. It calls the Turnix endpoint server-side with the token from TURNIX_API_TOKEN, forwards the caller's public IP in X-TURN-CLIENT-IP (respect the app's trusted-proxy setup when reading the IP), sends ttl=3600, and sends room/initiator_client when the app has a call or user identifier (sanitize to [A-Za-z0-9_-]). Use a 10-second timeout. Return only {"iceServers": [...], "expiresAt": "..."} to the client.
3. Error handling: if TURNIX_API_TOKEN is missing, fail at startup or return 500 with a clear log message. Map Turnix 401 to a 502 with a log line saying the token is invalid; pass 429 through as 503 with a "TURN usage limit reached" message; never include the token in errors or logs.
4. Frontend: before creating each RTCPeerConnection, fetch the new endpoint and pass iceServers into new RTCPeerConnection({ iceServers }). Keep any existing STUN servers only if the app needs them. If expiresAt has passed or is less than 60 seconds away when a new connection or ICE restart is needed, fetch fresh credentials first (for an ICE restart, call pc.setConfiguration({ ...pc.getConfiguration(), iceServers }) and then pc.restartIce()). Do not cache credentials in localStorage.
5. Configuration: add TURNIX_API_TOKEN to .env.example (or the project's equivalent) with an empty value and a comment, and document it in the README. Make sure .env is git-ignored.
6. Tests: add a backend test that mocks the Turnix API and checks that the endpoint sends the Bearer token and X-TURN-CLIENT-IP, returns iceServers, and does not expose the token. Then, if TURNIX_API_TOKEN is set in my environment, make one real call with curl to the Turnix endpoint and show me the status code and the number of iceServers (do not print the credentials).
7. Summarize the files you changed and anything I still need to do (for example, setting TURNIX_API_TOKEN in production).

Migrate from self-hosted coturn#

Use this when your app currently points at your own coturn server, typically with a static user or a static-auth-secret and credentials generated in your code.

Migrate from self-hosted coturn to Turnix
Migrate this application from a self-hosted coturn TURN server to Turnix (managed TURN/STUN).

Context about Turnix:
- Credentials endpoint: POST https://turnix.io/api/v1/credentials/ice with header "Authorization: Bearer <token>". The token is a secret project API token in the environment variable TURNIX_API_TOKEN; use it only on the server, never log or commit it.
- Optional body fields: ttl (integer seconds), room, initiator_client, receiver_client (letters, digits, "-" and "_" only), preferred_region or fixed_region (region slug). Optional header X-TURN-CLIENT-IP with the end user's public IP so the nearest region is chosen.
- 200 response: {"iceServers":[{"urls":["stun:stun.turnix.io:3478"]},{"username":"<uuid>","credential":"<hex>","urls":["turn:<region>.turnix.io:3478?transport=udp","turn:<region>.turnix.io:3478?transport=tcp","turns:<region>.turnix.io:443?transport=udp","turns:<region>.turnix.io:443?transport=tcp"]}],"expiresAt":"<ISO 8601 UTC>"}
- Errors: JSON {"error": "..."}; 401 bad/missing token, 422 invalid parameter or region, 429 usage limit reached.
- Turnix also offers a per-project shared secret ("auth secret") for software that generates TURN REST API credentials itself (username = unix expiry timestamp, password = base64(HMAC-SHA1(secret, username))), with hosts <region>.turnix.io on ports 3478 (turn, UDP/TCP) and 443 (turns). Prefer the credentials endpoint for code you control.
- Docs: https://turnix.io/docs/api-reference/credentials and https://turnix.io/docs/integrations/shared-secret

Do the following:
1. Find every place that references the old TURN/STUN setup: hard-coded turn:/stun: URLs, coturn usernames/passwords, static-auth-secret or HMAC credential generation, related environment variables, docker-compose services, deployment manifests and firewall docs. List them for me before changing anything.
2. Replace the credential generation with a server-side call to the Turnix credentials endpoint (one call per new peer connection, ttl=3600, forward the user's IP in X-TURN-CLIENT-IP, 10-second timeout). Return only iceServers and expiresAt to clients. Keep the existing client-facing response shape if other code depends on it, and adapt it from the Turnix response.
3. Remove the old static TURN usernames, passwords and secrets from code and config. Replace the related environment variables with TURNIX_API_TOKEN and update .env.example and the README.
4. Remove the coturn service from docker-compose or deployment files only if nothing else uses it, and tell me what you removed. Do not touch infrastructure outside this repository.
5. Handle errors without leaking the token: log Turnix 401 as a configuration error, surface 429 as "TURN usage limit reached".
6. Update or add tests that mock the Turnix endpoint. If TURNIX_API_TOKEN is set in my environment, make one real request and report the HTTP status and the TURN hostname in the response (not the username or credential).
7. Summarize the changes and the manual steps left (setting TURNIX_API_TOKEN in each environment, decommissioning the old server).

Add per-room client tracking#

Use this when Turnix already works and you want calls to show up per room and per participant in the dashboard.

Add Turnix client and room tracking
This app already requests TURN credentials from Turnix (POST https://turnix.io/api/v1/credentials/ice, server-side, Bearer token from TURNIX_API_TOKEN). Add client and room labels to those requests so calls can be traced in the Turnix dashboard.

Facts about the Turnix API:
- Optional body fields: room, initiator_client, receiver_client. Each value may contain only letters, digits, "-" and "_" (regex ^[A-Za-z0-9_-]+$). Any other character makes the whole request fail with 422 {"error":"<field> contains invalid characters"}.
- Turnix creates a client or room the first time it sees a new name in the project and reuses it afterwards. Clients sent together with a room are linked to that room.
- initiator_client is the participant that starts the connection (creates the offer), receiver_client the one that answers. For group calls, send only room and initiator_client (the requesting participant).
- Labels are visible to everyone with access to the Turnix project. Do not send personal data such as email addresses or names; use internal IDs or opaque hashes.
- Docs: https://turnix.io/docs/concepts/clients-rooms

Do the following:
1. Find where the backend calls the Turnix credentials endpoint and where it knows the current user and the call/meeting/room identifier.
2. Add a small helper that turns an internal ID into a safe label: keep [A-Za-z0-9_-], replace everything else with "-", trim to 64 characters, and fall back to omitting the field if the result is empty. Use a stable, non-personal identifier (for example the user's database ID or a hash of it).
3. Send room=<call id label> and initiator_client=<current user label> with every credential request. If the app has a 1:1 call model where the backend knows the other participant, also send receiver_client.
4. Make sure the client-facing API does not let users choose arbitrary labels for other users.
5. Add unit tests for the helper (including emails, spaces, unicode and very long IDs) and a test that the Turnix request body contains the expected labels.
6. Summarize the change and where I can see the result in the dashboard (Rooms and Clients pages).

Give your agent the docs#

Agents produce better code when they can read the reference itself. The docs are built for that:

The most useful pages to give your agent:

Last updated October 30, 2026