Consultando a trilha de auditoria e decidindo aprovações pendentes
Toda ação sensível em uma Organização deixa rastro, e algumas ações só entram em vigor depois que uma segunda pessoa dá o aval. Este tutorial mostra como ler e exportar a trilha de auditoria, e depois como decidir uma aprovação pendente.
As duas áreas exigem uma sessão de um Membro com a permissão certa: ler a trilha de auditoria pede audit:read, e decidir aprovações pede a permissão de gerenciamento de roles.
Filtrando a trilha de auditoria
GET /v1/audit-events retorna os eventos da sua Organização, do mais recente para o mais antigo. Você nunca passa um id de organização: a Organização usada é sempre a vinculada à sua sessão. Filtre por qualquer combinação de tipo de evento, sujeito e uma janela de data.
const orgId = "018f2f3a-6000-7000-9c3a-1f2b3c4d5e6f";
const token = process.env.ROLLFUSE_SESSION_TOKEN;
const params = new URLSearchParams({
event_type: "role.granted",
subject_type: "member",
occurred_after: "2026-08-01T00:00:00Z",
occurred_before: "2026-09-01T00:00:00Z",
limit: "50",
});
const auditRes = await fetch(
`https://api.rollfuse.com/v1/audit-events?${params}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const { audit_events, limit, offset } = await auditRes.json();
audit_events.forEach((event) =>
console.log(event.event_type, event.subject_id, event.actor)
);
A resposta devolve a paginação que foi realmente aplicada, então se você não passar limit, dá para ler o valor padrão direto da resposta em vez de tentar adivinhar. Uma janela invertida (occurred_after depois de occurred_before) ou um timestamp mal formado é rejeitada de cara, em vez de simplesmente devolver uma lista vazia.
Exportando a trilha
Quando você precisa da trilha completa para uma revisão de compliance, em vez de uma fatia paginada, exporte. O endpoint respeita os mesmos filtros da listagem, mas ignora a paginação e devolve um único documento.
const exportRes = await fetch(
`https://api.rollfuse.com/v1/audit-events/export?format=csv&occurred_after=2026-08-01T00:00:00Z`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const csv = await exportRes.text();
format tem csv como padrão; passe format=json se preferir já receber algo pronto para parsear. No CSV, a coluna payload de cada linha carrega o documento JSON do evento como um campo entre aspas, então quem consome o arquivo ainda precisa fazer o parse dessa coluna como JSON, mesmo o arquivo em si sendo CSV.
Decidindo uma aprovação pendente
Algumas ações, como conceder a role admin a um Membro, não entram em vigor na hora: elas geram um ApprovalRequest em vez disso. Liste as que ainda esperam uma decisão:
const pendingRes = await fetch(
"https://api.rollfuse.com/v1/approval-requests",
{ headers: { Authorization: `Bearer ${token}` } }
);
const pending = await pendingRes.json();
Cada item traz requested_by_member_id e o target_member_id a quem a mudança se aplicaria. Aprove ou rejeite pelo id, usando uma sessão de um Membro diferente de quem solicitou:
const decisionRes = await fetch(
`https://api.rollfuse.com/v1/approval-requests/${pending[0].id}/approve`,
{ method: "POST", headers: { Authorization: `Bearer ${token}` } }
);
const decided = await decisionRes.json();
console.log(decided.status); // "approved"
Troque o trecho final da URL para reject se quiser descartar a solicitação; rejeitar nunca cria a atribuição de role que a solicitação pedia. Duas proteções são aplicadas no servidor: quem decide não pode ser quem solicitou a mudança, e uma solicitação já decidida não pode ser decidida de novo. Os dois casos voltam como conflito em vez de simplesmente ter sucesso duas vezes.