Points de terminaison CRM
Connecte WAzion à ton CRM ou ERP externe pour que l’IA et le panneau latéral accèdent aux données des clients, des commandes et des produits de ton système.
Qu’est-ce que les Endpoints CRM ?
Les endpoints CRM permettent à WAzion de consulter les informations de votre système externe (CRM, ERP, base de données propre). Contrairement aux Fonctions IA (que l’IA décide quand appeler), ces endpoints sont appelés automatiquement lorsque l’agent ouvre une conversation ou recherche des informations.
Pour le panneau latéral
Affiche les données du client à côté de la conversation (commandes, historique, informations de contact).
Pour l’IA
Fournir un contexte initial sur le client afin que l’IA réponde avec des informations pertinentes.
1 sidePanel_CustomerInfo
Fournit les informations du client affichées dans le panneau latéral de l’extension lorsque l’agent ouvre une conversation.
Paramètres envoyés
| phone | Téléphone du client (E.164) |
| token | Jeton d’authentification |
| relatedphones | Téléphones associés (tableau) |
Réponse attendue
{
"found": true,
"customers": [
{
"name": "Juan García",
"email": "juan@email.com",
"phone": "+34612345678",
"shopUrl": "https://tucrm.com/c/123",
"ordersCount": 5,
"totalSpent": 450.00,
"totalRefunded": 0,
"state": "VIP - Activo",
"orders": [...],
"abandonedCarts": [...]
}
]
}
Note : Vous pouvez utiliser “customer“ (objet) ou “customers“ (tableau) pour supporter plusieurs clients. Retourne TOUJOURS HTTP 200, même si aucun client n’est trouvé (utilisez “found“: false).
📦 Voir la structure complète de la réponse (commandes, articles, suivi, paniers abandonnés)
Structure JSON complète avec tous les champs pris en charge :
{
"found": true,
"customers": [
{
"// Datos básicos del cliente"
"name": "Juan García López",
"email": "juan@email.com",
"phone": "+34612345678",
"shopUrl": "https://tu-crm.com/clientes/123",
"ordersCount": 15,
"totalSpent": 1250.50,
"totalRefunded": 50.00,
"totalDiscounts": 25.00,
"state": "Cliente VIP",
"// Array de pedidos"
"orders": [
{
"name": "#ORD-2025-001",
"date": "2025-01-10T14:30:00Z",
"amount": 129.99,
"netAmount": 104.99,
"totalRefunded": 25.00,
"totalDiscounts": 10.00,
"currency": "EUR",
"cancelled": false,
"shopUrl": "https://tu-crm.com/pedidos/1234",
"note": "Entregar por la tarde",
"// Items del pedido"
"items": [
{
"title": "Camiseta Premium Azul - Talla L",
"quantity": 2,
"currentQuantity": 2,
"amount": 59.98,
"originalAmount": 59.98,
"discountedAmount": 59.98,
"discount": 0,
"refundedQuantity": 0,
"refundedAmount": 0,
"status": "active" // active | partially_refunded | fully_refunded
}
],
"// Tracking de envíos"
"tracking": [
{
"number": "ES123456789012",
"company": "SEUR",
"url": "https://www.seur.com/tracking/...",
"displayStatus": "Entregado"
}
]
}
],
"// Carritos abandonados"
"abandonedCarts": [
{
"date": "2025-01-14T18:45:00Z",
"url": "https://tu-tienda.com/cart/recover/abc123",
"items": [
{
"title": "Zapatillas Running Pro",
"quantity": 1,
"amount": 129.99
}
]
}
]
}
]
}
Champs du client :
| Champ | Type | Requis |
|---|---|---|
| name | string | Oui |
| string | Oui | |
| phone | string | Oui |
| shopUrl | string | No |
| ordersCount | number | Oui |
| totalSpent | number | Oui |
| totalRefunded | number | No |
| totalDiscounts | number | No |
| state | string | Oui |
| orders | array | No |
| abandonedCarts | array | No |
Champs de la commande (order) :
| Champ | Type | Description |
|---|---|---|
| name | string | ID/Numéro de commande |
| date | string | Date ISO 8601 |
| amount | number | Total de la commande |
| netAmount | number | Montant net (après remboursements) |
| currency | string | Code de devise (EUR, USD...) |
| cancelled | boolean | vrai s’il est annulé |
| shopUrl | string | URL vers la commande dans votre système |
| note | string | Note de commande |
| items | array | Produits de la commande |
| tracking | array | Envois/suivi |
Champs de l’article :
| Champ | Type | Description |
|---|---|---|
| title | string | Nom du produit |
| quantity | number | Quantité commandée |
| currentQuantity | number | Quantité actuelle (après remboursements) |
| amount | number | Prix total de l’article |
| refundedQuantity | number | Unités remboursées |
| refundedAmount | number | Montant remboursé |
| status | string | active | partially_refunded | fully_refunded |
Champs du suivi :
| Champ | Type | Description |
|---|---|---|
| number | string | Numéro de suivi |
| company | string | Entreprise de livraison |
| url | string | URL de suivi |
| displayStatus | string | État lisible (Livré, En transit...) |
Étiquettes de traduction (UI)
Pour que l’extension affiche les textes dans la langue correcte, incluez l’objet “labels“ avec les traductions :
{
"found": true,
"customer": { ... },
"labels": {
"label_languages": "es",
"customer_info": "Información del Cliente",
"name": "Nombre",
"email": "Email",
...
}
}
Voir le tableau complet des étiquettes disponibles
| Key | Default (ES) | Description |
|---|---|---|
| label_languages | "es" | Langue des étiquettes. Si elle diffère de la langue de la boutique, WAzion les traduit automatiquement |
| customer_info | "Información del Cliente" | Titre section client |
| name | "Nombre" | Étiquette nom |
| "Email" | Étiquette email | |
| phone | "Teléfono" | Étiquette téléphone |
| orders_count | "Pedidos" | Compteur de commandes |
| total_spent | "Total gastado" | Total dépensé |
| total_refunded | "Total reembolsado" | Remboursements |
| discounts | "Descuentos" | Rabais |
| customer_state | "Estado" | État du client |
| recent_orders | "Pedidos recientes" | Titre commandes |
| order | "Pedido" | Commande individuelle |
| orders | "Pedidos" | Commandes |
| order_number | "Nº de pedido" | Numéro de commande |
| date | "Fecha" | Date |
| amount | "Importe" | Montant |
| net_amount | "Importe neto" | Montant net |
| subtotal | "Subtotal" | Sous-total |
| discount | "Descuento" | Remise individuelle |
| refund | "Reembolso" | Remboursement |
| refunded | "Reembolsado" | Badge remboursé |
| cancelled | "Cancelado" | Badge annulé |
| cancel_reason | "Motivo cancelación" | Motif d’annulation |
| items | "Artículos" | Produits/Articles |
| item_status | "Estado artículo" | État de l’article |
| quantity | "Cantidad" | Quantité |
| original_quantity | "Cantidad original" | Quantité originale |
| current_quantity | "Cantidad actual" | Quantité actuelle |
| sku | "SKU" | SKU |
| shipments | "Envíos" | Expéditions |
| shipping | "Envío" | Envoi individuel |
| tracking_number | "Nº seguimiento" | Numéro de suivi |
| no_shipping_info | "Sin información de envío" | Sans livraison |
| order_note | "Nota del pedido" | Notes de commande |
| fully_refunded | "Reembolsado completamente" | Article remboursé à 100 % |
| partially_refunded | "Reembolsado parcialmente" | Article partiellement remboursé |
| active | "Activo" | État actif |
| abandoned_carts | "Carrito/s abandonado/s" | Chariots abandonnés |
| copy_link | "Copiar enlace" | Bouton copier |
| view_customer | "Ver perfil del cliente" | Bouton voir client |
| view_profile | "Ver perfil" | Bouton voir le profil |
| remove_assignment | "Quitar asignación" | Bouton de dissociation |
| not_found | "Cliente no encontrado" | Message non trouvé |
| no_orders | "Sin pedidos" | Sans commandes |
| error | "Error" | Préfixe d’erreur |
| États du client | ||
| state_no_orders | "Sin pedidos" | Statut : sans commandes |
| state_conflictive | "Conflictivo" | Statut : conflictuel |
| state_processing | "Procesando" | État : en cours de traitement |
| state_new_orders | "Pedidos nuevos" | Statut : nouvelles commandes |
| state_recent_orders | "Pedidos recientes" | État : commandes récentes |
| state_old_orders | "Pedidos antiguos" | Statut : commandes anciennes |
Traduction automatique : Si vous envoyez des étiquettes dans une langue (ex : anglais avec label_languages : “en“) et que la boutique est configurée dans une autre (ex : espagnol), WAzion traduira automatiquement toutes les étiquettes. Cela vous permet de maintenir votre CRM dans une seule langue.
2 ai_CustomerInitialInfo
Fournir un contexte initial sur le client à l’IA. Ce texte est inclus dans l’invite de l’IA afin qu’elle puisse répondre avec des informations pertinentes sur le client.
Paramètres envoyés
| phone | Téléphone du client (E.164) |
| token | Jeton d’authentification |
| relatedphones | Téléphones associés (tableau) |
| order | Numéro de commande mentionné (optionnel) |
| Email du client (facultatif) | |
| test | true“ si c’est un test |
Réponse attendue
{
"found": true,
"info": "Cliente: Juan García.
VIP: Sí. Total pedidos: 5.
Último pedido: #12345 (15/01/2024)
Estado: Entregado.
Productos frecuentes: Zapatos, Camisetas.
ALERTA: Cliente alérgico al gluten."
}
Important : Le champ “info“ est un texte libre que l’IA lira comme contexte. Il inclut l’historique des achats, les préférences, les alertes importantes (allergies, problèmes antérieurs), l’état du client, le mode de paiement/livraison préféré, etc.
3 sidePanel_CustomerFindToJoin
Permet de rechercher des clients dans votre système pour les lier à une conversation WhatsApp. Utile lorsque le client écrit depuis un numéro différent de celui enregistré.
Paramètres envoyés
| query | Texte de recherche |
| token | Jeton d’authentification |
| phone | Numéro de téléphone actuel de la conversation |
| relatedphones | Téléphones déjà liés (tableau, pour les exclure) |
Réponse attendue
{
"customers": [
{
"id": "cust_123",
"name": "Juan García",
"email": "juan@email.com",
"phone": "+34612345678"
},
{
"id": "cust_456",
"name": "Juan Martínez",
"email": "juanm@email.com",
"phone": "+34687654321"
}
]
}
Note : Vous pouvez utiliser “customers“ ou “results“ comme nom du tableau. Le champ “phone“ de chaque client permet à WAzion de lier automatiquement la conversation.
4 search_Products
Permet de rechercher des produits dans votre catalogue externe. Les résultats s’affichent dans le panneau latéral et l’agent peut les partager avec le client. L’IA peut également rechercher des produits pour répondre aux questions.
Note pour CRM Custom : WAzion agit comme un proxy transparent pour ce point de terminaison. La réponse de votre CRM est renvoyée directement à l’extension sans modification. Vous devez implémenter la structure complète documentée si vous souhaitez profiter de toutes les fonctionnalités. Les champs enrichis (target_locale, title_copy, raw, etc.) ne sont générés automatiquement que pour les boutiques Shopify.
Paramètres envoyés
| Paramètre | Type | Description |
|---|---|---|
| q | string | Texte de recherche (minimum 2 caractères) |
| token | string | Jeton d’authentification de la boutique |
| phone | string | Numéro de téléphone du client (E.164) - pour les URL localisées par pays |
| format | string | ai“ quand l’IA recherche des produits (change la structure de la réponse) |
| target_locale | string | Langue détectée du client en fonction de son téléphone (ex : “es“, “de“, “fr“) |
| test | boolean | vrai“ si c’est un test de connexion |
Nouveau : cible_locale - WAzion détecte automatiquement la langue du client en se basant sur le préfixe de son téléphone. Par exemple, +34... → “es“, +49... → “de“. Utilisez ce paramètre pour retourner les produits dans la bonne langue.
Réponse format NORMAL (panneau latéral)
Lorsque l’agent recherche des produits depuis le panneau. Inclut des champs pour copier/partager.
{
"http_status": 200,
"count": 1,
"products": [
{
"title": "Camiseta Premium",
"title_copy": "Premium T-Shirt",
"handle": "camiseta-premium",
"description": "Descripción truncada a 500 chars...",
"sku": "CAM-001",
"image": "https://proxy/imagen.jpg",
"url": "https://tutienda.es/products/camiseta-premium",
"variants": [
{
"id": "12345678",
"title": "M / Rojo",
"title_copy": "M / Red",
"has_custom_title": true,
"sku": "CAM-001-M-RED",
"image": "https://proxy/variante.jpg",
"url": "https://tutienda.es/products/camiseta-premium?variant=12345678"
}
]
}
],
"target_locale": "en",
"raw": { ... }
}
Réponse format IA (lorsque format=“ai“)
Lorsque l’IA cherche des produits. Structure simplifiée sans champs de copie, description complète.
{
"count": 1,
"products": [
{
"title": "Premium T-Shirt",
"handle": "camiseta-premium",
"description": "Descripción COMPLETA sin truncar para contexto IA...",
"sku": "CAM-001",
"url": "https://tutienda.es/products/camiseta-premium",
"variants": [
{
"id": "12345678",
"title": "M / Red",
"sku": "CAM-001-M-RED",
"url": "https://tutienda.es/products/camiseta-premium?variant=12345678"
}
]
}
],
"locale": "en"
}
Voir tous les champs du produit
| Champ | Normal | IA | Description |
|---|---|---|---|
| title | Original | Traduit | Titre du produit |
| title_copy | Traduit | - | Titre à copier (langue du client) |
| handle | ✓ | ✓ | Slug du produit |
| description | 500 caractères | Complète | Description (HTML nettoyé) |
| sku | ✓ | ✓ | SKU de la première variante |
| image | ✓ | - | URL de l’image (peut être proxy) |
| url | ✓ | ✓ | URL localisée du produit |
| variants | ✓ | ✓ | Tableau de variantes |
Voir les champs de chaque variante
| Champ | Normal | IA | Description |
|---|---|---|---|
| id | ✓ | ✓ | ID de la variante |
| title | Original | Traduit | Titre de la variante (ex : “M / Rouge“) |
| title_copy | Traduit | - | Titre à copier (langue du client) |
| has_custom_title | ✓ | - | true s’il a un titre personnalisé (pas “Titre par défaut“) |
| sku | ✓ | ✓ | SKU de la variante |
| image | ✓ | - | Image spécifique de la variante (ou du produit si elle n’en a pas) |
| url | ✓ | ✓ | URL avec ?variant=ID |
Voir les champs de la réponse racine
| Champ | Normal | IA | Description |
|---|---|---|---|
| http_status | ✓ | - | Code HTTP de la réponse |
| count | ✓ | ✓ | Nombre de produits trouvés |
| products | ✓ | ✓ | Tableau de produits |
| target_locale | ✓ | - | Paramètre régional utilisé pour les traductions |
| locale | - | ✓ | Locale utilisé (format AI uniquement) |
| raw | ✓ | - | Réponse brute de la source (debug) |
🌍 URLs localisées par pays
Le paramètre phone contient le téléphone du client (E.164). Utilisez-le pour détecter son pays et renvoyer des URL adaptées :
- Domaines spécifiques par pays (tutienda.es, tutienda.de, tutienda.fr)
- Itinéraires avec préfixe de langue (/es/, /de/, /fr/)
- Paramètres de locale (?locale=es_ES)
- Marchés spécifiques de Shopify
Exemple : Si le téléphone commence par +34 (Espagne), retourner les URL avec un domaine .es ou /es/.
5 globalSearch
Recherche mondiale de clients pour le moteur de recherche flottant de l’extension. Permet de rechercher par nom, email, téléphone ou numéro de commande.
Paramètres envoyés
| Paramètre | Type | Description |
|---|---|---|
| query | string | Texte de recherche (minimum 2 caractères) |
| token | string | Jeton d’authentification de la boutique |
Réponse attendue
{
"found": true,
"customers": [
{
"id": "cust_123",
"name": "Juan García López",
"email": "juan.garcia@email.com",
"phone": "+34612345678",
"customerUrl": "https://tucrm.com/clientes/123",
"orders": [
{
"number": "#ORD-1234",
"url": "https://tucrm.com/pedidos/1234"
},
{
"number": "#ORD-1233",
"url": "https://tucrm.com/pedidos/1233"
}
]
}
]
}
Champs de chaque client
| Champ | Type | Requis | Description |
|---|---|---|---|
| id | string | Oui | Identifiant unique du client dans votre système |
| name | string | Oui | Nom complet du client |
| string | Oui | E-mail du client | |
| phone | string | Oui | Téléphone du client (E.164 préféré, ex : +34612345678) |
| customerUrl | string | Non | URL pour voir le client dans votre CRM (affiché comme lien cliquable) |
| orders | array | Non | Tableau avec les dernières commandes (maximum 3) |
Champs de chaque commande (orders[])
| Champ | Type | Requis | Description |
|---|---|---|---|
| number | string | Oui | Numéro de commande (ex : “#ORD-1234“) |
| url | string | Non | URL pour voir la commande dans ton système |
Notes importantes
- • Le champ
phoneest obligatoire pour que l’agent puisse ouvrir la conversation avec ce client. - • Un maximum de 15 résultats seront affichés à l’utilisateur (limité automatiquement).
- • Les doublons par téléphone sont supprimés automatiquement.
- • Si
customerUrlest présent, le nom du client sera un lien cliquable. - • Les commandes sont affichées sous forme de liens individuels sous le client.
Spécifications techniques
Délai d’attente
| globalSearch | 5s |
| Autres points de terminaison | 10s |
| Délai de connexion dépassé | 5s |
| Tentatives répétées | Non |
Méthodes HTTP
| Configurable | GET / POST |
| Corps (POST) | JSON / Form |
| Paramètres (GET) | Query string |
Exigences
- HTTPS obligatoire
- Réponse JSON valide
- HTTP 200 toujours (utiliser found:false s’il n’y a pas de données)
Différence avec les Fonctions IA
Les points de terminaison CRM ne réessayent pas automatiquement en cas d’échec. Ils sont appelés en temps réel pendant que l’agent travaille, donc ils doivent répondre rapidement. En cas d’échec, l’information n’apparaît tout simplement pas.
Types d’authentification
Exemple d’URL (GET + authentification par requête)
// WAzion llamará:
https://tu-api.com/customer
?phone=+34612345678
&token=tu-token-secreto
&relatedphones=["+34698765432"]
&test=false
Exemples de mise en œuvre
<?php
// Endpoint: /api/customer-info
header('Content-Type: application/json');
// Obtener parámetros (soporta GET y POST)
$input = json_decode(file_get_contents('php://input'), true) ?? $_GET;
$phone = $input['phone'] ?? '';
$token = $input['token'] ?? '';
$relatedPhones = $input['relatedphones'] ?? [];
$order = $input['order'] ?? '';
$isTest = ($input['test'] ?? '') === 'true';
// Verificar token
if ($token !== 'tu-token-secreto') {
echo json_encode(['found' => false, 'error' => 'No autorizado']);
exit;
}
// Si es test, devolver datos de ejemplo
if ($isTest) {
echo json_encode([
'found' => true,
'customers' => [[
'name' => 'Cliente de Prueba',
'email' => 'test@example.com',
'phone' => '+34612345678',
'shopUrl' => 'https://tucrm.com/cliente/123',
'ordersCount' => 3,
'totalSpent' => 150.00,
'state' => 'Activo',
'orders' => []
]]
]);
exit;
}
// Buscar por teléfono principal + relacionados
$allPhones = array_merge([$phone], $relatedPhones);
$customers = buscarClientesPorTelefonos($allPhones);
echo json_encode([
'found' => !empty($customers),
'customers' => $customers
]);
const express = require('express');
const app = express();
app.use(express.json());
const SECRET_TOKEN = 'tu-token-secreto';
app.all('/api/customer-info', async (req, res) => {
// Soporta GET y POST
const params = { ...req.query, ...req.body };
const { phone, token, relatedphones = [], order, test } = params;
// Verificar token
if (token !== SECRET_TOKEN) {
return res.json({ found: false, error: 'No autorizado' });
}
// Datos de test
if (test === 'true') {
return res.json({
found: true,
customers: [{
name: 'Cliente de Prueba',
email: 'test@example.com',
phone: '+34612345678',
shopUrl: 'https://tucrm.com/cliente/123',
ordersCount: 3,
totalSpent: 150.00,
state: 'Activo',
orders: []
}]
});
}
// Buscar clientes
const allPhones = [phone, ...relatedphones];
const customers = await buscarClientesPorTelefonos(allPhones);
res.json({ found: customers.length > 0, customers });
});
app.listen(3000);
from flask import Flask, request, jsonify
app = Flask(__name__)
SECRET_TOKEN = 'tu-token-secreto'
@app.route('/api/customer-info', methods=['GET', 'POST'])
def customer_info():
# Soporta GET y POST
params = {**request.args, **request.get_json(silent=True) or {}}
phone = params.get('phone', '')
token = params.get('token', '')
related_phones = params.get('relatedphones', [])
is_test = params.get('test') == 'true'
# Verificar token
if token != SECRET_TOKEN:
return jsonify({'found': False, 'error': 'No autorizado'})
# Datos de test
if is_test:
return jsonify({
'found': True,
'customers': [{
'name': 'Cliente de Prueba',
'email': 'test@example.com',
'phone': '+34612345678',
'shopUrl': 'https://tucrm.com/cliente/123',
'ordersCount': 3,
'totalSpent': 150.00,
'state': 'Activo',
'orders': []
}]
})
# Buscar clientes
all_phones = [phone] + related_phones
customers = buscar_clientes_por_telefonos(all_phones)
return jsonify({'found': len(customers) > 0, 'customers': customers})
Historique des modifications
sidePanel_CustomerInfo traduit désormais automatiquement toutes les étiquettes si label_languages diffère de la langue de la boutique. Vous pouvez garder votre CRM dans une seule langue (ex : anglais) et WAzion se charge des traductions.
WAzion envoie désormais la langue détectée du client (basée sur le préfixe de son téléphone) comme paramètre target_locale. Utile pour renvoyer les produits dans la bonne langue du client.