Einfache Ansagen-Kampagnen für automatisierte ausgehende Anrufe.
Nutzen Sie die 3CX Call Control API, um ausgehende Anrufkampagnen zu automatisieren. Verbinden Sie eine Liste von Telefonnummern mit einem IVR, spielen Sie eine automatisierte Nachricht ab und leiten Sie Anrufe basierend auf IVR-Menüauswahl an verschiedene Ziele weiter. Im Gegensatz zu herkömmlichen Outbound-Anrufen bietet diese Methode Flexibilität bei Messaging, Anrufweiterleitung und CRM- oder Datenbankintegration. Lesen Sie weiter, um mehr zu erfahren und die ersten Schritte zu unternehmen.
Wann Sie das Outbound Prompt-Kampagnenskript verwenden sollten

Ein perfektes Beispiel ist die Annullierung eines Fluges. Eine Fluggesellschaft kann Passagiere per Sprachnachricht benachrichtigen und ihnen Menüoptionen zur Verbindung mit dem Support anbieten.
Dies ist ein einfacher Anwendungsfall, der jedoch erweitert werden kann. Sie können ein individuelles IVR-System mit DTMF-Eingabe und Audio-Stream-Steuerung für Outbound-Kampagnen erstellen.
Weitere Beispiele finden Sie im offiziellen 3CX GitHub-Repository.
Einrichtung der Anrufbearbeitung und API-Integration
Erstellen Sie ein 3CX IVR, fügen Sie es zum Call Control API-Zugriff hinzu und wählen Sie es aus der Nebenstellenliste aus.
Anrufeinleitung
Die Client-Benutzeroberfläche verwendet einen einfachen Textbereich zur Eingabe einer durch Kommas getrennten Zahlenliste.
const destinations = source
.split(',')
.map((num) => num.trim())
.filter(Boolean);
Eine Warteschleifenstruktur verarbeitet die Anrufe einzeln. Unbeantwortete oder besetzte Anrufe können zur erneuten Wahl in die Warteschlange gestellt werden.
destinations.forEach((destNumber) => this.callQueue.enqueue(destNumber));
Aufruflogik
Die folgende Funktion ruft die erste Nummer aus der Warteschleife ab und beginnt mit der Verarbeitung.
public async makeCallsToDst() {
if (this.callQueue.isEmpty()) return;
const destNumber = this.callQueue.dequeue();
// …
Vor dem Wählen überprüft das System die PBX-Verbindung und stellt sicher, dass die Quellnebenstelle nicht verwendet wird.
if (!this.sourceDn || !this.externalApiSvc.connected) {
if (destNumber)
this.failedCalls.push({
callerId: destNumber,
reason: NO_SOURCE_OR_DISCONNECTED,
});
return;
}
const participants = this.getParticipantsOfDn(this.sourceDn);
if (participants && participants.size > 0) {
if (destNumber)
this.failedCalls.push({
callerId: destNumber,
reason: CAMPAIGN_SOURCE_BUSY,
});
return;
}
//…
Einen Anruf tätigen
Der Anruf wird über das erste verfügbare Gerät getätigt.
Die Liste der verfügbaren Geräte für eine bestimmte DN finden Sie im Status der Anrufsteuerung.
try {
const source = this.fullInfo?.callcontrol.get(this.sourceDn);
const device: DNDevice | undefined = source?.devices?.values().next().value;
if (!device?.device_id) {
throw new BadRequest('Devices not found');
}
const response = await this.externalApiSvc.makeCallFromDevice(
this.sourceDn,
encodeURIComponent(device.device_id),
destNumber,
);
//…
Die Methode makeCallFromDevice verwendet diesen Endpunkt:
public makeCallFromDevice(source: string, deviceId: string, dest: string) {
const url = '/callcontrol' + `/${source}` + '/devices' + `/${deviceId}` + '/makecall';
return this.fetch!.post(
url,
{
destination: dest,
},
{
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
},
);
}
Error Handling
Wenn die TK-Anlage die Anfrage akzeptiert, wird die Anruf-ID gespeichert. Andernfalls wird ein Fehler protokolliert.
if (response.data.result?.id) {
this.incomingCallsParticipants.set(response.data.result.id, response.data.result);
} else {
this.failedCalls.push({
callerId: destNumber!,
reason: response?.data?.reasontext || UNKNOWN_CALL_ERROR,
});
}
//…
Fehler zwischen Anwendung und PBX werden hier behandelt:
//...
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
this.failedCalls.push({
callerId: destNumber!,
reason: error.response?.data.reasontext || UNKNOWN_CALL_ERROR,
});
} else {
this.failedCalls.push({
callerId: destNumber!,
reason: UNKNOWN_CALL_ERROR,
});
}
}
Teilnehmerereignisbehandlung
Eine WebSocket-Verbindung verfolgt den IVR-Status, startet neue Anrufe und verwaltet Teilnehmer.
Weitere Informationen zur WebSocket-Ereignisstruktur und anderen damit verbundenen Aspekten finden Sie in dieser Anleitung.
private wsEventHandler = (json: string) => {
try {
const wsEvent: WSEvent = JSON.parse(json);
if (!this.externalApiSvc.connected || !wsEvent?.event?.entity) {
return;
}
const { dn, type } = determineOperation(wsEvent.event.entity);
//...
Wenn ein Update erfolgt, ruft die Anwendung neue Daten ab und speichert sie.
case EventType.Upset:
{
this.externalApiSvc
.requestUpdatedEntityFromWebhookEvent(wsEvent)
.then((res) => {
const data = res.data;
set(this.fullInfo, wsEvent.event.entity, data); // update local state
if (dn === this.sourceDn) {
if (type === PARTICIPANT_TYPE_UPDATE) {
/**
* handle here update of participants
*/
}
}
})
.catch((err) => {
if (axios.isAxiosError(err)) {
console.error(`AXIOS ERROR code: ${err.response?.status}`);
} else console.error('Unknown error', err);
});
}
break;
Wir können diese URL verwenden, um die aktualisierte Entität anzufordern und eine inkrementelle Statusaktualisierung für unsere Anwendung durchzuführen (siehe DN-Aktualisierungsanforderung):
public requestUpdatedEntityFromWebhookEvent(ws: WSEvent) {
return this.fetch.get(ws.event.entity);
}
Wenn ein Teilnehmer entfernt wird, wird die Kampagne fortgesetzt.
case EventType.Remove: {
const removed = set(this.fullInfo, wsEvent.event.entity, undefined);
if (dn === this.sourceDn) { // update related to our campaign handler
if (type === PARTICIPANT_TYPE_UPDATE) {// update related to call participant
/**
* handle here removed participants
*/
if (removed?.id) {
//...
if (!participants || participants?.size < 1) { // Handler is free
this.makeCallsToDst(); // continue with campaign
}
}
}
}
}
Wir können diesen Ereignishandler innerhalb des WebSocket-Ereignislisteners verwenden.
ws.on('message', (buffer) => {
const message = decoder.decode(buffer as Buffer);
wsEventHandler(message);
});
Weitere Call Flow-Skripte verfügbar
Auf unserer Website finden Sie eine Sammlung von Call-Flow-Skripten. Sehen Sie sich diese an und erfahren Sie, wie Sie 3CX entsprechend Ihren Anforderungen automatisieren können.



