> ## 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.

# REST-API-Endpunkte für Kampagnen

> Erstellen, listen, starten und verwalten Sie ausgehende Anrufkampagnen mit der Talkturo-API. Beinhaltet Terminplanung, Anruffenster und Endpunkte für die Kontaktzuweisung.

Mit Kampagnen führen Sie ausgehende Massenwahl zu einer Kontaktliste mit einem konfigurierten KI-Assistenten durch. Sie legen eine Kampagne mit Zeitplan und Wahloptionen an, fügen Kontakte hinzu und starten sie — die API deckt Erstellung, Kontaktlisten und Ausführung ab.

***

## List campaigns

`GET /api/crm/campaigns`

Returns a paginated list of campaigns for a team. You can filter by status, assistant, and whether to include soft-deleted campaigns.

### Query parameters

<ParamField query="teamId" type="string" required>
  The team ID to list campaigns for.
</ParamField>

<ParamField query="status" type="string">
  Filter campaigns by status. One of: `draft`, `scheduled`, `running`, `paused`, `completed`, `cancelled`.
</ParamField>

<ParamField query="assistantId" type="string">
  Filter campaigns assigned to a specific assistant ID.
</ParamField>

<ParamField query="deleted" type="string">
  Controls whether to include soft-deleted campaigns. One of: `exclude` (default), `include`, `only`.
</ParamField>

<ParamField query="limit" type="integer">
  Maximum number of records to return. Defaults to `50`.
</ParamField>

<ParamField query="offset" type="integer">
  Number of records to skip for pagination. Defaults to `0`.
</ParamField>

### Example request

```bash theme={null}
curl "https://<your-domain>/api/crm/campaigns?teamId=team_01j...&status=running&limit=20" \
  -H "Authorization: Bearer <token>"
```

### Antwort

```json theme={null}
{
  "success": true,
  "campaigns": [
    {
      "id": "camp_01j...",
      "team_id": "team_01j...",
      "assistant_id": "asst_01j...",
      "company_id": "comp_01j...",
      "name": "Q1 Outreach",
      "description": "Qualify leads from the January trade show",
      "from_number": "+12025551234",
      "status": "running",
      "call_window_start": "09:00",
      "call_window_end": "17:00",
      "call_window_timezone": "America/New_York",
      "max_concurrent_calls": 5,
      "total_contacts": 200,
      "contacts_called": 80,
      "contacts_completed": 65,
      "contacts_answered": 55,
      "created_at": "2024-01-10T09:00:00Z",
      "updated_at": "2024-01-15T14:30:00Z"
    }
  ],
  "count": 1,
  "limit": 20,
  "offset": 0
}
```

<ResponseField name="campaigns" type="array">
  Array of campaign objects.
</ResponseField>

<ResponseField name="campaigns[].id" type="string">
  Unique campaign identifier.
</ResponseField>

<ResponseField name="campaigns[].team_id" type="string">
  The team this campaign belongs to.
</ResponseField>

<ResponseField name="campaigns[].assistant_id" type="string">
  The assistant assigned to place calls in this campaign.
</ResponseField>

<ResponseField name="campaigns[].company_id" type="string">
  The company associated with this campaign.
</ResponseField>

<ResponseField name="campaigns[].name" type="string">
  Campaign name.
</ResponseField>

<ResponseField name="campaigns[].status" type="string">
  Current campaign status: `draft`, `scheduled`, `running`, `paused`, `completed`, or `cancelled`.
</ResponseField>

<ResponseField name="campaigns[].from_number" type="string">
  The phone number used as the caller ID for outbound calls.
</ResponseField>

<ResponseField name="campaigns[].call_window_start" type="string">
  Start of the daily call window in `HH:MM` format.
</ResponseField>

<ResponseField name="campaigns[].call_window_end" type="string">
  End of the daily call window in `HH:MM` format.
</ResponseField>

<ResponseField name="campaigns[].call_window_timezone" type="string">
  IANA timezone for the call window (for example, `America/New_York`).
