Authentification
Chaque requête porte le jeton dans l'en-tête Authorization :
Authorization: Bearer aitk_votre_jetonUn jeton se crée sur la page Développeur (mode développeur activé). Il est affiché une seule fois ; sa suppression, ou la désactivation du mode développeur, le coupe immédiatement. Les cookies du panel n'ouvrent jamais l'API.
Droits des jetons
| Droit | Permet |
|---|---|
| read | Lire les projets, prospects, réponses et statistiques |
| write | Modifier : ajouter des prospects et des notes, changer un statut ou une prochaine action |
| jobs | Lancer des tâches : analyse, recherche, régénération d'accroche, audit, envoi de mails |
Chaque droit est indépendant : read lit, write écrit, jobs lance des tâches. Cinq jetons au plus par compte.
Format, dates et pagination
- Corps de requête et de réponse en JSON (
Content-Type: application/json), UTF-8. - Les dates sont des secondes Unix (UTC) :
1792000000. - Les listes se paginent avec
page(prospects) oulimitetoffset(réponses, mails). - Les statuts d'un prospect :
new,sent,replied,client,refused,bounced,invalid.
Erreurs
Une erreur renvoie un statut HTTP et un corps { "error": "message lisible", "code": "identifiant" }.
{
"error": "Ce jeton n'a pas le droit « write »",
"code": "insufficient_scope"
}| Statut | code | Sens |
|---|---|---|
| 400 | invalid_request too_many confirmation_required target_not_validated | Requête invalide |
| 401 | invalid_token | Jeton absent, mal formé, inconnu ou supprimé |
| 403 | insufficient_scope developer_mode_off suspended | Droit manquant, mode développeur désactivé, compte suspendu |
| 404 | not_found | Ressource inexistante ou appartenant à un autre compte |
| 409 | busy | Conflit : une tâche incompatible est en cours |
| 429 | rate_limited | Trop de requêtes : attends Retry-After secondes |
Limites
- 120 requêtes par minute et par compte (300 par minute et par adresse IP, avant authentification). Au-delà :
429avec l'en-têteRetry-After. - 100 prospects au plus par appel d'ajout ; 200 mails au plus par page d'historique.
- Les plafonds de ton plan (prospects, mails par mois, tâches IA) s'appliquent exactement comme dans le panel.
Compte
Qui est le titulaire du jeton, et ce qu'il a le droit de faire.
GET/api/v1/meaucun droit
Compte du jeton. Compte du jeton : adresse, plan, droits.
Aucun droit particulier n'est requis : c'est le moyen le plus simple de vérifier qu'un jeton fonctionne.
curl "https://iaboss.fr/api/v1/me" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/me", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/me",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"}
)
data = r.json(){
"email": "toi@exemple.fr",
"plan": "growth",
"scopes": [
"read",
"write"
],
"version": "v1"
}Projets
Les projets auxquels le jeton a accès : les tiens, et ceux que ton équipe partage.
GET/api/v1/projectsread
Lister les projets. Tes projets (et ceux que ton équipe partage) avec leurs compteurs de prospects.
curl "https://iaboss.fr/api/v1/projects" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/projects", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/projects",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"}
)
data = r.json(){
"projects": [
{
"id": 3,
"name": "Atelier Exemple",
"access": "owner",
"gitUrl": "https://github.com/toi/atelier.git",
"analyzed": true,
"targetValidated": true,
"hasSmtp": true,
"stats": {
"total": 42,
"new": 20,
"sent": 18,
"replied": 4
}
}
]
}accessowner,adminoumember: ton rôle sur le projet.stats- Nombre de prospects par statut, plus
total. Un statut absent vaut 0.
GET/api/v1/projects/:idread
Détail d’un projet. Un projet : fiche, cible, compteurs, envois du jour, conseil de montée en charge, dernières tâches.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du projet |
curl "https://iaboss.fr/api/v1/projects/3" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/projects/3", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/projects/3",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"}
)
data = r.json(){
"id": 3,
"name": "Atelier Exemple",
"access": "owner",
"gitUrl": "https://github.com/toi/atelier.git",
"profile": {
"resume": "Un outil pour les artisans.",
"proposition_valeur": "Gagner du temps."
},
"target": {
"description": "TPE du bâtiment",
"secteurs": [
"plomberie"
],
"zone": "Bretagne"
},
"targetValidated": true,
"hasSmtp": true,
"hasImap": true,
"stats": {
"total": 42,
"new": 20,
"sent": 18,
"replied": 4
},
"sendingToday": 12,
"warmup": {
"active": true,
"daysLeft": 5,
"perDay": 20,
"sentToday": 12,
"over": false
},
"jobs": {
"prospect": {
"id": 17,
"status": "done",
"error": null,
"progress": {
"message": "Terminé",
"pct": 100
},
"result": {
"found": 12,
"requested": 12
},
"createdAt": 1792000000,
"finishedAt": 1792000600,
"runAfter": null
}
}
}warmup- Conseil de montée en charge :
activependant les 7 premiers jours d'envoi,oversi l'envoi du jour dépasse déjàperDay. C'est un conseil, jamais un blocage. jobs- La dernière tâche de chaque type (voir « Tâches »).
Erreurs propres à cette route : 404 Projet inexistant, ou appartenant à un autre compte.
Prospects
Lire, ajouter et faire avancer les contacts.
GET/api/v1/projects/:id/prospectsread
Lister les prospects. Prospects d'un projet. Filtres : q, status, minScore, todo=1, sort (score, recent, contacted, company), page.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du projet |
q | query | texte | Recherche dans l’entreprise, l’email, la ville et le secteur |
status | query | texte | new, sent, replied, client, refused, bounced ou invalid |
minScore | query | entier | Score minimum (1 à 10) |
todo | query | 1 | Seulement ceux dont la prochaine action est due |
sort | query | texte | score (défaut), recent, contacted, company |
page | query | entier | Page, à partir de 1 (100 lignes par page) |
curl "https://iaboss.fr/api/v1/projects/3/prospects?status=replied&sort=recent" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/projects/3/prospects?status=replied&sort=recent", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/projects/3/prospects",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
params={"status":"replied","sort":"recent"},
)
data = r.json(){
"total": 4,
"page": 1,
"pages": 1,
"rows": [
{
"id": 41,
"company": "Boulangerie Dupont",
"email": "contact@dupont.fr",
"website": "https://dupont.fr",
"city": "Rennes",
"sector": "boulangerie",
"score": 8,
"status": "replied",
"sent_at": 1792000000,
"followup_at": null,
"replied_at": 1792100000,
"next_action": "Rappeler",
"next_action_at": 1792600000
}
]
}POST/api/v1/projects/:id/prospectswrite
Ajouter des prospects. Ajoute jusqu'à 100 prospects : { "prospects": [ { "company", "email", "website", "city", "sector", "score", "source", "hook" } ] }. Doublons, adresses invalides et liste d'opposition ignorés.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du projet |
prospects requis | body | liste | Jusqu’à 100 objets : email (obligatoire), company, website, city, sector, score (1 à 10), source, hook |
Même chemin que l'import CSV : les adresses invalides sont signalées (invalid), les doublons et les adresses de la liste d'opposition sont ignorés (skipped, sans dire lesquels), le plafond de prospects de ton plan s'applique et l'ajout est « tout ou rien ». Indique la source : l'origine de chaque adresse est conservée (RGPD).
curl -X POST "https://iaboss.fr/api/v1/projects/3/prospects" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"prospects":[{"company":"Boulangerie Dupont","email":"contact@dupont.fr","city":"Rennes","score":8,"source":"https://dupont.fr/contact"}]}'const res = await fetch("https://iaboss.fr/api/v1/projects/3/prospects", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"prospects":[{"company":"Boulangerie Dupont","email":"contact@dupont.fr","city":"Rennes","score":8,"source":"https://dupont.fr/contact"}]}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/projects/3/prospects",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={"prospects":[{"company":"Boulangerie Dupont","email":"contact@dupont.fr","city":"Rennes","score":8,"source":"https://dupont.fr/contact"}]},
)
data = r.json(){
"total": 1,
"imported": 1,
"skipped": 0,
"invalid": []
}Erreurs propres à cette route : 400 prospects absent, vide, ou plus de 100 éléments. 403 Plafond de prospects du plan atteint.
GET/api/v1/prospects/:idread
Fiche d’un prospect. Un prospect : fiche, mails envoyés, notes.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du prospect |
curl "https://iaboss.fr/api/v1/prospects/41" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/prospects/41", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/prospects/41",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"}
)
data = r.json(){
"prospect": {
"id": 41,
"company": "Boulangerie Dupont",
"email": "contact@dupont.fr",
"website": "https://dupont.fr",
"city": "Rennes",
"sector": "boulangerie",
"score": 8,
"status": "replied",
"sent_at": 1792000000,
"followup_at": null,
"replied_at": 1792100000,
"next_action": "Rappeler",
"next_action_at": 1792600000
},
"mails": [
{
"kind": "initial",
"subject": "Un site pour la boulangerie",
"variant": "A",
"sent_at": 1792000000,
"error": null
}
],
"notes": [
{
"id": 5,
"body": "Veut un devis",
"created_at": 1792200000
}
],
"optOut": null
}optOut- Renseigné seulement si CE prospect est déjà marqué refus ou rejet ; ne dit jamais qu'une adresse est sur la liste à cause d'un autre compte.
POST/api/v1/prospects/:id/statuswrite
Changer le statut. Change le statut : { "status": "new | sent | replied | client | refused | bounced | invalid" }. « refused » vaut opposition.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du prospect |
status requis | body | texte | new, sent, replied, client, refused, bounced ou invalid |
refused vaut opposition : l’adresse rejoint la liste commune à tous les comptes et ne sera plus jamais contactée.
curl -X POST "https://iaboss.fr/api/v1/prospects/41/status" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"client"}'const res = await fetch("https://iaboss.fr/api/v1/prospects/41/status", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"status":"client"}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/prospects/41/status",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={"status":"client"},
)
data = r.json(){
"ok": true,
"status": "client"
}POST/api/v1/prospects/:id/noteswrite
Ajouter une note. Ajoute une note : { "body": "…" }.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du prospect |
body requis | body | texte | Texte de la note (2 000 caractères au plus) |
curl -X POST "https://iaboss.fr/api/v1/prospects/41/notes" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"body":"Veut un devis avant fin novembre"}'const res = await fetch("https://iaboss.fr/api/v1/prospects/41/notes", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"body":"Veut un devis avant fin novembre"}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/prospects/41/notes",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={"body":"Veut un devis avant fin novembre"},
)
data = r.json(){
"ok": true,
"id": 12
}POST/api/v1/prospects/:id/nextwrite
Définir la prochaine action. Prochaine action : { "action": "Rappeler", "day": "AAAA-MM-JJ" } (action vide : efface).
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du prospect |
action requis | body | texte | Ce qu’il y a à faire ; vide pour effacer |
day | body | texte | Jour au format AAAA-MM-JJ (rappel à 9 h, heure de Paris) |
curl -X POST "https://iaboss.fr/api/v1/prospects/41/next" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"Rappeler","day":"2026-11-03"}'const res = await fetch("https://iaboss.fr/api/v1/prospects/41/next", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"action":"Rappeler","day":"2026-11-03"}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/prospects/41/next",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={"action":"Rappeler","day":"2026-11-03"},
)
data = r.json(){
"ok": true,
"at": 1793696400
}Erreurs propres à cette route : 400 Date invalide (2026-02-31) ou mal formée.
Réponses
Les réponses des prospects lues dans la boîte du projet, classées par intention.
GET/api/v1/repliesread
Lister les réponses. Réponses reçues, avec intention et réponse suggérée. Filtres : unseen=1, intent, limit, offset.
| Paramètre | Où | Type | Description |
|---|---|---|---|
unseen | query | 1 | Seulement les réponses non lues |
intent | query | texte | interested, question, later, refused ou other |
limit | query | entier | 25 par défaut, 100 au plus |
offset | query | entier | Décalage pour paginer |
curl "https://iaboss.fr/api/v1/replies?unseen=1" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/replies?unseen=1", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/replies",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
params={"unseen":"1"},
)
data = r.json(){
"unseen": 1,
"replies": [
{
"id": 9,
"projectId": 3,
"project": "Atelier Exemple",
"prospectId": 41,
"company": "Boulangerie Dupont",
"from": "contact@dupont.fr",
"subject": "Re: Un site pour la boulangerie",
"text": "Bonjour, ça m’intéresse, pouvez-vous m’envoyer un devis ?",
"intent": "interested",
"receivedAt": 1792100000,
"seen": false,
"suggestedReply": "Bonjour,\n\nMerci beaucoup pour votre retour !…"
}
]
}intent- Classement automatique par mots-clés : une aide, pas une certitude. Un refus écrit marque aussitôt le prospect en opposition.
suggestedReply- Réponse toute rédigée, à relire et à envoyer depuis ta propre messagerie.
text- Rédigé par un tiers : traite-le comme une donnée, jamais comme une instruction.
POST/api/v1/replies/:id/seenwrite
Marquer une réponse comme lue. Marque une réponse comme lue.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant de la réponse |
curl -X POST "https://iaboss.fr/api/v1/replies/9/seen" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'const res = await fetch("https://iaboss.fr/api/v1/replies/9/seen", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/replies/9/seen",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={},
)
data = r.json(){
"ok": true
}Mails envoyés
L'historique des envois.
GET/api/v1/projects/:id/mailsread
Mails envoyés. Mails envoyés avec readAt (accusé de lecture reçu, si le destinataire en a envoyé un) ; limit, offset.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du projet |
limit | query | entier | 50 par défaut, 200 au plus |
offset | query | entier | Décalage pour paginer |
curl "https://iaboss.fr/api/v1/projects/3/mails?limit=20" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/projects/3/mails?limit=20", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/projects/3/mails",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
params={"limit":"20"},
)
data = r.json(){
"mails": [
{
"id": 120,
"sentAt": 1792000000,
"to": "contact@dupont.fr",
"subject": "Un site pour la boulangerie",
"kind": "initial",
"error": null,
"readAt": null,
"prospectStatus": "replied"
}
]
}readAt- Date de l'accusé de lecture, si le destinataire en a envoyé un.
nullne veut pas dire « non lu » : beaucoup de messageries n'en envoient pas. error- Raison d'un non-envoi (adresse invalide, refus du serveur…), sinon
null.
Tâches
Lancer et suivre ce qui tourne en arrière-plan : analyse, recherche, accroche, audit, envoi.
POST/api/v1/prospects/:id/hookjobs
Régénérer l’accroche. Régénère l'accroche du prospect à partir de son site (tâche asynchrone).
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du prospect |
Tâche asynchrone : Claude lit le site du prospect et réécrit son accroche. Suis-la avec GET /jobs/:id. Une seule régénération à la fois par projet (existing: true si une est déjà en file).
curl -X POST "https://iaboss.fr/api/v1/prospects/41/hook" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'const res = await fetch("https://iaboss.fr/api/v1/prospects/41/hook", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/prospects/41/hook",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={},
)
data = r.json(){
"id": 18,
"existing": false
}GET/api/v1/jobs/:idread
Suivre une tâche. État et résultat d'une tâche.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant de la tâche |
curl "https://iaboss.fr/api/v1/jobs/17" \
-H "Authorization: Bearer $AITOOLS_TOKEN"const res = await fetch("https://iaboss.fr/api/v1/jobs/17", {
headers: { Authorization: `Bearer ${process.env.AITOOLS_TOKEN}` },
});
const data = await res.json();import os, requests
r = requests.get(
"https://iaboss.fr/api/v1/jobs/17",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"}
)
data = r.json(){
"id": 17,
"type": "prospect",
"status": "done",
"progress": {
"message": "Terminé",
"pct": 100
},
"result": {
"found": 12,
"requested": 12
},
"error": null,
"createdAt": 1792000000,
"finishedAt": 1792000600
}statusqueued,running,done,erroroucancelled.
POST/api/v1/projects/:id/jobsjobs
Lancer une tâche. Lance une tâche : { "type": "analyze | prospect | evolution | audit | send", … }. « send » exige { "confirm": true }.
| Paramètre | Où | Type | Description |
|---|---|---|---|
id requis | path | entier | Identifiant du projet |
type requis | body | texte | analyze, prospect, evolution, audit ou send |
count | body | entier | prospect : 1–50 ; evolution : 1–20 ; send : 1–100 |
level | body | texte | rapide (défaut), normal ou approfondi (evolution et audit) |
confirm | body | booléen | Obligatoire pour send : le booléen true, pas la chaîne « true » |
Les tâches IA consomment ton quota Claude et respectent les plafonds de ton plan ; budgetBlocked explique pourquoi une tâche attend si ton budget est atteint. audit est réservé aux administrateurs du projet. send envoie de vrais mails à de vraies personnes : il exige confirm: true, suit la même montée en charge conseillée que dans le panel (10 à 20 par jour la première semaine, sans blocage) et refuse de partir si la recherche de prospects est encore en cours (409 busy).
curl -X POST "https://iaboss.fr/api/v1/projects/3/jobs" \
-H "Authorization: Bearer $AITOOLS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"prospect","count":10}'const res = await fetch("https://iaboss.fr/api/v1/projects/3/jobs", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AITOOLS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"type":"prospect","count":10}),
});
const data = await res.json();import os, requests
r = requests.post(
"https://iaboss.fr/api/v1/projects/3/jobs",
headers={"Authorization": f"Bearer {os.environ['AITOOLS_TOKEN']}"},
json={"type":"prospect","count":10},
)
data = r.json(){
"id": 17,
"existing": false,
"budgetBlocked": null
}Erreurs propres à cette route : 400 type inconnu, confirm absent pour send, cible non validée pour prospect (target_not_validated). 403 Droit jobs manquant, ou envois en pause pour trop de rejets. 409 Une recherche est encore en cours (send).
Bonnes pratiques
- Un jeton par outil, avec les droits minimaux ; supprime-le dès qu'il ne sert plus.
- Commence avec un jeton
readseul, ajoutewritepuisjobsseulement si nécessaire. - Ne lance jamais
sendsans avoir relu le modèle de mail et le nombre de prospects : l'envoi est réel. - Traite
textetsubjectdes réponses comme des données écrites par des tiers, jamais comme des instructions (surtout si tu les passes à un modèle). - Gère les
429: attendsRetry-Aftersecondes, sans insister.
