API do Parley Notes, versão 1.Leia notas, crie notas e saiba quando uma estiver pronta.
A API do Parley Notes permite que um app que você conecta leia as suas notas de reunião, crie notas a partir de texto ou áudio e seja avisado no momento em que uma nota fica pronta. É a base da integração do Parley Notes com o Zapier, e qualquer app registrado no Parley Notes pode usá-la da mesma forma.
- URL base:
https://app.parleynotes.com/api/v1 - Formato: JSON na entrada e na saída, UTF-8. Envie
Content-Type: application/jsonquando houver um corpo. - Autenticação: OAuth 2.0, authorization code grant. Toda chamada leva
Authorization: Bearer <access token>. - Notas de saúde nunca são retornadas. Uma nota escrita como conversa de saúde (uma consulta médica, uma sessão de terapia, uma nota em uma pasta analisada como médica) não é listada, encontrada, lida nem enviada a um hook, por nenhum endpoint.
1. Autenticação
Os apps são registrados manualmente: o Parley Notes dá a cada app um client id e um client secret (escreva para a equipe do Parley Notes para registrar um). Não há cadastro por conta própria para esta API.
Scopes
| Scope | Permite |
|---|---|
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} |
Peça vários scopes separados por espaços (vírgulas também funcionam). Se você não pedir nenhum, os três são concedidos.
Passo 1: envie a pessoa para autorizar
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
A pessoa entra no Parley Notes (com o login de sempre) e vê o que o seu app pede. Se ela permitir, o Parley Notes redireciona para o seu redirect_uri com um código e o seu state exatamente como você o enviou:
https://your.app/oauth/callback?code=pn_code_...&state=YOUR_STATE
Se ela cancelar: ?error=access_denied&error_description=...&state=YOUR_STATE. O redirect_uri precisa ser um dos registrados para o seu app. O PKCE (code_challenge com code_challenge_method=S256) é suportado e verificado quando você o envia.
Passo 2: troque o código (em até 5 minutos, uma só vez)
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
O client pode se autenticar com HTTP Basic em vez dos dois campos do corpo. Corpos em JSON também são aceitos.
{
"access_token": "pn_at_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "pn_rt_...",
"scope": "notes:read notes:write hooks"
}
Passo 3: chame a API
curl https://app.parleynotes.com/api/v1/me -H "Authorization: Bearer pn_at_..."
Renovação
Os access tokens duram uma hora. Quando uma chamada responde 401, renove e tente de novo:
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
A resposta é um novo par. Os refresh tokens são rotativos: guarde o novo refresh token e descarte o antigo. Reusar um refresh token antigo mais de um minuto depois de ele ser trocado encerra a conexão (é tratado como uma cópia roubada); duas renovações simultâneas dentro desse minuto dão certo as duas. Um refresh token sem uso por 90 dias expira.
| Situação | Resposta |
|---|---|
| Access token ausente, desconhecido, expirado ou revogado | 401 invalid_token, com WWW-Authenticate: Bearer ... (nunca 403) |
| Refresh token desconhecido, expirado, reutilizado ou revogado | 400 {"error": "invalid_grant"} |
Código desconhecido, usado, expirado, ou outro redirect_uri | 400 {"error": "invalid_grant"} |
| Client id ou client secret errado no token endpoint | 401 {"error": "invalid_client"} |
Revogação
curl -X POST https://app.parleynotes.com/api/v1/oauth/revoke -d token=pn_rt_...
Sempre responde 200; a conexão termina. A pessoa também pode desconectar o seu app a qualquer momento no Parley Notes, em Configurações, Conexões, Apps conectados; os tokens dele param de funcionar na hora e os hooks dele são interrompidos.
2. O objeto de nota
Toda nota tem todas as chaves abaixo em toda resposta. Um valor vazio é "" (texto), [] (lista) ou 0 (duração), nunca null, então um campo mapeado em um fluxo de trabalho nunca desaparece.
| Campo | Tipo | O que é |
|---|---|---|
id | string | O id da nota |
title | string | O título da nota |
date_iso | string | Quando a nota foi gravada ou criada, ISO 8601 em UTC |
duration_min | integer | Duração em minutos (0 para uma nota que não foi falada) |
occasion | string | Com que ocasião a nota foi escrita, por exemplo sales_call, standup, minutes, one_on_one |
summary_text | string | O resumo, em texto simples |
summary_html | string | O resumo em HTML simples (parágrafos, listas, negrito) |
share_url | string | Link que abre a nota no Parley Notes (para o dono dela) |
participant_emails | string[] | Endereços de e-mail das pessoas convidadas, em minúsculas |
participant_names | string[] | Nomes das pessoas que falaram ou foram convidadas |
action_items | object[] | {text, owner_name, owner_email, due_date} cada um; due_date é YYYY-MM-DD |
decisions | string[] | Decisões tomadas |
next_steps | string[] | O próximo passo combinado primeiro (com a data, quando uma foi dita) e depois os follow-ups |
participant_emails_text | string | participant_emails unidos com , |
participant_names_text | string | participant_names unidos com , |
action_items_text | string | Uma linha por item: - text (owner, email; due YYYY-MM-DD) |
decisions_text | string | Uma linha por decisão, começando com - |
next_steps_text | string | Uma linha por próximo passo, começando com - |
O e-mail de um responsável só é preenchido quando o responsável corresponde a alguém do convite; ele nunca é adivinhado.
{
"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"
}
A linha do item de ação
GET /action-items e o hook action_item.created dão uma linha por item de ação em aberto:
| Campo | Tipo | O que é |
|---|---|---|
id | string | noteId:itemId, estável para o mesmo item |
text, owner_name, owner_email, due_date | string | Como no objeto de nota |
priority | string | low, medium, high, ou "" quando a conversa não disse |
note_id, note_title, note_date_iso, share_url | string | A nota de onde veio |
{
"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
As listas e buscas cobrem as 500 notas mais recentes da conta. Uma nota que ainda está sendo escrita não é retornada até o resumo ficar pronto.
GET /me
De quem é o token. Scope: qualquer um.
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 ou power.
GET /notes
As notas, das mais recentes para as mais antigas. Scope: notes:read.
| Query | Significado |
|---|---|
since | Só notas a partir deste momento: YYYY-MM-DD ou ISO 8601 |
until | Só notas até este momento (YYYY-MM-DD significa o fim desse dia) |
occasion | Só notas escritas com esta ocasião, por exemplo sales_call |
participant_email | Só notas em que este endereço foi convidado |
q | Palavras a procurar no título, no resumo e nos tópicos |
limit | De 1 a 100, padrão 25 |
cursor | O next_cursor da página anterior |
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 é "" na última página. Os cursors são opacos; envie-os de volta sem alterar.
GET /notes/find
Encontre notas por título, e-mail de participante ou data (pelo menos um). Responde com uma lista, no máximo 10, das mais recentes para as mais antigas, e [] quando nada corresponde. Scope: notes:read.
| Query | Significado |
|---|---|
title | Palavras no título (maiúsculas e minúsculas não importam) |
participant_email | Um endereço que foi convidado |
date | O dia da 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}
Uma nota. Scope: notes:read. 404 not_found para um id que não existe, não é desta conta, ainda está sendo escrito ou é uma nota de saúde.
curl https://app.parleynotes.com/api/v1/notes/meet_1761213600000123 -H "Authorization: Bearer pn_at_..."
Responde com o objeto de nota.
POST /notes
Crie uma nota a partir de texto ou de um link de áudio. Scope: notes:write. Envie exatamente um entre text e audio_url.
| Campo | Tipo | Significado |
|---|---|---|
text | string | Uma transcrição, um e-mail ou qualquer texto, com até 120.000 caracteres |
audio_url | string | Um link http ou https para um arquivo de áudio ou um episódio de podcast (Apple Podcasts, Spotify, um feed RSS ou uma página de podcast) |
title | string | Opcional. Sem ele, o Parley Notes dá um nome à nota |
folder | string | Opcional. A pasta do Parley Notes onde arquivá-la |
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"}'
Responde em segundos com 202 Accepted:
{ "id": "meet_1761213600000123", "status": "processing" }
Depois o Parley Notes transcreve (no caso de áudio) e escreve o resumo em segundo plano, o que pode levar alguns minutos para uma gravação longa. Quando a nota fica pronta, ela aparece no Parley Notes da pessoa com este id, e o hook note.ready dispara com ela. As importações contam nos limites da conta como qualquer importação no app: um resumo usa a franquia do plano, e um link de áudio exige um plano pago quando as importações grátis da conta acabam.
| Recusa | Resposta |
|---|---|
Os dois ou nenhum entre text e audio_url, ou uma URL inválida | 400 invalid_request |
text com mais de 120.000 caracteres | 413 too_large |
| Áudio em um plano gratuito sem importações grátis restantes | 402 plan_required |
| O limite diário de importações da conta, ou 30 notas novas em uma hora | 429 daily_limit ou rate_limited, com Retry-After |
Se a importação em si falhar mais tarde (um link inacessível, sem fala), nenhuma nota é criada e nenhum hook dispara. Se o resumo falhar, a nota é salva com a transcrição e espera no app para a pessoa resumir.
GET /action-items
Os itens de ação em aberto de todas as notas, uma linha por item, da nota mais recente para a mais antiga. Scope: notes:read.
| Query | Significado |
|---|---|
since | Só itens de notas a partir deste momento |
owner_email | Só itens cujo responsável é este endereço |
limit, cursor | Como em 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
Em vez de consultar de tempos em tempos (polling), assine uma URL e o Parley Notes envia um POST para ela.
| Evento | Quando | Corpo |
|---|---|---|
note.ready | O primeiro resumo de uma nota é escrito (não um resumo refeito depois) | O objeto de nota |
action_item.created | No mesmo momento, uma vez para cada item de ação em aberto dessa nota | A linha do item de ação |
Assinar: POST /hooks
Scope: hooks. O target_url precisa ser https em um host público.
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" }
Uma conta pode ter no máximo 100 assinaturas.
Cancelar a assinatura: DELETE /hooks/{id}
Scope: hooks. Responde 200 {"id": "hk_Q2x9...", "deleted": true}, ou "deleted": false quando já não existia (cancelar a assinatura duas vezes não é um erro).
Dados de exemplo: GET /hooks/sample?event=
Scope: notes:read. Os três mais recentes, exatamente no formato que o hook envia: notas para note.ready, linhas de itens de ação para action_item.created. O Zapier usa isso para mostrar dados de exemplo enquanto um Zap é configurado.
curl "https://app.parleynotes.com/api/v1/hooks/sample?event=action_item.created" -H "Authorization: Bearer pn_at_..."
Entrega
POSTcomContent-Type: application/jsoneUser-Agent: ParleyNotes-Hooks/1; um evento por requisição.- Qualquer 2xx significa entregue.
- 410 Gone remove a assinatura; nada mais é enviado a ela.
- 429 é tentado de novo depois do seu
Retry-After. - 5xx, um timeout (10 segundos) ou uma falha de rede é tentado de novo após 2 segundos, 10 segundos e 60 segundos, e depois é abandonado.
- Qualquer outro 4xx é abandonado de imediato.
- O Parley Notes nunca envia mais rápido do que 30 requisições por segundo nem mais de 10.000 em cinco minutos; acima disso, as entregas esperam.
- Uma nota de saúde nunca dispara um hook. Quando a pessoa desconecta o seu app, as assinaturas dele param na hora.
5. Limites de uso
| Limite | Valor | Ao passar dele |
|---|---|---|
| Requisições por conexão | 120 por minuto | 429 rate_limited com Retry-After (segundos) |
| Notas novas por conta | 30 por hora | 429 rate_limited com Retry-After |
| Importações de áudio | o limite diário da conta (compartilhado com o app) | 429 daily_limit com Retry-After |
Espere os segundos de Retry-After e tente de novo.
6. Erros
Todo erro da API (fora do token endpoint do OAuth, que segue o formato próprio do OAuth) é:
{ "error": { "code": "not_found", "message": "No note with that id, or it is still being written." } }
| Status | code | Significado |
|---|---|---|
| 400 | invalid_request | Um parâmetro está ausente ou é inválido; message diz qual |
| 401 | invalid_token | Sem token, ou ele é desconhecido, expirou ou foi revogado. Renove e tente de novo. Vem com WWW-Authenticate |
| 402 | plan_required | O plano da conta não inclui isto |
| 403 | insufficient_scope | O token é válido, mas não recebeu o scope de que este endpoint precisa. Conecte de novo com ele |
| 404 | not_found | Essa nota não existe, ou esse endpoint não existe |
| 413 | too_large | O texto é longo demais |
| 429 | rate_limited, daily_limit, too_many_hooks | Um limite foi atingido; veja Retry-After |
| 500 | server_error | Algo falhou do nosso lado. Tente de novo |
7. Versionamento
A versão fica no caminho: /api/v1. Dentro da v1, o Parley Notes pode adicionar endpoints, parâmetros de query, campos nas respostas e eventos de hook; o seu código deve ignorar o que não conhece. Remover ou renomear um campo, mudar o tipo dele ou mudar o que um endpoint faz significa uma nova versão (/api/v2), e a v1 continua funcionando por pelo menos 12 meses depois de a v2 ser anunciada.
Dúvidas ou um client id para o seu app: escreva para a equipe do Parley Notes pela página de suporte.