API di Parley Notes, versione 1.Leggi le note, crea note e scopri quando una è pronta.
L'API di Parley Notes permette a un'app che colleghi di leggere le tue note di riunione, creare note da testo o audio ed essere avvisata nel momento in cui una nota è pronta. È la base su cui è costruita l'integrazione di Parley Notes per Zapier, e qualsiasi app registrata su Parley Notes può usarla allo stesso modo.
- URL di base:
https://app.parleynotes.com/api/v1 - Formato: JSON in entrata e in uscita, UTF-8. Invia
Content-Type: application/jsoncon un corpo. - Autenticazione: OAuth 2.0, authorization code grant. Ogni chiamata porta
Authorization: Bearer <access token>. - Le note sulla salute non vengono mai restituite. Una nota scritta come conversazione sulla salute (una visita medica, una seduta di terapia, una nota in una cartella analizzata come medica) non viene elencata, trovata, letta né inviata a un hook, da nessun endpoint.
1. Autenticazione
Le app vengono registrate a mano: Parley Notes assegna a ogni app un client id e un client secret (scrivi al team di Parley Notes per registrarne una). Per questa API non esiste una registrazione self-service.
Scope
| Scope | Consente |
|---|---|
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} |
Puoi chiedere più scope separati da spazi (vanno bene anche le virgole). Se non ne chiedi nessuno, li ottieni tutti e tre.
Passo 1: manda la persona ad autorizzare
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 persona accede a Parley Notes (con il suo accesso abituale) e vede cosa chiede la tua app. Se lo consente, Parley Notes reindirizza al tuo redirect_uri con un codice e il tuo state esattamente come l'hai inviato:
https://your.app/oauth/callback?code=pn_code_...&state=YOUR_STATE
Se annulla: ?error=access_denied&error_description=...&state=YOUR_STATE. Il redirect_uri deve essere uno di quelli registrati per la tua app. PKCE (code_challenge con code_challenge_method=S256) è supportato e viene verificato quando lo invii.
Passo 2: scambia il codice (entro 5 minuti, una sola volta)
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
Il client può autenticarsi con HTTP Basic al posto dei due campi del corpo. Sono accettati anche corpi JSON.
{
"access_token": "pn_at_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "pn_rt_...",
"scope": "notes:read notes:write hooks"
}
Passo 3: chiama l'API
curl https://app.parleynotes.com/api/v1/me -H "Authorization: Bearer pn_at_..."
Rinnovo
Gli access token durano un'ora. Quando una chiamata risponde 401, rinnova il token e riprova:
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 risposta è una nuova coppia. I refresh token ruotano: conserva il nuovo refresh token e scarta quello vecchio. Riutilizzare un vecchio refresh token più di un minuto dopo che è stato scambiato chiude la connessione (viene trattato come una copia rubata); due rinnovi in corsa tra loro entro quel minuto riescono entrambi. Un refresh token non usato per 90 giorni scade.
| Situazione | Risposta |
|---|---|
| Access token mancante, sconosciuto, scaduto o revocato | 401 invalid_token, con WWW-Authenticate: Bearer ... (mai 403) |
| Refresh token sconosciuto, scaduto, riutilizzato o revocato | 400 {"error": "invalid_grant"} |
Codice sconosciuto, già usato, scaduto, oppure un altro redirect_uri | 400 {"error": "invalid_grant"} |
| Client id o secret sbagliati al token endpoint | 401 {"error": "invalid_client"} |
Revoca
curl -X POST https://app.parleynotes.com/api/v1/oauth/revoke -d token=pn_rt_...
Risponde sempre 200; la connessione termina. La persona può anche scollegare la tua app in qualsiasi momento in Parley Notes, sotto Impostazioni, Connessioni, App collegate; i suoi token smettono subito di funzionare e i suoi hook si fermano.
2. L'oggetto nota
Ogni nota ha ogni chiave qui sotto in ogni risposta. Un valore vuoto è "" (testo), [] (elenco) o 0 (durata), mai null, così un campo mappato in un workflow non sparisce mai.
| Campo | Tipo | Cos'è |
|---|---|---|
id | string | L'id della nota |
title | string | Il titolo della nota |
date_iso | string | Quando la nota è stata registrata o creata, ISO 8601 in UTC |
duration_min | integer | Durata in minuti (0 per una nota non parlata) |
occasion | string | Come è stata scritta la nota, per esempio sales_call, standup, minutes, one_on_one |
summary_text | string | Il riepilogo, in testo semplice |
summary_html | string | Il riepilogo in HTML semplice (paragrafi, elenchi, grassetto) |
share_url | string | Link che apre la nota in Parley Notes (per il suo proprietario) |
participant_emails | string[] | Indirizzi email delle persone invitate, in minuscolo |
participant_names | string[] | Nomi delle persone che hanno parlato o sono state invitate |
action_items | object[] | {text, owner_name, owner_email, due_date} ciascuno; due_date è YYYY-MM-DD |
decisions | string[] | Decisioni prese |
next_steps | string[] | Prima il prossimo passo concordato (con la sua data, se è stata detta), poi i follow-up |
participant_emails_text | string | participant_emails unito con , |
participant_names_text | string | participant_names unito con , |
action_items_text | string | Una riga per voce: - text (owner, email; due YYYY-MM-DD) |
decisions_text | string | Una riga per decisione, che inizia con - |
next_steps_text | string | Una riga per prossimo passo, che inizia con - |
L'email di un responsabile viene compilata solo quando il responsabile corrisponde a qualcuno nell'invito; non viene mai indovinata.
{
"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 riga dell'azione
GET /action-items e l'hook action_item.created danno una riga per ogni azione aperta:
| Campo | Tipo | Cos'è |
|---|---|---|
id | string | noteId:itemId, stabile per la stessa voce |
text, owner_name, owner_email, due_date | string | Come nell'oggetto nota |
priority | string | low, medium, high, oppure "" quando la conversazione non lo diceva |
note_id, note_title, note_date_iso, share_url | string | La nota da cui viene |
{
"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. Endpoint
Elenchi e ricerche coprono le 500 note più recenti dell'account. Una nota ancora in scrittura non viene restituita finché il suo riepilogo non è pronto.
GET /me
A chi appartiene il token. Scope: qualsiasi.
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 è free, starter, regular o power.
GET /notes
Le note, dalla più recente. Scope: notes:read.
| Query | Significato |
|---|---|
since | Solo le note da questo momento in poi: YYYY-MM-DD o ISO 8601 |
until | Solo le note fino a questo momento (YYYY-MM-DD indica la fine di quel giorno) |
occasion | Solo le note scritte per questa occasione, per esempio sales_call |
participant_email | Solo le note in cui questo indirizzo era invitato |
q | Parole da cercare nel titolo, nel riepilogo e negli argomenti |
limit | Da 1 a 100, predefinito 25 |
cursor | Il next_cursor della pagina precedente |
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 è "" nell'ultima pagina. I cursori sono opachi; rimandali indietro invariati.
GET /notes/find
Trova le note per titolo, email di un partecipante o data (almeno uno). Risponde con un elenco, al massimo 10, dalla più recente, e [] quando nulla corrisponde. Scope: notes:read.
| Query | Significato |
|---|---|
title | Parole nel titolo (maiuscole e minuscole non contano) |
participant_email | Un indirizzo che era invitato |
date | Il giorno della nota, 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}
Una nota. Scope: notes:read. 404 not_found per un id che non esiste, non appartiene a questo account, è ancora in scrittura o è una nota sulla salute.
curl https://app.parleynotes.com/api/v1/notes/meet_1761213600000123 -H "Authorization: Bearer pn_at_..."
Risponde con l'oggetto nota.
POST /notes
Crea una nota da un testo o da un link audio. Scope: notes:write. Invia esattamente uno tra text e audio_url.
| Campo | Tipo | Significato |
|---|---|---|
text | string | Una trascrizione, un'email o qualsiasi testo, fino a 120.000 caratteri |
audio_url | string | Un link http o https a un file audio o a un episodio di podcast (Apple Podcasts, Spotify, un feed RSS o una pagina di podcast) |
title | string | Facoltativo. Senza, Parley Notes dà un nome alla nota |
folder | string | Facoltativo. La cartella di Parley Notes in cui archiviarla |
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"}'
Risponde entro pochi secondi con 202 Accepted:
{ "id": "meet_1761213600000123", "status": "processing" }
Poi Parley Notes trascrive (per l'audio) e scrive il riepilogo in background, il che può richiedere qualche minuto per una registrazione lunga. Quando la nota è pronta compare nell'account Parley Notes della persona con questo id, e l'hook note.ready scatta con essa. Le importazioni contano sui limiti dell'account come qualsiasi importazione nell'app: un riepilogo usa la quota del piano, e un link audio richiede un piano a pagamento una volta esaurite le importazioni gratuite dell'account.
| Rifiuto | Risposta |
|---|---|
Entrambi o nessuno tra text e audio_url, oppure un URL non valido | 400 invalid_request |
text oltre 120.000 caratteri | 413 too_large |
| Audio con un piano gratuito senza importazioni gratuite rimaste | 402 plan_required |
| Il limite giornaliero di importazioni dell'account, o 30 nuove note in un'ora | 429 daily_limit o rate_limited, con Retry-After |
Se l'importazione stessa fallisce più tardi (un link irraggiungibile, nessun parlato), non viene creata alcuna nota e nessun hook scatta. Se il riepilogo fallisce, la nota viene salvata con la sua trascrizione e aspetta nell'app che la persona la riassuma.
GET /action-items
Le azioni aperte in tutte le note, una riga per voce, dalla nota più recente. Scope: notes:read.
| Query | Significato |
|---|---|
since | Solo le voci delle note da questo momento in poi |
owner_email | Solo le voci il cui responsabile è questo indirizzo |
limit, cursor | Come per 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
Invece di fare polling, iscrivi un URL e Parley Notes invia una POST su di esso.
| Evento | Quando | Corpo |
|---|---|---|
note.ready | Viene scritto il primo riepilogo di una nota (non un riepilogo successivo) | L'oggetto nota |
action_item.created | Nello stesso momento, una volta per ogni azione aperta di quella nota | La riga dell'azione |
Iscrizione: POST /hooks
Scope: hooks. target_url deve essere https su un host pubblico.
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 account può avere al massimo 100 iscrizioni.
Annullamento: DELETE /hooks/{id}
Scope: hooks. Risponde 200 {"id": "hk_Q2x9...", "deleted": true}, oppure "deleted": false quando era già sparita (annullare due volte non è un errore).
Dati di esempio: GET /hooks/sample?event=
Scope: notes:read. Gli ultimi tre, esattamente nella forma che invia l'hook: note per note.ready, righe di azioni per action_item.created. Zapier lo usa per mostrare dati di esempio mentre si configura uno Zap.
curl "https://app.parleynotes.com/api/v1/hooks/sample?event=action_item.created" -H "Authorization: Bearer pn_at_..."
Consegna
POSTconContent-Type: application/jsoneUser-Agent: ParleyNotes-Hooks/1; un evento per richiesta.- Qualsiasi 2xx significa consegnato.
- 410 Gone rimuove l'iscrizione; non viene più inviato nulla.
- 429 viene ritentato dopo il suo
Retry-After. - 5xx, un timeout (10 secondi) o un errore di rete vengono ritentati dopo 2 secondi, 10 secondi e 60 secondi, poi si rinuncia.
- Qualsiasi altro 4xx viene abbandonato subito.
- Parley Notes non invia mai più veloce di 30 richieste al secondo né più di 10.000 in cinque minuti; oltre, le consegne aspettano.
- Una nota sulla salute non fa mai scattare un hook. Quando la persona scollega la tua app, le sue iscrizioni si fermano subito.
5. Limiti di frequenza
| Limite | Valore | Oltre il limite |
|---|---|---|
| Richieste per connessione | 120 al minuto | 429 rate_limited con Retry-After (secondi) |
| Nuove note per account | 30 all'ora | 429 rate_limited con Retry-After |
| Importazioni audio | il limite giornaliero dell'account (condiviso con l'app) | 429 daily_limit con Retry-After |
Aspetta i secondi indicati da Retry-After, poi riprova.
6. Errori
Ogni errore dell'API (tranne il token endpoint di OAuth, che segue il formato proprio di OAuth) è:
{ "error": { "code": "not_found", "message": "No note with that id, or it is still being written." } }
| Stato | code | Significato |
|---|---|---|
| 400 | invalid_request | Un parametro manca o non è valido; message dice quale |
| 401 | invalid_token | Nessun token, oppure è sconosciuto, scaduto o revocato. Rinnovalo e riprova. Arriva con WWW-Authenticate |
| 402 | plan_required | Il piano dell'account non lo include |
| 403 | insufficient_scope | Il token è valido ma non ha lo scope che serve a questo endpoint. Collegati di nuovo con quello scope |
| 404 | not_found | Nota o endpoint inesistente |
| 413 | too_large | Il testo è troppo lungo |
| 429 | rate_limited, daily_limit, too_many_hooks | Si è raggiunto un limite; vedi Retry-After |
| 500 | server_error | Qualcosa è andato storto da parte nostra. Riprova |
7. Versionamento
La versione è nel percorso: /api/v1. All'interno di v1, Parley Notes può aggiungere endpoint, parametri di query, campi nelle risposte ed eventi hook; il tuo codice deve ignorare ciò che non conosce. Rimuovere o rinominare un campo, cambiarne il tipo o cambiare ciò che fa un endpoint significa una nuova versione (/api/v2), e v1 continua a funzionare per almeno 12 mesi dopo l'annuncio di v2.
Domande o un client id per la tua app: scrivi al team di Parley Notes tramite la pagina di assistenza.