Synergy Connect

Documentação

Paginação

As rotas que devolvem listas (conversas, mensagens, contatos) são paginadas por cursor. Um cursor é um texto opaco que a API devolve e que você repassa para pedir a página seguinte. Não monte, não interprete e não guarde cursores por muito tempo: um cursor alterado responde 400.

Como funciona#

RotaPede a próxima página comOnde vem o cursor
GET …/conversationsafterpaging.after
POST …/conversations/searchafter no corpopaging.after
POST …/contacts/searchafter no corpopaging.after
GET …/conversations/{conversation_id}/messagesbeforepaging.before

Em todas, limit vai de 1 a 50 (padrão 20). Quando paging.after (ou paging.before) é null, não há mais páginas.

Primeira página:

Próxima página:

As mensagens de uma conversa andam para trás no tempo: a primeira página é a mais nova, e before traz as mais antigas.

Exemplo
curl 'https://api.synergyconnect.com.br/v1/numbers/106540352242922/conversations?limit=20' \
  -H "Authorization: Bearer $SYNERGY_API_KEY"
JSON
{
  "data": [ { "id": "4182", "wa_id": "5511999999999", "name": "Maria Souza", "status": "pending", "unread": 2, "automation": null, "window_expires_at": "1767312000", "last_message": { "direction": "in", "preview": "Oi, meu pedido chegou?", "timestamp": "1767225600" } } ],
  "paging": { "after": "WzE3NjcyMjU2MDAwMDAsNDE4Ml0" },
  "rev": 9120
}
Exemplo
curl 'https://api.synergyconnect.com.br/v1/numbers/106540352242922/conversations?limit=20&after=WzE3NjcyMjU2MDAwMDAsNDE4Ml0' \
  -H "Authorization: Bearer $SYNERGY_API_KEY"
Exemplo
curl 'https://api.synergyconnect.com.br/v1/numbers/106540352242922/conversations/4182/messages?limit=20&before=WzE3NjcyMjU1OTAwMDAsODEyXQ' \
  -H "Authorization: Bearer $SYNERGY_API_KEY"

Página curta com cursor: continue#

Cada chamada examina no máximo 500 conversas ou contatos (200 mensagens) e para. Com um filtro ou uma busca que casa pouco, isso pode acontecer antes de a página encher. Nesse caso a resposta traz o que achou, mesmo que sejam poucos itens ou nenhum, e um paging.after diferente de null: significa "continue daqui".

Por isso a regra do laço é só parar quando o cursor vier null, nunca quando a página vier menor que o limit:

No SDK, for await (const c of wa.conversations.list()) faz isso por você.

Exemplo

JavaScript

async function* allConversations(phoneNumberId, status = 'active') {
  let after = null;
  do {
    const url = new URL(`https://api.synergyconnect.com.br/v1/numbers/${phoneNumberId}/conversations`);
    url.searchParams.set('status', status);
    url.searchParams.set('limit', '50');
    if (after) url.searchParams.set('after', after);
    const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.SYNERGY_API_KEY}` } });
    if (!res.ok) throw new Error(`HTTP ${res.status}`); // 429: espere o Retry-After
    const page = await res.json();
    yield* page.data;
    after = page.paging.after;
  } while (after);
}

for await (const conversa of allConversations('106540352242922')) {
  console.log(conversa.id, conversa.name);
}

Python

import os
import time

import requests


def all_conversations(phone_number_id, status="active"):
    after = None
    while True:
        params = {"status": status, "limit": 50}
        if after:
            params["after"] = after
        res = requests.get(
            f"https://api.synergyconnect.com.br/v1/numbers/{phone_number_id}/conversations",
            params=params,
            headers={"Authorization": f"Bearer {os.environ['SYNERGY_API_KEY']}"},
        )
        if res.status_code == 429:
            time.sleep(int(res.headers.get("Retry-After", "60")))
            continue
        res.raise_for_status()
        page = res.json()
        yield from page["data"]
        after = page["paging"]["after"]
        if not after:
            return

Custo e limites#

Cada página conta nos limites de leitura: 30 páginas por minuto e 1.000 por dia, por chave e número (Ler conversas). Percorrer tudo a cada ciclo gasta o teto à toa. Para manter uma cópia atualizada, use conversations/changes com o rev e um webhook, e reserve a paginação completa para a carga inicial.

Um limite batido responde 429 com Retry-After; espere e continue do mesmo cursor.

Cursores inválidos#

SituaçãoResposta
Cursor alterado, truncado ou que não é de uma lista desta rota400, código 100, "Invalid cursor"
Cursor de uma lista com outro filtroPode devolver resultados inesperados: recomece sem cursor ao mudar status ou o termo da busca

Cursores nunca causam erro 5xx. Em dúvida, descarte o cursor e recomece.

Listas sem cursor#

GET /v1/numbers e GET …/templates devolvem { "data": [...] } sem paging. Nos modelos, use limit (até 100) e os filtros status, name (prefixo) e language para reduzir o resultado.

Ficou com dúvida? Escreva para suporte@synergyconnect.com.br.