POST /v1/actions/create-contact
Upsert un contact par numéro de téléphone avec nom, email, tags et métadonnées optionnels.
Crée un contact, ou met à jour celui qui existe si un contact avec le même téléphone est déjà présent dans votre tenant. Renvoie 201 que la ligne ait été insérée ou mise à jour.
POST /api/v1/actions/create-contact
Corps de la requête
| Champ | Type | Requis | Notes |
|---|---|---|---|
phone |
string | oui | Format international avec +. Normalisé côté serveur. |
name |
string | non | Nom d'affichage |
email |
string | non | Doit être un email valide si fourni |
tags |
string | non | Liste séparée par des virgules, p. ex. "vip, beta-testers, fr-FR". Les tags sont créés à la volée s'ils n'existent pas. |
metadata |
object | non | JSON libre, max ~64 KB |
curl -X POST https://www.qyvo.io/api/v1/actions/create-contact \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"phone": "+14155550123",
"name": "Romain",
"email": "[email protected]",
"tags": "vip, fr-FR",
"metadata": { "shopify_id": "12345", "lifetime_value": 8742.00 }
}'
const contact = await fetch('https://www.qyvo.io/api/v1/actions/create-contact', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.QYVO_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone: '+14155550123',
name: 'Romain',
email: '[email protected]',
tags: 'vip, fr-FR',
metadata: { shopify_id: '12345', lifetime_value: 8742.0 },
}),
}).then((r) => r.json());
$contact = Http::withToken(env('QYVO_TOKEN'))
->post('https://www.qyvo.io/api/v1/actions/create-contact', [
'phone' => '+14155550123',
'name' => 'Romain',
'email' => '[email protected]',
'tags' => 'vip, fr-FR',
'metadata' => ['shopify_id' => '12345', 'lifetime_value' => 8742.0],
])
->json();
import os, httpx
contact = httpx.post(
'https://www.qyvo.io/api/v1/actions/create-contact',
headers={'Authorization': f"Bearer {os.environ['QYVO_TOKEN']}"},
json={
'phone': '+14155550123',
'name': 'Romain',
'email': '[email protected]',
'tags': 'vip, fr-FR',
'metadata': {'shopify_id': '12345', 'lifetime_value': 8742.0},
},
).json()
Réponse — 201 Created
{
"id": "01J1Y...",
"phone": "+14155550123",
"name": "Romain",
"email": "[email protected]",
"tags": ["vip", "fr-FR"],
"created_at": "2026-05-07T08:14:23+00:00"
}
Erreurs
| Statut | Cause |
|---|---|
422 |
Validation (phone manquant, email invalide, nom trop long) |
422 |
No workspace configured for this account. |
Idempotence
L'endpoint fait un upsert sur (tenant_id, phone) — l'appeler deux fois avec le même téléphone ne crée jamais deux contacts. Le second appel met à jour le nom, l'email, les métadonnées et les tags. Pour éviter d'écraser des champs que vous ne voulez pas changer, utilisez update-contact pour les mises à jour partielles.
