Get results
The growth scoreboard for a window ending now: per-channel sections for email, outbound, LinkedIn, SEO, AI answers and ads, each available with data or unavailable with a reason.
The same scoreboard Revnu reads every time it wakes. Read-only: nothing this route returns can be changed through it.
curl -H "Authorization: Bearer $REVNU_API_TOKEN" "https://revnu.com/api/v1/results?since=1789000000000"Query
| Param | Meaning |
|---|---|
since |
Start of the window, epoch milliseconds, clamped to between 31 days and one hour ago. Default 24 hours ago. |
Response
{
"results": {
"window": { "from": 1789000000000, "to": 1789604800000 },
"baseline": { "from": 1788395200000, "to": 1789000000000 },
"harness": { "available": true, "data": { } },
"email": {
"available": true,
"data": {
"sent": 120,
"sentBaseline": 96,
"draftsAwaiting": 4,
"tracking": { "available": false, "reason": "tracking_off" },
"replies": {
"available": true,
"data": {
"replies": 7,
"bounces": 2,
"repliedContacts": [{ "who": "Jo Park", "company": "Northwind", "agoDays": 1, "intent": "interested" }]
}
}
}
},
"outbound": { "available": true, "data": { "routes": [ ] } },
"linkedin": {
"available": true,
"data": {
"invites": 14,
"health": { "needsReauth": false, "pausedUntil": null, "pauseReason": null, "inviteHeadroom": 6 },
"replies": { "available": true, "data": { "count": 3 } }
}
},
"seo": {
"available": true,
"data": { "postsPublished": 2, "postsHeld": 1, "postsFailed": 0, "views": 340 }
},
"aeo": { "available": true, "data": { } },
"ads": { "available": false, "reason": "no_campaigns" }
}
}The numbers above are an example of the shape, not real figures, and some fields are left out to keep it short. The tables below list every field. baseline is the equal-length window just before window, for comparisons such as sent against sentBaseline.
Each channel section is { "available": true, "data": {…} }, optionally with caveats, or { "available": false, "reason": "…" }. Zero and unknown are different numbers.
| Field | Meaning |
|---|---|
sent |
Emails sent in the window |
sentBaseline |
Emails sent in the baseline window |
draftsAwaiting |
Email drafts waiting in the review queue |
tracking |
Opens and clicks, a section of its own: unavailable with tracking_off when no tracking domain is set up or tracking is turned off |
replies.data.replies |
People who replied in the window, counted by when the reply arrived. Automatic replies are left out. |
replies.data.bounces |
Emails that bounced in the window |
replies.data.repliedContacts |
The newest five replies: who, company, agoDays, and intent when Revnu has read the reply |
replies.data.byIntent |
Replies grouped by intent, when at least one has been classified |
Reply rate is not a field: divide replies by sent. For everyone who replied, list GET /leads?status=replied.
The LinkedIn section reads the workspace owner's connected LinkedIn account. Counts are for the window unless the table says otherwise.
| Field | Meaning |
|---|---|
invites |
Connection requests sent in the window. Requests LinkedIn turned away because you were already connected or already invited are left out. |
alreadyConnectedHits |
Requests that hit that already-connected or already-invited wall |
newDMs |
Messages that started a new conversation |
chatReplies |
Messages sent into a conversation that already existed |
inmails |
InMails sent |
baseline |
{ invites, dms, inmails } for the baseline window, where dms is newDMs plus chatReplies |
health.needsReauth |
true when the LinkedIn connection has expired. Reconnect it in the dashboard. |
health.pausedUntil |
Epoch milliseconds when Revnu's LinkedIn pause ends, or null when it isn't paused. Live state, not windowed. |
health.pauseReason |
A short plain-text reason for the pause, such as a rate limit or several provider errors in a row, or null |
health.inviteHeadroom |
Connection requests Revnu can still send today: the smaller of what is left of today's limit and this week's |
replies.data.count |
Conversations that got a reply in the window, counted by when the reply arrived |
accepts.data.count |
Connection requests accepted in the window, counted by when Revnu saw the connection |
scoreboard |
All-time requests and acceptances by list, { label, invites, maturedInvites, accepts } each. maturedInvites counts requests at least 7 days old plus accepted ones, a fair base for an acceptance rate. |
Why LinkedIn pauses and when it resumes is in Why Did LinkedIn Sending Stop?. For one person's connection and conversation, use GET /linkedin/person.
SEO
The SEO section is about the blog Revnu writes for. postsPublished and postsHeld count only posts Revnu wrote, not ones you added yourself.
| Field | Meaning |
|---|---|
postsPublished |
Posts Revnu wrote that were published or exported in the window |
postsHeld |
Posts waiting for your review right now. Live, not windowed. |
postsFailed |
Posts started in the window that failed. A count only: the cause isn't returned. |
refreshes |
{ applied, skipped }: updates to live posts Revnu applied or skipped in the window |
views |
Views of your blog posts in the window. viewsPrev is the baseline window. |
genCostCents |
Revnu's estimated cost of writing the posts it finished in the window, in cents |
gsc |
Search Console clicks and impressions, a section of its own: { clicks, impressions, prevClicks, from, through, ourPosts }. Unavailable with not_connected, needs_reauth or no_data_yet. |
gsc.data.ourPosts |
The same numbers for your blog pages only, with the top five pages in top. null until Revnu has page-level data. |
scoreboard |
The last 14 days by content type, plus up to five pages with impressions and no clicks |
Search Console reports a day or two late, so gsc covers a window shifted back by two days. from and through give the exact dates. prevClicks is null, not 0, when the data doesn't reach back that far.
Outbound
Outbound is all-time, not windowed: one row per campaign in routes, sorted by sends. Each row has route, delivered, replied, bounced and pending (leads found but not yet sent), plus ready and drafted when Revnu could count them, and sequence with the campaign's approval state.
Why a section is unavailable
| Reason | Meaning |
|---|---|
not_connected |
The channel isn't connected |
needs_reauth |
It was connected, but the connection has expired; reconnect it in the dashboard |
tracking_off |
Open and click tracking isn't set up or is turned off |
no_blog |
Revnu hasn't written for your blog yet |
no_campaigns |
No ad campaigns exist |
not_tracked |
AI-answer visibility hasn't been measured yet |
measurement_stalled |
AI-answer measurements exist but none are recent enough to use |
no_data_yet |
Connected, but nothing has arrived for this window yet |
no_writer_yet |
Revnu doesn't measure this number yet |
read_failed |
This section couldn't be read this time; the others still rendered. Retry. |
What a read-only token can't tell you
Some questions have no field. These come only from asking Revnu in a message, which needs agent:message:
How a sending inbox's warm-up is going, and when it will start sending. No route returns warm-up progress.
Why a blog post failed.
postsFailedis a count. The cause stays with Revnu.The detail behind a LinkedIn pause beyond
pauseReason, and what Revnu will do about it.
A message is a request for work, so a token that can ask can also start work. Authentication has the safest way to set that up.
Responses
| Code | Meaning |
|---|---|
| 200 | { results } |
| 400 | since is not epoch milliseconds |
| 401 | Missing, revoked or unknown token |
| 402 | setup_pending: the account hasn't started its trial |
| 403 | The token lacks results:read |
| 429 | Over the read limit; wait Retry-After seconds |
Frequently Asked Questions
Which scope does this need?
results:read. A token without it gets 403 with requiredScope in the body. GET /me shows a token's scopes. results:read can't send, publish, run or spend.
How do I get reply rate?
Divide email.data.replies.data.replies by email.data.sent for the same window, after checking both are available. Pull Results Into Reporting has a weekly Slack post that does it.
Why is a channel unavailable instead of zero?
So a 0 always means a measured zero. Revnu marks a channel unavailable, with the reason in reason, when it has no measurement for it yet.
Why is LinkedIn paused, and until when?
Read linkedin.data.health.pausedUntil (epoch milliseconds, or null when it isn't paused) and pauseReason. Why Did LinkedIn Sending Stop? explains the pauses.
Does the API show sending inbox warm-up progress?
Ask Revnu with a message, which needs agent:message. Warm-up progress comes from the agent rather than a results field.
Can I read more than 31 days?
Each call covers up to 31 days. Pull daily and keep your own history for longer ranges.
Are responses cached?
No. Every response is Cache-Control: no-store, so what you read is current.