Documentation Index
Fetch the complete documentation index at: https://docs.talkturo.ai/llms.txt
Use this file to discover all available pages before exploring further.
Webhooks liefern Ereignisse in Echtzeit an Ihren Server — ohne API-Polling. Talkturo unterscheidet Anrufstatus-Ereignisse aus der Telefonie und Abrechnungsereignisse vom Abo-Anbieter. Ziel-URLs tragen Sie im Dashboard ein; bei einem Ereignis sendet Talkturo eine signierte POST-Anfrage an diese URL.
Open Integrations settings
In the Talkturo dashboard, navigate to Settings → Integrations.
Enter your endpoint URL
In the Webhooks section, enter the publicly reachable HTTPS URL of your server for each webhook type. The URL must return a 200 status code within 5 seconds or Talkturo will treat the delivery as failed.
Save and test
Click Save. Use the Send test event button to verify your endpoint receives and processes the payload correctly.
Your webhook endpoint must be reachable over the public internet. Localhost URLs will not receive events in production.
Webhook security
Talkturo includes a cryptographic signature in the Telnyx-Signature-Ed25519 header (for call webhooks) and a X-Signature header (for billing webhooks). Verify this signature before processing the payload to confirm the request originated from Talkturo and was not tampered with.
The signature is a base64-encoded HMAC or Ed25519 signature computed over the raw request body. Compare it against a signature you compute using your webhook secret, available in the dashboard under Settings → Integrations → Webhook Secrets.
Always verify signatures in production. Skipping signature verification exposes your endpoint to spoofed events.
Call status webhook
POST /api/db/webhook
Talkturo sends call status events to this endpoint as calls progress through their lifecycle. Configure the URL your server exposes for this path in the dashboard.
Event types
| Event | Description |
|---|
call.initiated | An outbound call was placed or an inbound call arrived |
call.answered | The callee picked up |
call.completed | The call ended normally |
call.hangup | One party disconnected the call |
call.machine_detection.ended | Answering machine detection completed |
call.recording.saved | A call recording was saved to storage |
Payload structure
{
"type": "call.completed",
"data": {
"call_control_id": "v2:T02llLL...",
"call_leg_id": "0cf8a7d8-...",
"call_session_id": "84a7e8b2-...",
"client_state": "eyJhc3Npc3RhbnRJZCI6...",
"connection_id": "1234567890",
"from": "+14155550101",
"to": "+12025551234",
"direction": "outbound",
"start_time": "2024-01-15T14:00:00Z",
"end_time": "2024-01-15T14:04:32Z",
"duration_secs": 272
}
}
```| Feld | Geben Sie | ein Beschreibung |
|-------|------|-------------|
| „Typ“ | Zeichenfolge | Der Ereignistyp (z. B. „call.completed“) |
| `data.call_control_id` | Zeichenfolge | Telnyx-Anrufsteuerungskennung |
| `data.call_leg_id` | Zeichenfolge | Eindeutiger Bezeichner für diesen Anrufabschnitt |
| `data.call_session_id` | Zeichenfolge | Gruppiert alle Beine in derselben Sitzung |
| `data.client_state` | Zeichenfolge | Base64-codierte Metadaten, die bei der Initiierung des Anrufs übergeben wurden |
| `data.connection_id` | Zeichenfolge | Die vom Anruf verwendete Telnyx-Verbindung |
| `data.from` | Zeichenfolge | Anrufernummer im E.164-Format |
| `data.to` | Zeichenfolge | Angerufene Nummer im E.164-Format |
| `data.direction` | Zeichenfolge | „eingehend“ oder „ausgehend“ |
| `data.start_time` | Zeichenfolge | ISO 8601 Datum und Uhrzeit des Anrufbeginns |
| `data.end_time` | Zeichenfolge | ISO 8601 Datum und Uhrzeit des Endes des Anrufs (nur „call.completed“) |
| `data.duration_secs` | Ganzzahl | Anrufdauer in Sekunden (nur „call.completed“) |
### Beispielhandler```javascript
import { createHmac } from 'crypto';
export async function POST(request) {
const body = await request.text();
const signature = request.headers.get('Telnyx-Signature-Ed25519');
// Verify the signature using your webhook secret from the dashboard
const isValid = verifyTelnyxSignature(body, signature, process.env.WEBHOOK_SECRET);
if (!isValid) {
return new Response('Unauthorized', { status: 401 });
}
const event = JSON.parse(body);
switch (event.type) {
case 'call.completed':
await handleCallCompleted(event.data);
break;
case 'call.answered':
await handleCallAnswered(event.data);
break;
}
return new Response('OK', { status: 200 });
}
Billing webhook
POST /api/billing/webhook
Talkturo sends subscription and payment events to this endpoint when your billing status changes. Talkturo supports both Stripe and LemonSqueezy as billing providers.
Event types
| Event | Description |
|---|
subscription.created | A new subscription was activated |
subscription.updated | Subscription plan or status changed |
subscription.cancelled | Subscription was cancelled |
subscription.expired | Subscription reached end of billing period |
invoice.paid | A payment was successfully collected |
invoice.payment_failed | A payment attempt failed |
Payload structure
{
"type": "subscription.created",
"data": {
"subscription_id": "sub_...",
"customer_id": "cus_...",
"plan_name": "Growth",
"status": "active",
"current_period_start": "2024-01-15T00:00:00Z",
"current_period_end": "2024-02-15T00:00:00Z",
"metadata": {
"team_id": "team_01j..."
}
}
}
```| Feld | Geben Sie | ein Beschreibung |
|-------|------|-------------|
| „Typ“ | Zeichenfolge | Der Abrechnungsereignistyp |
| `data.subscription_id` | Zeichenfolge | Die Abonnement-ID Ihres Abrechnungsanbieters |
| `data.customer_id` | Zeichenfolge | Die Kundenkennung Ihres Abrechnungsanbieters |
| `data.plan_name` | Zeichenfolge | Der Name des Plans (z. B. „Growth“, „Enterprise“) |
| `data.status` | Zeichenfolge | Abonnementstatus („aktiv“, „abgebrochen“, „überfällig“) |
| `data.current_period_start` | Zeichenfolge | ISO 8601 Beginn des aktuellen Abrechnungszeitraums |
| `data.current_period_end` | Zeichenfolge | ISO 8601 Ende des aktuellen Abrechnungszeitraums |
| `data.metadata.team_id` | Zeichenfolge | Die diesem Abonnement zugeordnete Talkturo-Team-ID |
### Beispielhandler```javascript
export async function POST(request) {
const body = await request.text();
const signature = request.headers.get('X-Signature');
// Verify the signature using your billing webhook secret
const isValid = verifySignature(body, signature, process.env.WEBHOOK_SECRET);
if (!isValid) {
return new Response('Unauthorized', { status: 401 });
}
const event = JSON.parse(body);
switch (event.type) {
case 'subscription.created':
await activateTeamFeatures(event.data.metadata.team_id, event.data.plan_name);
break;
case 'subscription.cancelled':
await downgradeTeamFeatures(event.data.metadata.team_id);
break;
}
return new Response('OK', { status: 200 });
}
Retry behavior
If your endpoint does not return a 2xx status code within 5 seconds, Talkturo retries the delivery with exponential backoff. To avoid processing duplicate events, make your webhook handler idempotent — check whether you have already processed a given event ID before acting on it.