# Le cycle d'une conversation

## Déroulé type, dans une page web

<Stepper>

1. **Charger l'avatar** : `GET /v1/avatars/{avatar_id}` avec la clé publique. Vous recevez le nom, les couleurs et les liens des fichiers du visage. **Pas de décompte** : l'affichage n'est pas facturé.

1. **Ouvrir la conversation** : `POST /v1/conversations` avec la clé publique, à la **première action** du visiteur (un clic, une question), pas au simple affichage de la page. Vous recevez un jeton de conversation.

1. **Converser** : les questions, la voix et la transcription se font avec ce **jeton** (`Authorization: Bearer <jeton>`).

1. **Renouveler le jeton** avant ses 30 minutes : `POST /v1/conversations/{id}/token`. Pas de décompte.

1. **Terminer** (facultatif) : `POST /v1/conversations/{id}/end`. La conversation ne peut plus être reprise et son jeton n'est plus accepté.

</Stepper>

## Les durées

| | Durée | Au-delà |
| --- | --- | --- |
| Jeton de conversation | 30 minutes | `401 token_expired` : renouveler avant, ou rouvrir avec `resume` |
| Conversation | **10 minutes au plus** depuis l'ouverture, renouvellements compris | `410 conversation_expired` : en ouvrir une nouvelle, **décomptée** |
| Liens des fichiers du visage | 1 heure (`assets_expire_at`) | `403 invalid_link` : relire la fiche de l'avatar |

## Reprendre une conversation

Si le visiteur recharge la page, rouvrez avec l'identifiant de la conversation précédente :

```http
POST /v1/conversations
Authorization: Bearer pk_test_…
Content-Type: application/json

{ "resume": "conv_9xk2…" }
```

| Réponse | Cas | Décompte |
| --- | --- | --- |
| `200` | conversation du même déploiement, non terminée, active il y a moins de 30 minutes | **non** (`counted: false`) |
| `201` | sinon : une nouvelle conversation est ouverte | oui (`counted: true`) |

Comme une conversation dure 10 minutes au plus, la reprise ne vaut que dans ces 10 minutes.

## La réponse d'ouverture

```json
{
  "conversation_id": "conv_9xk2…",
  "token": "eyJ…",
  "expires_at": "2026-10-27T18:42:00Z",
  "counted": true,
  "quota": { "used": 412, "limit": 500, "period": "2026-10" },
  "voice": { "allowed": true, "reason": null, "units": 1, "spoken": 0 }
}
```

- `quota` : conversations décomptées du mois, et votre forfait.
- `voice.allowed` vaut `false` quand la voix n'est pas disponible ; `voice.reason` dit pourquoi (voir [Voix et décompte](/voix-et-decompte)).
- **Au-delà du forfait, la conversation s'ouvre quand même**, en écrit seul : aucun refus, aucun dépassement facturé.

## Fichiers du visage

Les liens de `assets` sont **signés et valables 1 heure**. Ne les fabriquez pas et ne les gardez pas : relisez la fiche de l'avatar pour en obtenir de nouveaux. Un lien modifié ou expiré reçoit `403 invalid_link`.

Le [SDK Twimi](/sdk) fait tout cela pour vous ; ces détails servent à une intégration directe.
