Skip to Content
Browse the Docs▾

Get results

GET/api/v1/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.

Email

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.

LinkedIn

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. postsFailed is 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.