</ResponseField>

<ResponseField name="campaigns[].max_concurrent_calls" type="integer">
  Maximum number of calls placed simultaneously.
</ResponseField>

<ResponseField name="campaigns[].total_contacts" type="integer">
  Total number of contacts in the campaign.
</ResponseField>

<ResponseField name="campaigns[].contacts_called" type="integer">
  Number of contacts where a call attempt was made.
</ResponseField>

<ResponseField name="campaigns[].contacts_completed" type="integer">
  Number of contacts where the call reached a terminal state.
</ResponseField>

<ResponseField name="campaigns[].contacts_answered" type="integer">
  Number of contacts who answered the call.
</ResponseField>

<ResponseField name="count" type="integer">
  Total number of campaigns matching the filters (before pagination).
</ResponseField>

<ResponseField name="limit" type="integer">
  The `limit` value applied to this response.
</ResponseField>

<ResponseField name="offset" type="integer">
  The `offset` value applied to this response.
</ResponseField>

***

## Create a campaign

`POST /api/crm/campaigns`

Creates a new outbound calling campaign. The campaign starts in `draft` status. Add contacts and then call the [run endpoint](#start-a-campaign) to begin dialing.

### Request body

<ParamField body="teamId" type="string" required>
  The team ID that owns this campaign.
</ParamField>

<ParamField body="assistantId" type="string" required>
  The ID of the assistant that will place calls.
</ParamField>

<ParamField body="companyId" type="string" required>
  The company ID to associate with this campaign.
</ParamField>

<ParamField body="fromNumberIds" type="array" required>
  An array of phone number IDs to use as caller IDs. Talkturo rotates across these numbers when placing calls.
</ParamField>

<ParamField body="name" type="string" required>
  A human-readable name for the campaign.
</ParamField>

<ParamField body="description" type="string">
  Optional description of the campaign's purpose.
</ParamField>

<ParamField body="scheduledStartAt" type="string">
  ISO 8601 datetime for when the campaign should start automatically. If omitted, you start the campaign manually via the run endpoint.
</ParamField>

<ParamField body="callWindowStart" type="string">
  Start of the daily calling window in `HH:MM` format (for example, `"09:00"`). Calls only go out during this window.
</ParamField>

<ParamField body="callWindowEnd" type="string">
  End of the daily calling window in `HH:MM` format (for example, `"17:00"`).
</ParamField>

<ParamField body="callWindowTimezone" type="string">
  IANA timezone for the call window (for example, `"America/New_York"`).
</ParamField>

<ParamField body="maxConcurrentCalls" type="integer">
  Maximum number of simultaneous outbound calls. Defaults to `3`.
</ParamField>

<ParamField body="maxAttemptsPerContact" type="integer">
  How many times to retry a contact who does not answer. Defaults to `3`.
</ParamField>

<ParamField body="retryDelayMinutes" type="integer">
  Minutes to wait before retrying a contact. Defaults to `60`.
</ParamField>

<ParamField body="settings" type="object">
  Additional campaign settings as a freeform object.
</ParamField>

### Example request

```bash theme={null}
curl -X POST https://<your-domain>/api/crm/campaigns \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "teamId": "team_01j...",
    "assistantId": "asst_01j...",
    "companyId": "comp_01j...",
    "fromNumberIds": ["pn_01j..."],
    "name": "Q1 Trade Show Follow-Up",
    "description": "Follow up with leads from the January trade show",
    "callWindowStart": "09:00",
    "callWindowEnd": "17:00",
    "callWindowTimezone": "America/New_York",
    "maxConcurrentCalls": 5,
    "maxAttemptsPerContact": 3,
    "retryDelayMinutes": 60
  }'
```

### Antwort

```json theme={null}
{
  "success": true,
  "campaign": {
    "id": "camp_01j...",
    "team_id": "team_01j...",
    "assistant_id": "asst_01j...",
    "company_id": "comp_01j...",
    "name": "Q1 Trade Show Follow-Up",
    "status": "draft",
    "call_window_start": "09:00",
    "call_window_end": "17:00",
    "call_window_timezone": "America/New_York",
    "max_concurrent_calls": 5,
    "total_contacts": 0,
    "contacts_called": 0,
    "contacts_completed": 0,
    "contacts_answered": 0,
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T10:00:00Z"
  }
}
```

***

## Add contacts to a campaign

`POST /api/crm/campaigns/{id}/contacts`

Adds one or more existing contacts to a campaign. Contacts must already exist in your CRM. Use the [contacts endpoints](/de/api-reference/contacts) to create them first if needed.

### Path parameters

<ParamField path="id" type="string" required>
  The campaign ID to add contacts to.
</ParamField>

### Request body

<ParamField body="contactIds" type="array" required>
  An array of contact ID strings to add to the campaign.
</ParamField>

### Example request

```bash theme={null}
curl -X POST https://<your-domain>/api/crm/campaigns/camp_01j.../contacts \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "contactIds": ["cont_01j...", "cont_02k...", "cont_03l..."]
  }'
```

### Antwort

```json theme={null}
{
  "success": true
}
```

***

## Start a campaign

`POST /api/crm/campaigns/{id}/run`

Initiates outbound calls for a campaign. Talkturo dials all contacts in `pending` or `queued` status, up to the campaign's `maxConcurrentCalls` limit. Use `dryRun: true` to preview which calls would be placed without actually dialing.

### Path parameters

<ParamField path="id" type="string" required>
  The campaign ID to start.
</ParamField>

### Request body

<ParamField body="accountSlug" type="string">
  Your account slug.
</ParamField>

<ParamField body="maxCalls" type="integer">
  Cap the number of calls started in this execution. Useful for gradual rollouts.
</ParamField>

<ParamField body="dryRun" type="boolean">
  When `true`, the API returns which calls would be started without actually placing them. Use this to verify campaign configuration before going live.
</ParamField>

### Example request

```bash theme={null}
curl -X POST https://<your-domain>/api/crm/campaigns/camp_01j.../run \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "accountSlug": "my-team",
    "maxCalls": 20
  }'
```

### Antwort

```json theme={null}
{
  "success": true,
  "started": 18,
  "failed": 2,
  "calls": [...],
  "errors": [
    "Contact cont_09x... has no phone number",
    "Contact cont_10y... is marked do-not-call"
  ],
  "message": "Started 18 calls",
  "dryRun": false
}
```

<ResponseField name="started" type="integer">
  Anzahl der erfolgreich initiierten Anrufe.
</ResponseField>

<ResponseField name="failed" type="integer">
  Anzahl der Kontakte, die in diesem Lauf nicht angerufen werden konnten.
</ResponseField>

<ResponseField name="calls" type="array">
  Array von Anrufobjekten für die gestarteten Anrufe.
</ResponseField>

<ResponseField name="errors" type="array">
  Array von Fehlermeldungszeichenfolgen, die beschreiben, warum einzelne Kontakte übersprungen wurden.
</ResponseField>

<ResponseField name="message" type="string">
  Für Menschen lesbare Zusammenfassung des Laufs.
</ResponseField>

<ResponseField name="dryRun" type="boolean">
  Spiegelt den „dryRun“-Wert Ihrer Anfrage wider.
</ResponseField>

## Lebenszyklus des Kampagnenstatus

| Status          | Beschreibung                                                             |
| --------------- | ------------------------------------------------------------------------ |
| „Entwurf“       | Kampagne erstellt, aber noch nicht gestartet                             |
| „geplant“       | Die Kampagne soll zu einem späteren Zeitpunkt „scheduledStartAt“ starten |
| „laufen“        | Es werden aktiv Anrufe getätigt                                          |
| `pausiert`      | Kampagne vorübergehend gestoppt; kann wieder aufgenommen werden          |
| „abgeschlossen“ | Alle Kontakte sind erreicht oder erschöpft                               |
| „abgesagt“      | Kampagne dauerhaft gestoppt                                              |
