API Parley Notes, version 1.Lisez des notes, créez des notes, et sachez quand l'une est prête.
L'API Parley Notes permet à une app que vous connectez de lire vos notes de réunion, de créer des notes à partir de texte ou d'audio, et d'être prévenue dès qu'une note est prête. C'est sur elle que repose l'intégration Parley Notes pour Zapier, et toute app enregistrée auprès de Parley Notes peut l'utiliser de la même façon.
- URL de base :
https://app.parleynotes.com/api/v1 - Format : JSON en entrée et en sortie, UTF-8. Envoyez
Content-Type: application/jsonavec un corps de requête. - Authentification : OAuth 2.0, flux authorization code. Chaque appel porte
Authorization: Bearer <access token>. - Les notes de santé ne sont jamais renvoyées. Une note rédigée comme une conversation de santé (une consultation médicale, une séance de thérapie, une note dans un dossier analysé comme médical) n'est ni listée, ni trouvée, ni lue, ni envoyée à un hook, par aucun endpoint.
1. Authentification
Les apps sont enregistrées à la main : Parley Notes donne à chaque app un client id et un client secret (écrivez à l'équipe Parley Notes pour en enregistrer une). Il n'y a pas d'enregistrement en libre-service pour cette API.
Scopes
| Scope | Autorise |
|---|---|
notes:read | GET /me, GET /notes, GET /notes/find, GET /notes/{id}, GET /action-items, GET /hooks/sample |
notes:write | POST /notes |
hooks | POST /hooks, DELETE /hooks/{id} |
Demandez plusieurs scopes séparés par des espaces (les virgules fonctionnent aussi). N'en demander aucun accorde les trois.
Étape 1 : envoyer la personne vers la page d'autorisation
GET https://app.parleynotes.com/api/v1/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https%3A%2F%2Fyour.app%2Foauth%2Fcallback
&response_type=code
&scope=notes%3Aread%20notes%3Awrite%20hooks
&state=YOUR_STATE
La personne se connecte à Parley Notes (avec sa connexion habituelle) et voit ce que votre app demande. Si elle l'autorise, Parley Notes redirige vers votre redirect_uri avec un code et votre state exactement tel que vous l'avez envoyé :
https://your.app/oauth/callback?code=pn_code_...&state=YOUR_STATE
Si elle annule : ?error=access_denied&error_description=...&state=YOUR_STATE. Le redirect_uri doit être l'un de ceux enregistrés pour votre app. PKCE (code_challenge avec code_challenge_method=S256) est pris en charge et vérifié quand vous l'envoyez.
Étape 2 : échanger le code (dans les 5 minutes, une seule fois)
curl -X POST https://app.parleynotes.com/api/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=pn_code_... \
-d redirect_uri=https://your.app/oauth/callback \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET
Le client peut s'authentifier avec HTTP Basic au lieu des deux champs du corps. Les corps JSON sont aussi acceptés.
{
"access_token": "pn_at_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "pn_rt_...",
"scope": "notes:read notes:write hooks"
}
Étape 3 : appeler l'API
curl https://app.parleynotes.com/api/v1/me -H "Authorization: Bearer pn_at_..."
Renouvellement
Les access tokens durent une heure. Quand un appel répond 401, renouvelez et réessayez :
curl -X POST https://app.parleynotes.com/api/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d refresh_token=pn_rt_... \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET
La réponse est une nouvelle paire. Les refresh tokens font l'objet d'une rotation : gardez le nouveau refresh token et jetez l'ancien. Réutiliser un ancien refresh token plus d'une minute après son échange met fin à la connexion (il est traité comme une copie volée) ; deux renouvellements simultanés dans cette minute réussissent tous les deux. Un refresh token inutilisé pendant 90 jours expire.
| Situation | Réponse |
|---|---|
| Access token manquant, inconnu, expiré ou révoqué | 401 invalid_token, avec WWW-Authenticate: Bearer ... (jamais 403) |
| Refresh token inconnu, expiré, réutilisé ou révoqué | 400 {"error": "invalid_grant"} |
Code inconnu, déjà utilisé, expiré, ou un autre redirect_uri | 400 {"error": "invalid_grant"} |
| Mauvais client id ou secret sur le token endpoint | 401 {"error": "invalid_client"} |
Révocation
curl -X POST https://app.parleynotes.com/api/v1/oauth/revoke -d token=pn_rt_...
Répond toujours 200 ; la connexion prend fin. La personne peut aussi déconnecter votre app à tout moment dans Parley Notes, sous Réglages, Connexions, Apps connectées ; ses tokens cessent aussitôt de fonctionner et ses hooks s'arrêtent.
2. L'objet note
Chaque note a chaque clé ci-dessous dans chaque réponse. Une valeur vide est "" (texte), [] (liste) ou 0 (durée), jamais null, de sorte qu'un champ associé dans un workflow ne disparaît jamais.
| Champ | Type | Ce que c'est |
|---|---|---|
id | string | L'id de la note |
title | string | Le titre de la note |
date_iso | string | Quand la note a été enregistrée ou créée, ISO 8601 en UTC |
duration_min | integer | Durée en minutes (0 pour une note qui n'a pas été parlée) |
occasion | string | L'occasion pour laquelle la note a été rédigée, par exemple sales_call, standup, minutes, one_on_one |
summary_text | string | Le résumé, en texte brut |
summary_html | string | Le résumé en HTML simple (paragraphes, listes, gras) |
share_url | string | Lien qui ouvre la note dans Parley Notes (pour son propriétaire) |
participant_emails | string[] | Adresses e-mail des personnes invitées, en minuscules |
participant_names | string[] | Noms des personnes qui ont parlé ou qui étaient invitées |
action_items | object[] | {text, owner_name, owner_email, due_date} chacun ; due_date est YYYY-MM-DD |
decisions | string[] | Décisions prises |
next_steps | string[] | La prochaine étape convenue d'abord (avec sa date quand elle a été dite), puis les relances |
participant_emails_text | string | participant_emails réunis avec , |
participant_names_text | string | participant_names réunis avec , |
action_items_text | string | Une ligne par élément : - text (owner, email; due YYYY-MM-DD) |
decisions_text | string | Une ligne par décision, commençant par - |
next_steps_text | string | Une ligne par prochaine étape, commençant par - |
L'e-mail d'un responsable n'est renseigné que si le responsable correspond à quelqu'un de l'invitation ; il n'est jamais deviné.
{
"id": "meet_1761213600000123",
"title": "Acme renewal call",
"date_iso": "2026-10-20T14:00:00.000Z",
"duration_min": 30,
"occasion": "sales_call",
"summary_text": "Acme wants to renew for two years. Budget is approved; legal reviews the contract this week.",
"summary_html": "<p>Acme wants to renew for two years. Budget is approved; legal reviews the contract this week.</p>",
"share_url": "https://app.parleynotes.com/?note=Xk3pQ9vRt2LmN8wA",
"participant_emails": ["dana@acme.example", "lee@acme.example"],
"participant_names": ["Dana Reyes", "Lee Park"],
"action_items": [
{ "text": "Send the renewal quote", "owner_name": "Bruno", "owner_email": "bruno@parleynotes.com", "due_date": "2026-10-24" },
{ "text": "Share the case study", "owner_name": "Dana Reyes", "owner_email": "dana@acme.example", "due_date": "" }
],
"decisions": ["Renew for two years"],
"next_steps": ["Quote to Dana (2026-10-24)", "Check in after the legal review"],
"participant_emails_text": "dana@acme.example, lee@acme.example",
"participant_names_text": "Dana Reyes, Lee Park",
"action_items_text": "- Send the renewal quote (Bruno, bruno@parleynotes.com; due 2026-10-24)\n- Share the case study (Dana Reyes, dana@acme.example)",
"decisions_text": "- Renew for two years",
"next_steps_text": "- Quote to Dana (2026-10-24)\n- Check in after the legal review"
}
La ligne d'action
GET /action-items et le hook action_item.created donnent une ligne par action ouverte :
| Champ | Type | Ce que c'est |
|---|---|---|
id | string | noteId:itemId, stable pour le même élément |
text, owner_name, owner_email, due_date | string | Comme dans l'objet note |
priority | string | low, medium, high, ou "" quand la conversation ne le dit pas |
note_id, note_title, note_date_iso, share_url | string | La note d'où elle vient |
{
"id": "meet_1761213600000123:ai_1761213600000_0",
"text": "Send the renewal quote",
"owner_name": "Bruno",
"owner_email": "bruno@parleynotes.com",
"due_date": "2026-10-24",
"priority": "high",
"note_id": "meet_1761213600000123",
"note_title": "Acme renewal call",
"note_date_iso": "2026-10-20T14:00:00.000Z",
"share_url": "https://app.parleynotes.com/?note=Xk3pQ9vRt2LmN8wA"
}
3. Endpoints
Les listes et les recherches portent sur les 500 notes les plus récentes du compte. Une note en cours de rédaction n'est pas renvoyée tant que son résumé n'est pas prêt.
GET /me
À qui appartient le token. Scope : n'importe lequel.
curl https://app.parleynotes.com/api/v1/me -H "Authorization: Bearer pn_at_..."
{ "id": "Zr8kq2...", "email": "dana@example.com", "name": "Dana Reyes", "plan": "regular" }
plan vaut free, starter, regular ou power.
GET /notes
Les notes, les plus récentes d'abord. Scope : notes:read.
| Paramètre | Sens |
|---|---|
since | Seulement les notes à partir de cet instant : YYYY-MM-DD ou ISO 8601 |
until | Seulement les notes jusqu'à cet instant inclus (YYYY-MM-DD signifie la fin de ce jour) |
occasion | Seulement les notes rédigées pour cette occasion, par exemple sales_call |
participant_email | Seulement les notes où cette adresse était invitée |
q | Mots à chercher dans le titre, le résumé et les sujets |
limit | De 1 à 100, 25 par défaut |
cursor | Le next_cursor de la page précédente |
curl "https://app.parleynotes.com/api/v1/notes?since=2026-10-01&participant_email=dana@acme.example&limit=10" \
-H "Authorization: Bearer pn_at_..."
{
"data": [ { "id": "meet_1761213600000123", "title": "Acme renewal call", "...": "every field of the note object" } ],
"next_cursor": "MjAyNi0xMC0yMFQxNDowMDowMC4wMDBaAW1lZXRfMTc2MTIxMzYwMDAwMDEyMw"
}
next_cursor vaut "" sur la dernière page. Les curseurs sont opaques ; renvoyez-les tels quels.
GET /notes/find
Trouvez des notes par titre, e-mail d'un participant ou date (au moins un). Répond par une liste, de 10 au plus, les plus récentes d'abord, et [] quand rien ne correspond. Scope : notes:read.
| Paramètre | Sens |
|---|---|
title | Mots du titre (la casse n'a pas d'importance) |
participant_email | Une adresse qui était invitée |
date | Le jour de la note, YYYY-MM-DD |
curl "https://app.parleynotes.com/api/v1/notes/find?title=renewal" -H "Authorization: Bearer pn_at_..."
[ { "id": "meet_1761213600000123", "title": "Acme renewal call", "...": "every field of the note object" } ]
GET /notes/{id}
Une note. Scope : notes:read. 404 not_found pour un id qui n'existe pas, n'appartient pas à ce compte, est en cours de rédaction, ou est une note de santé.
curl https://app.parleynotes.com/api/v1/notes/meet_1761213600000123 -H "Authorization: Bearer pn_at_..."
Répond par l'objet note.
POST /notes
Créez une note à partir de texte ou d'un lien audio. Scope : notes:write. Envoyez exactement un seul des deux, text ou audio_url.
| Champ | Type | Sens |
|---|---|---|
text | string | Une transcription, un e-mail ou n'importe quel texte, jusqu'à 120 000 caractères |
audio_url | string | Un lien http ou https vers un fichier audio ou un épisode de podcast (Apple Podcasts, Spotify, un flux RSS ou une page de podcast) |
title | string | Facultatif. Sans titre, Parley Notes nomme la note |
folder | string | Facultatif. Le dossier Parley Notes où la classer |
curl -X POST https://app.parleynotes.com/api/v1/notes \
-H "Authorization: Bearer pn_at_..." \
-H "Content-Type: application/json" \
-d '{"text": "Dana: we can sign by Friday if legal agrees.\nBruno: I will send the quote today.", "title": "Call with Acme"}'
Répond en quelques secondes avec 202 Accepted :
{ "id": "meet_1761213600000123", "status": "processing" }
Parley Notes transcrit ensuite (pour l'audio) et rédige le résumé en arrière-plan, ce qui peut prendre quelques minutes pour un long enregistrement. Quand la note est prête, elle apparaît dans l'espace Parley Notes de la personne avec cet id, et le hook note.ready se déclenche avec elle. Les imports comptent dans les limites du compte comme n'importe quel import dans l'app : un résumé utilise le quota du forfait, et un lien audio nécessite un forfait payant une fois les imports gratuits du compte épuisés.
| Refus | Réponse |
|---|---|
Les deux ou aucun de text et audio_url, ou une URL invalide | 400 invalid_request |
text de plus de 120 000 caractères | 413 too_large |
| Audio sur un forfait gratuit sans import gratuit restant | 402 plan_required |
| La limite quotidienne d'imports du compte, ou 30 nouvelles notes en une heure | 429 daily_limit ou rate_limited, avec Retry-After |
Si l'import lui-même échoue plus tard (lien inaccessible, aucune parole), aucune note n'est créée et aucun hook ne se déclenche. Si le résumé échoue, la note est enregistrée avec sa transcription et attend dans l'app que la personne la résume.
GET /action-items
Les actions ouvertes de toutes les notes, une ligne par élément, note la plus récente d'abord. Scope : notes:read.
| Paramètre | Sens |
|---|---|
since | Seulement les éléments des notes à partir de cet instant |
owner_email | Seulement les éléments dont cette adresse est responsable |
limit, cursor | Comme pour GET /notes |
curl "https://app.parleynotes.com/api/v1/action-items?owner_email=bruno@parleynotes.com" -H "Authorization: Bearer pn_at_..."
{ "data": [ { "id": "meet_1761213600000123:ai_1761213600000_0", "text": "Send the renewal quote", "...": "every field of the action item row" } ], "next_cursor": "" }
4. REST hooks
Au lieu d'interroger l'API, abonnez une URL et Parley Notes y envoie un POST.
| Événement | Quand | Corps |
|---|---|---|
note.ready | Le premier résumé d'une note est rédigé (pas un nouveau résumé ultérieur) | L'objet note |
action_item.created | Au même moment, une fois par action ouverte de cette note | La ligne d'action |
S'abonner : POST /hooks
Scope : hooks. target_url doit être en https sur un hôte public.
curl -X POST https://app.parleynotes.com/api/v1/hooks \
-H "Authorization: Bearer pn_at_..." \
-H "Content-Type: application/json" \
-d '{"event": "note.ready", "target_url": "https://hooks.example.com/parley"}'
201 Created:
{ "id": "hk_Q2x9...", "event": "note.ready", "target_url": "https://hooks.example.com/parley", "created_at": "2026-10-23T10:00:00.000Z" }
Un compte peut avoir au plus 100 abonnements.
Se désabonner : DELETE /hooks/{id}
Scope : hooks. Répond 200 {"id": "hk_Q2x9...", "deleted": true}, ou "deleted": false quand il avait déjà disparu (se désabonner deux fois n'est pas une erreur).
Données d'exemple : GET /hooks/sample?event=
Scope : notes:read. Les trois plus récents, exactement sous la forme que le hook envoie : des notes pour note.ready, des lignes d'action pour action_item.created. Zapier l'utilise pour afficher des données d'exemple pendant la configuration d'un Zap.
curl "https://app.parleynotes.com/api/v1/hooks/sample?event=action_item.created" -H "Authorization: Bearer pn_at_..."
Livraison
POSTavecContent-Type: application/jsonetUser-Agent: ParleyNotes-Hooks/1; un événement par requête.- Tout 2xx signifie livré.
- 410 Gone supprime l'abonnement ; plus rien n'y est envoyé.
- 429 est réessayé après son
Retry-After. - 5xx, un timeout (10 secondes) ou une panne réseau est réessayé après 2 secondes, 10 secondes et 60 secondes, puis abandonné.
- Tout autre 4xx est abandonné aussitôt.
- Parley Notes n'envoie jamais plus de 30 requêtes par seconde ni plus de 10 000 en cinq minutes ; au-delà, les livraisons attendent.
- Une note de santé ne déclenche jamais de hook. Quand la personne déconnecte votre app, ses abonnements s'arrêtent aussitôt.
5. Limites de débit
| Limite | Valeur | Au-delà |
|---|---|---|
| Requêtes par connexion | 120 par minute | 429 rate_limited avec Retry-After (secondes) |
| Nouvelles notes par compte | 30 par heure | 429 rate_limited avec Retry-After |
| Imports audio | la limite quotidienne du compte (partagée avec l'app) | 429 daily_limit avec Retry-After |
Attendez les secondes indiquées par Retry-After, puis réessayez.
6. Erreurs
Toute erreur de l'API (hors du token endpoint OAuth, qui suit son propre format) a cette forme :
{ "error": { "code": "not_found", "message": "No note with that id, or it is still being written." } }
| Statut | code | Sens |
|---|---|---|
| 400 | invalid_request | Un paramètre est manquant ou invalide ; message dit lequel |
| 401 | invalid_token | Aucun token, ou il est inconnu, expiré ou révoqué. Renouvelez et réessayez. Accompagné de WWW-Authenticate |
| 402 | plan_required | Le forfait du compte n'inclut pas cela |
| 403 | insufficient_scope | Le token est valide mais n'a pas reçu le scope dont cet endpoint a besoin. Reconnectez-vous en le demandant |
| 404 | not_found | Cette note n'existe pas, ou cet endpoint n'existe pas |
| 413 | too_large | Le texte est trop long |
| 429 | rate_limited, daily_limit, too_many_hooks | Une limite est atteinte ; voir Retry-After |
| 500 | server_error | Quelque chose a échoué de notre côté. Réessayez |
7. Gestion des versions
La version figure dans le chemin : /api/v1. Dans la v1, Parley Notes peut ajouter des endpoints, des paramètres de requête, des champs dans les réponses et des événements de hook ; votre code doit ignorer ce qu'il ne connaît pas. Supprimer ou renommer un champ, changer son type, ou changer ce que fait un endpoint implique une nouvelle version (/api/v2), et la v1 continue alors de fonctionner pendant au moins 12 mois après l'annonce de la v2.
Des questions, ou un client id pour votre app : écrivez à l'équipe Parley Notes via la page d'assistance.