3CX
Connectez un système téléphonique 3CX auto-hébergé à Aethex avec l'API de configuration 3CX et l'API Aethex. Votre agent vocal se connecte à 3CX comme l'un de ses utilisateurs, répond aux appels vers votre numéro et passe des appels via le trunk opérateur de votre 3CX.
Fonctionnement
Aethex se connecte à 3CX comme un poste de bureau : il se connecte à 3CX en tant qu'utilisateur, avec l'identifiant SIP de cet utilisateur. 3CX traite alors l'agent comme n'importe quel autre utilisateur. Les appels que 3CX route vers l'utilisateur arrivent à l'agent, et les appels que l'agent passe sortent par vos règles sortantes 3CX et votre trunk opérateur.La configuration comporte deux volets. Côté 3CX, vous créez l'utilisateur, autorisez la périphérie SIP Aethex et routez votre numéro vers l'utilisateur, avec l'API de configuration 3CX. Côté Aethex, vous créez une ligne qui se connecte à 3CX et attribuez le numéro à votre agent, avec l'API Aethex.Seul 3CX auto-hébergé permet cette configuration. Les éditions 3CX SMB et Hosted by 3CX ne la prennent pas en charge.
Avant de commencer
Chaque appel 3CX de ce guide utilise l'API de configuration 3CX, que 3CX inclut avec sa licence 8SC et supérieure avec IA.
| Ce qu'il vous faut | Où l'obtenir |
|---|---|
| 3CX v20 auto-hébergé, avec un nom d'hôte public et une adresse IPv4 publique fixe | Votre serveur 3CX. Aethex n'accepte pas les adresses privées. |
| Un client API 3CX avec accès à l'API de configuration | Console d'administration 3CX, Integrations > API > Add. Saisissez un Client ID, cochez Enable access to the 3CX Configuration API (XAPI), réglez Department sur System Wide et Role sur System Owner ou System Admin, puis enregistrez. 3CX n'affiche la clé API qu'une seule fois. |
| Un trunk opérateur dans 3CX qui reçoit le numéro qu'utilisera l'agent | Console d'administration 3CX, Voice & Chat. Ce guide écrit le numéro au format E.164, par exemple +15555550100. |
| Une clé API Aethex et un agent | Portail développeur, Clés API. La clé doit avoir les scopes sip_trunks:write, sip_trunks:read, phone_numbers:write et calls:write, qui couvrent les trunks, les numéros et les appels. |
Obtenir un jeton d'accès 3CX
Échangez le Client ID et la clé API contre un jeton d'accès sur POST /connect/token de votre serveur 3CX, puis envoyez le jeton dans un en-tête Bearer à chaque appel de l'API de configuration. Le jeton dure 60 minutes et 3CX ne délivre pas de jeton de rafraîchissement : demandez-en un nouveau quand il expire. Les chemins de l'API de configuration commencent par /xapi/v1.
PBX=https://pbx.example.com
TOKEN=$(curl -s -X POST "$PBX/connect/token" \
-d client_id=aethex-setup \
-d client_secret="$THREECX_API_KEY" \
-d grant_type=client_credentials | jq -r .access_token)
# Check the token works
curl -s -G "$PBX/xapi/v1/Defs" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode '$select=Id'Créer l'utilisateur 3CX de l'agent
Créez un utilisateur 3CX par agent. Demandez à 3CX le prochain numéro de poste libre, puis créez l'utilisateur avec ce numéro. Trois paramètres de la même requête comptent pour Aethex : PbxDeliversAudio fait passer l'audio de l'appel par 3CX, SRTPMode réglé sur SRTPEnabled active le chiffrement des médias (sans lui, les appels se connectent sans audio), et AuthID réglé sur le numéro de poste fait correspondre le nom de connexion à l'utilisateur.Relisez ensuite AuthID et AuthPassword. Ce sont le nom d'utilisateur et le mot de passe SIP avec lesquels Aethex se connecte à l'étape 6.
# 1. Ask 3CX for the next free extension number
curl -s "$PBX/xapi/v1/Users/Pbx.GetFirstAvailableExtensionNumber()" \
-H "Authorization: Bearer $TOKEN"
# { "Number": "120", ... }
# 2. Create the agent's user with that number
curl -s -X POST "$PBX/xapi/v1/Users" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Number": "120",
"FirstName": "Aethex",
"LastName": "Agent",
"AuthID": "120",
"PbxDeliversAudio": true,
"SRTPMode": "SRTPEnabled"
}'
# The response carries the new user's Id. Keep it as USER_ID.
# 3. Read the SIP login Aethex will use
curl -s -G "$PBX/xapi/v1/Users($USER_ID)" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode '$select=Number,AuthID,AuthPassword'Autoriser la périphérie SIP Aethex
3CX bloque une adresse après plusieurs échecs de connexion. Ajoutez les deux adresses de la périphérie SIP Aethex à la liste de blocage IP de 3CX en tant qu'entrées Allow, pour qu'un échec de connexion pendant la configuration ne fasse pas bloquer Aethex. C'est l'équivalent API de Advanced > IP Blacklist dans la console d'administration.
for ip in 13.63.135.167 51.21.123.34; do
curl -s -X POST "$PBX/xapi/v1/Blocklist" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{ \"IPAddrMask\": \"$ip\", \"BlockType\": \"Allow\", \"Description\": \"Aethex SIP edge\" }"
doneRouter votre numéro vers l'agent
Les appels vers votre numéro arrivent sur votre trunk opérateur. Ajoutez une règle entrante qui envoie les appels de ce numéro à l'utilisateur de l'agent, pendant et en dehors des heures d'ouverture. Listez d'abord vos trunks : mettez le Number du trunk dans TrunkDN, et le numéro exactement comme DidNumbers l'affiche dans Data. Remplacez 120 par le numéro de poste de l'étape 2.
# Find the carrier trunk and the number as 3CX stores it
curl -s -G "$PBX/xapi/v1/Trunks" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode '$select=Id,Number,DidNumbers'
# Send calls for that number to the agent's user, at all hours
curl -s -X POST "$PBX/xapi/v1/InboundRules" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"RuleName": "Aethex agent",
"Condition": "BasedOnDID",
"Data": "15555550100",
"TrunkDN": { "Number": "10000" },
"OfficeHoursDestination": { "To": "Extension", "Number": "120" },
"OutOfOfficeHoursDestination": { "To": "Extension", "Number": "120" }
}'Autoriser l'appel sortant pour l'agent
Ajoutez une règle sortante pour le poste de l'agent, sans préfixe ni limite de longueur de numéro, et routez-la vers votre trunk opérateur par l'Id du trunk. Le numéro présenté est par défaut celui du trunk.3CX applique la première règle qui correspond. Si une règle précédente couvre déjà le poste, ajoutez le poste aux DNRanges de cette règle avec PATCH /xapi/v1/OutboundRules(id), ou remontez la nouvelle règle avec POST /xapi/v1/OutboundRules/Pbx.MoveUpDown.
GET /xapi/v1/CountryCodes, ajoutez leurs indicatifs pays et renvoyez la liste complète avec PATCH /xapi/v1/CountryCodes.curl -s -X POST "$PBX/xapi/v1/OutboundRules" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Name": "Aethex agent",
"DNRanges": [{ "From": "120", "To": "120" }],
"Routes": [{ "TrunkId": 1 }]
}'
# Check the order: 3CX uses the first rule that matches the extension
curl -s -G "$PBX/xapi/v1/OutboundRules" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode '$select=Id,Name,Priority,DNRanges'Créer la ligne Aethex
Créez une ligne en mode register. Aethex se connecte à 3CX avec l'identifiant de l'utilisateur et maintient la connexion active, pour que 3CX puisse envoyer des appels à l'agent et accepter les siens. La réponse contient l'id de la ligne ; conservez-le pour les étapes 7 et 8. Le tableau explique chaque valeur.
| Champ | Valeur pour 3CX |
|---|---|
auth_mode | register : Aethex se connecte à 3CX comme un poste de bureau. Valide uniquement avec type réglé sur inbound ; Aethex ajoute lui-même le côté sortant. |
numbers | Votre numéro au format E.164. Une ligne register dessert exactement un numéro : créez donc une ligne par numéro. |
outbound_address | Le nom d'hôte de votre 3CX et son port SIP, généralement 5060. |
realm | 3CXPhoneSystem. 3CX répond au défi de connexion pour ce realm, pas pour son nom d'hôte. Sans lui, la ligne reste à failing. |
auth_username, auth_password | AuthID et AuthPassword de l'étape 2. Le mot de passe est stocké chiffré et n'est jamais renvoyé. |
allowed_addresses | L'adresse IPv4 publique de votre 3CX, comme seule entrée. Elle ouvre le pare-feu Aethex à votre 3CX. |
transport | udp ou tcp. Les lignes register ne prennent pas en charge TLS. |
outbound_dial_format | digits : Aethex envoie le numéro sans le + initial. 3CX modifie un numéro qui commence par +, et l'appel échoue alors avec « Number not found ». |
outbound_from_user | username : les appels sortants transmettent le nom de connexion comme utilisateur SIP From, ce qui permet à 3CX d'associer l'appel à l'utilisateur de l'agent. Le numéro passe dans P-Asserted-Identity. Avec la valeur par défaut, number, 3CX refuse les appels de l'agent comme appel entrant non identifié. |
name, numbers, allowed_addresses, outbound_dial_format, les limites d'appel et status. Pour changer l'adresse 3CX, le realm, l'identifiant, le transport, le chiffrement des médias ou outbound_from_user, supprimez la ligne et créez-en une nouvelle.curl -X POST https://api.aethexai.com/api/v1/sip-trunks \
-H "X-API-Key: $AETHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "3CX agent line",
"type": "inbound",
"auth_mode": "register",
"numbers": ["+15555550100"],
"outbound_address": "pbx.example.com:5060",
"realm": "3CXPhoneSystem",
"auth_username": "120",
"auth_password": "<AuthPassword from step 2>",
"allowed_addresses": ["203.0.113.10"],
"transport": "udp",
"outbound_dial_format": "digits",
"outbound_from_user": "username"
}'Attribuer le numéro à votre agent
Enregistrez le numéro avec la ligne et l'agent. agent_id fait répondre l'agent aux appels vers le numéro. Réglez outbound_enabled sur true : une ligne register passe ses appels par ce lien entre le numéro et la ligne.
curl -X POST https://api.aethexai.com/api/v1/phone-numbers/sip/register \
-H "X-API-Key: $AETHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+15555550100",
"trunk_id": "<id returned in step 6>",
"agent_id": "<your-agent-id>",
"outbound_enabled": true
}'Vérifier la connexion et tester les appels
Environ une minute après la création de la ligne, Aethex se connecte à 3CX. GET /sip-trunks/:id renvoie alors registration_status à registered, et 3CX renvoie l'utilisateur avec IsRegistered à true. Si la ligne affiche failing, consultez Dépannage ci-dessous.Pour tester l'entrant, appelez votre numéro depuis un téléphone extérieur à 3CX. L'agent répond, et l'appel apparaît dans Reports de 3CX et dans votre journal d'appels Aethex. Pour tester le sortant, déclenchez un appel avec votre numéro comme from_number. Le téléphone sonne, l'agent parle quand on décroche, et 3CX signale l'appel comme sortant.
# Aethex: the line logs in to 3CX within about a minute
curl -s https://api.aethexai.com/api/v1/sip-trunks/$TRUNK_ID \
-H "X-API-Key: $AETHEX_API_KEY" | jq .registration_status
# "registered"
# 3CX: the agent's user shows as registered
curl -s -G "$PBX/xapi/v1/Users($USER_ID)" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode '$select=Number,IsRegistered'
# Outbound: the agent calls a phone through 3CX
curl -X POST https://api.aethexai.com/api/v1/calls/trigger \
-H "X-API-Key: $AETHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "<your-agent-id>",
"to_number": "+15555550199",
"from_number": "+15555550100"
}'Réseau et pare-feu
Ouvrez ces ports entre votre 3CX et la périphérie SIP Aethex (sip.aethexai.com, aux adresses de l'étape 3). L'audio utilise G.711 loi A (PCMA) ou loi mu (PCMU). La plage de ports médias de votre 3CX se trouve sous Ports > Media dans le tableau de bord 3CX.
| Sens | Signalisation | Médias (RTP) |
|---|---|---|
| Aethex vers 3CX | TCP, UDP 5060 | UDP 9000–10999 (par défaut dans 3CX) |
| 3CX vers Aethex | TCP, UDP 5060 | UDP 10000–60000 |
Dépannage
Les problèmes les plus fréquents, leur cause et la solution.
| Symptôme | Cause | Solution |
|---|---|---|
La ligne reste à failing, et l'Event Log de 3CX affiche « Block WAN requests is ON » | Block remote non-tunnel connections est encore activé pour l'utilisateur. | Décochez-le dans l'onglet Options de l'utilisateur, dans la console d'administration (étape 2). |
La ligne reste à failing | Realm, identifiant ou mot de passe incorrect. | Recréez la ligne avec realm réglé sur 3CXPhoneSystem et les AuthID et AuthPassword de l'étape 2. |
| Les appelants tombent sur la messagerie vocale | Aethex n'est pas connecté en tant qu'utilisateur de l'agent. | Vérifiez que la ligne affiche registered et que l'utilisateur 3CX affiche IsRegistered (étape 8). |
| Les appels se connectent sans audio | Le SRTP est désactivé pour l'utilisateur, ou les ports médias sont fermés. | Réglez SRTPMode sur SRTPEnabled (étape 2) et ouvrez les ports indiqués dans Réseau et pare-feu. |
| Les appels sortants échouent, et l'Event Log de 3CX affiche « Unidentified Incoming Call » (appel entrant non identifié) | La ligne envoie le numéro comme appelant au lieu du nom de connexion. | Recréez la ligne avec outbound_from_user réglé sur username. |
| Les appels sortants échouent avec « Number not found » | Le numéro a été envoyé avec un + initial. | Réglez outbound_dial_format sur digits avec PATCH /sip-trunks/:id. |
| Les appels sortants échouent faute de règle sortante correspondante | Aucune règle sortante ne couvre le poste de l'agent, ou une règle précédente correspond en premier. | Ajoutez le poste à une règle qui route vers votre trunk opérateur (étape 5). |
