Créer un dossier depuis un formulaire
Ce guide vous montre comment créer un dossier bénéficiaire dans téo à partir d'un formulaire web (site internet, landing page, etc.).
Cas d'usage
Vous souhaitez :
- Permettre aux visiteurs de votre site de s'inscrire à une formation
- Automatiser la création de dossiers depuis un CRM externe
- Intégrer téo avec un outil de marketing automation
Prérequis
- Vos identifiants API (voir Authentification)
- L'UUID de la prestation cible (voir Identifiants)
Vue d'ensemble
N'exposez jamais vos identifiants API côté client (JavaScript navigateur). Utilisez toujours un backend pour communiquer avec l'API téo.
Étape 1 : Collecter les données
Créez un formulaire avec les champs nécessaires. Voici les champs minimums pour créer un dossier :
<form action="/api/inscription" method="POST">
<input type="text" name="firstName" placeholder="Prénom" required />
<input type="text" name="lastName" placeholder="Nom" required />
<input type="email" name="email" placeholder="Email" required />
<input type="tel" name="phone" placeholder="Téléphone" />
<!-- Prestation cachée ou en select -->
<input type="hidden" name="serviceId" value="UUID_DE_LA_PRESTATION" />
<button type="submit">S'inscrire</button>
</form>
Étape 2 : Traiter les données côté serveur
Exemple Node.js (Express)
const express = require('express');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Configuration
const TEO_API = 'https://teoapp.fr/api';
const CLIENT_ID = process.env.TEO_CLIENT_ID;
const CLIENT_SECRET = process.env.TEO_CLIENT_SECRET;
const TEO_ID = process.env.TEO_ID;
// Cache du token
let tokenCache = { token: null, expiresAt: 0 };
async function getAccessToken() {
// Réutiliser le token s'il est encore valide
if (tokenCache.token && Date.now() < tokenCache.expiresAt) {
return tokenCache.token;
}
const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
const response = await fetch('https://auth.teoapp.fr/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${credentials}`
},
body: `grant_type=client_credentials&scope=target-entity:${TEO_ID}`
});
const data = await response.json();
// Mettre en cache (expire 1 minute avant pour éviter les erreurs)
tokenCache = {
token: data.access_token,
expiresAt: Date.now() + (data.expires_in - 60) * 1000
};
return data.access_token;
}
app.post('/api/inscription', async (req, res) => {
try {
const { firstName, lastName, email, phone, serviceId } = req.body;
// Validation basique
if (!firstName || !lastName || !email || !serviceId) {
return res.status(400).json({ error: 'Champs obligatoires manquants' });
}
const token = await getAccessToken();
// Créer le dossier dans téo
const response = await fetch(`${TEO_API}/production/dossiers`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'Accept': 'application/ld+json'
},
body: JSON.stringify({
firstName,
lastName,
email,
phone: phone || null,
service: `/api/production/services/${serviceId}`
})
});
if (!response.ok) {
const error = await response.json();
console.error('Erreur API téo:', error);
return res.status(response.status).json({
error: 'Erreur lors de la création du dossier',
details: error
});
}
const dossier = await response.json();
res.json({
success: true,
message: 'Inscription enregistrée',
dossierId: dossier.id
});
} catch (error) {
console.error('Erreur serveur:', error);
res.status(500).json({ error: 'Erreur interne' });
}
});
app.listen(3000);
Exemple PHP
<?php
// Configuration
define('TEO_API', 'https://teoapp.fr/api');
define('CLIENT_ID', getenv('TEO_CLIENT_ID'));
define('CLIENT_SECRET', getenv('TEO_CLIENT_SECRET'));
define('TEO_ID', getenv('TEO_ID'));
// Cache simple en session (utilisez Redis/Memcached en production)
session_start();
function getAccessToken(): string
{
// Vérifier le cache
if (isset($_SESSION['teo_token']) && $_SESSION['teo_token_expires'] > time()) {
return $_SESSION['teo_token'];
}
$credentials = base64_encode(CLIENT_ID . ':' . CLIENT_SECRET);
$ch = curl_init('https://auth.teoapp.fr/oauth2/token');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
"Authorization: Basic $credentials"
],
CURLOPT_POSTFIELDS => 'grant_type=client_credentials&scope=target-entity:' . TEO_ID
]);
$response = json_decode(curl_exec($ch));
curl_close($ch);
// Mettre en cache
$_SESSION['teo_token'] = $response->access_token;
$_SESSION['teo_token_expires'] = time() + $response->expires_in - 60;
return $response->access_token;
}
function createDossier(array $data): array
{
$token = getAccessToken();
$ch = curl_init(TEO_API . '/production/dossiers');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $token",
'Content-Type: application/json',
'Accept: application/ld+json'
],
CURLOPT_POSTFIELDS => json_encode($data)
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [
'success' => $httpCode === 201,
'code' => $httpCode,
'data' => json_decode($response, true)
];
}
// Traitement du formulaire
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$firstName = trim($_POST['firstName'] ?? '');
$lastName = trim($_POST['lastName'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$serviceId = $_POST['serviceId'] ?? '';
// Validation
if (empty($firstName) || empty($lastName) || empty($email) || empty($serviceId)) {
http_response_code(400);
echo json_encode(['error' => 'Champs obligatoires manquants']);
exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
http_response_code(400);
echo json_encode(['error' => 'Email invalide']);
exit;
}
// Créer le dossier
$result = createDossier([
'firstName' => $firstName,
'lastName' => $lastName,
'email' => $email,
'phone' => $phone ?: null,
'service' => "/api/production/services/$serviceId"
]);
if ($result['success']) {
echo json_encode([
'success' => true,
'message' => 'Inscription enregistrée',
'dossierId' => $result['data']['id']
]);
} else {
http_response_code($result['code']);
echo json_encode([
'error' => 'Erreur lors de la création',
'details' => $result['data']
]);
}
}
Exemple Python (Flask)
import os
import time
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
# Configuration
TEO_API = 'https://teoapp.fr/api'
CLIENT_ID = os.environ['TEO_CLIENT_ID']
CLIENT_SECRET = os.environ['TEO_CLIENT_SECRET']
TEO_ID = os.environ['TEO_ID']
# Cache du token
token_cache = {'token': None, 'expires_at': 0}
def get_access_token():
global token_cache
# Réutiliser le token s'il est encore valide
if token_cache['token'] and time.time() < token_cache['expires_at']:
return token_cache['token']
import base64
credentials = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
response = requests.post(
'https://auth.teoapp.fr/oauth2/token',
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': f'Basic {credentials}'
},
data=f'grant_type=client_credentials&scope=target-entity:{TEO_ID}'
)
data = response.json()
# Mettre en cache
token_cache = {
'token': data['access_token'],
'expires_at': time.time() + data['expires_in'] - 60
}
return data['access_token']
@app.route('/api/inscription', methods=['POST'])
def inscription():
data = request.form
first_name = data.get('firstName', '').strip()
last_name = data.get('lastName', '').strip()
email = data.get('email', '').strip()
phone = data.get('phone', '').strip()
service_id = data.get('serviceId', '')
# Validation
if not all([first_name, last_name, email, service_id]):
return jsonify({'error': 'Champs obligatoires manquants'}), 400
try:
token = get_access_token()
response = requests.post(
f'{TEO_API}/production/dossiers',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json',
'Accept': 'application/ld+json'
},
json={
'firstName': first_name,
'lastName': last_name,
'email': email,
'phone': phone or None,
'service': f'/api/production/services/{service_id}'
}
)
if response.status_code == 201:
dossier = response.json()
return jsonify({
'success': True,
'message': 'Inscription enregistrée',
'dossierId': dossier['id']
})
else:
return jsonify({
'error': 'Erreur lors de la création',
'details': response.json()
}), response.status_code
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(port=3000)
Étape 3 : Champs disponibles
Voici les principaux champs que vous pouvez envoyer lors de la création d'un dossier :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
firstName | string | Oui | Prénom du bénéficiaire |
lastName | string | Oui | Nom du bénéficiaire |
email | string | Oui | Email du bénéficiaire |
phone | string | Non | Téléphone |
service | IRI | Oui | Référence à la prestation (format /api/production/services/{uuid}) |
birthDate | date | Non | Date de naissance (format YYYY-MM-DD) |
address | string | Non | Adresse postale |
postalCode | string | Non | Code postal |
city | string | Non | Ville |
Pour ajouter des données spécifiques à votre téo, utilisez la propriété data. Contactez le support pour connaître les champs disponibles.
Gestion des erreurs
Doublons
Si un dossier existe déjà avec le même email pour la même prestation, l'API retournera une erreur 422.
if (response.status === 422) {
const error = await response.json();
if (error.violations?.some(v => v.message.includes('doublon'))) {
return res.status(409).json({
error: 'Un dossier existe déjà avec cet email'
});
}
}
Prestation invalide
Si l'UUID de prestation est incorrect ou la prestation n'est pas accessible :
if (response.status === 400 || response.status === 404) {
console.error('Prestation invalide:', serviceId);
// Vérifiez l'UUID dans téo (voir guide Identifiants)
}
Bonnes pratiques
- Validez côté client ET serveur - Ne faites jamais confiance aux données du formulaire
- Utilisez HTTPS - Toutes les communications doivent être chiffrées
- Limitez les tentatives - Implémentez un rate limiting pour éviter les abus
- Loggez les erreurs - Conservez une trace pour le debugging
- Confirmez l'inscription - Envoyez un email de confirmation au bénéficiaire
Aller plus loin
- Afficher vos prestations - Récupérer dynamiquement la liste des prestations
- Gestion des erreurs - Comprendre et gérer les erreurs API
- Référence API - Documentation complète de l'endpoint Dossiers