Skip to Content
Browse the Docs▾

Pull Results Into Reporting

Read the scoreboard Revnu reads, plus workflows and run history, into your own dashboards, and post a weekly Slack summary of sends, replies, reply rate and who replied. Or ask Revnu to post it for you, with no code.

GET /api/v1/results returns the scoreboard Revnu wakes up with: per-channel sections for email, outbound, LinkedIn, ads, SEO, AI answers and social, over a window ending now. A token with results:read reads it; add leads:read for lead-level detail. Neither can cause any work.

Don't write code? Skip to No code: ask Revnu. Revnu can post the same weekly numbers to Slack for you.

No code: ask Revnu

If you want the numbers in a Slack channel every week and nothing else, you don't need the API. Ask Revnu in chat:

Every Monday at 9am, post last week's sends, replies, reply rate and who replied to #sales.

Revnu sets it up as a workflow, confirms the schedule back to you, and posts at that time every week whether or not anything moved. It can post in your Revnu channel or another Slack channel you name. You'll find it under Dashboard > Workflows and change it by asking in chat. More in Recurring Work With Workflows, Daily Updates and the Monday Report and, for code, Create a workflow.

Build the API version below when you want the numbers next to your other metrics, in a warehouse, or in a format you control.

Available or not, never a fake zero

Each section is either { "available": true, "data": {…} } or { "available": false, "reason": "…" }. Zero and unknown are different numbers and the API never turns one into the other. Render an unavailable section as "not connected" or "not tracked", not as 0. A section can also carry caveats, such as a count that hit a read cap.

Windows

since is epoch milliseconds and is clamped to between 31 days and one hour ago; the default is 24 hours. Every section also has an equal-length baseline window before it, so email.data.sentBaseline is last period's sends. Pull once an hour or once a day into your warehouse and you have everything Revnu sees.

A Monday Slack post of sends, replies and reply rate

The email section has what a weekly report needs:

Number Where
Emails sent email.data.sent (last period: email.data.sentBaseline)
People who replied email.data.replies.data.replies
Bounces email.data.replies.data.bounces
Who replied email.data.replies.data.repliedContacts: the newest five, each { who, company, agoDays, intent? }
Drafts waiting for you email.data.draftsAwaiting

Reply rate is yours to compute: replies over sends. Replies are counted by when they arrived, so a reply in this window can answer an email sent last week. When replies.available is false, the reply count is unknown, not zero, so report it as unknown.

// Run every Monday at 09:00, for example from a cron job or a scheduled function.
const WEEK = 7 * 24 * 60 * 60 * 1000;
const res = await fetch(`https://revnu.com/api/v1/results?since=${Date.now() - WEEK}`, {
  headers: { Authorization: `Bearer ${process.env.REVNU_API_TOKEN}` },
});
const { results } = await res.json();

let text: string;
if (!results.email.available) {
  text = `Email: not available (${results.email.reason})`;
} else {
  const { sent } = results.email.data;
  const r = results.email.data.replies;
  const replies = r.available ? r.data.replies : null;
  const rate = replies !== null && sent > 0 ? `${((replies / sent) * 100).toFixed(1)}%` : "n/a";
  const who = r.available
    ? (r.data.repliedContacts ?? []).map((c) => `${c.who} (${c.company})`).join(", ")
    : "";
  text = `Last 7 days: ${sent} sent, ${replies ?? "unknown"} replied, reply rate ${rate}.${who ? `\nReplied: ${who}` : ""}`;
}

await fetch(process.env.SLACK_WEBHOOK_URL!, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ text }),
});

SLACK_WEBHOOK_URL is an incoming webhook you create in your own Slack workspace.

With daily updates on, Revnu's own Monday check-in is already a weekly roll-up, sent wherever you talk to Revnu. Build this when you want the numbers in a channel of your choosing or next to your other metrics.

Everyone who replied, not just the newest five

repliedContacts stops at five. For the full list, page through GET /leads?status=replied with a leads:read token. Leads come newest first by when Revnu created them, not by when they replied, so a reply on a lead from weeks ago can sit several pages down. Page to the end every time and keep the ids you've already reported.

const seen = new Set<string>(await loadReportedIds()); // ids you reported last time
const fresh: Array<{ company: string; who: string | null }> = [];
let cursor: string | null = null;
do {
  const url = new URL("https://revnu.com/api/v1/leads");
  url.searchParams.set("status", "replied");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.REVNU_API_TOKEN}` },
  });
  const page = await res.json();
  for (const lead of page.leads) {
    if (!seen.has(lead.id)) fresh.push({ company: lead.companyName, who: lead.contact?.name ?? null });
  }
  cursor = page.nextCursor;
} while (cursor);

Each lead carries its primary contact and a replyKind. The reply text itself isn't in the API; read it in Inbox.

Workflows and runs

GET /api/v1/workflows lists recurring workflows with their schedule, next run and steps. GET /api/v1/workflows/{id}/runs is the run history with per-step outcomes and found: { leads, contacts, people }, newest first, so a failed step shows up in your monitoring the same hour it happens. List one run's leads with GET /leads?workflowRunId=.

Frequently Asked Questions

Is this the same data as the dashboard?

Yes. Both read the same results window, so the number in your report matches the number Revnu reports to you.

How do I calculate reply rate from the API?

Divide email.data.replies.data.replies by email.data.sent for the same window. Check both sections are available first; an unavailable section is unknown, not zero.

Can I get more than 31 days?

Each call covers up to 31 days. Pull daily and keep your own history for longer trends.

Can Revnu post a weekly report to Slack without code?

Yes. Ask in chat: > Every Monday at 9am, post last week's sends, replies, reply rate and who replied to #sales. Revnu sets it up as a workflow. See Recurring Work With Workflows.

What does replies.available false mean?

That Revnu couldn't count replies for that window, so the number is unknown. Report it as unknown, not 0.

Which scopes does a reporting token need?

results:read, plus leads:read for lead and reply detail. Neither can send, publish, run or spend.