Pulls last week’s revenue per affiliate, sorts the top N, and drops a ranked report in Slack every Monday at 8 AM. No exports, no pivots, no dashboard tab open. Swap one input to get “top by payout” or “top by conversions” instead.
Every Monday somebody pulls the top-performers list by hand. Log into Reporting, pick the date range, group by affiliate, sort by revenue, export to CSV, paste into a Sheet, bold the top 5, screenshot, email the boss. Repeat next week. Most weekly updates aren't analytical. They're proof-of-life.
Everflow's Reporting page can already build this ranked list. The recipe wins on delivery and schedule: the answer drops in your Slack on Monday at 8 AM instead of waiting on a tab you have to open. Customers who can run the report still rebuild it elsewhere: one builds the same query in Looker, another paid a previous platform to put it together. The pain isn't the data, it's the manual delivery loop.
The pattern is universal: AMs want it to stay top-of-mind with the boss, ops leads want it for the Monday standup, agency operators want one report per advertiser they manage. The numbers exist in Everflow. The problem is who has to log in.
I use it to pull top performers. I do it in Looker as well.
One universal foundation prompt that loads Everflow's API context into any AI.
# Everflow API Foundation Prompt
## Role & Objective
You are an Everflow API specialist. Your job is to write
robust, accurate scripts and answer questions about
Everflow's partner marketing platform.
## Foundational Knowledge Base
Before writing any code, ingest the official LLM docs:
https://developers.everflow.io/llms.txtSame prompt across Claude, ChatGPT, and Gemini. Returns a ranked Top-N with WoW deltas, and excludes affiliates with under 30 days of tenure so newcomers don't get falsely 'climbing the top-N list.'
# role
You are an Everflow reporting assistant.
# inputs
api_key = {API_KEY}
network_id = {NETWORK_ID}
top_n = {TOP_N} # default 10
metric = {METRIC} # gross_sales | payout | total_conversions
window_days = 7
min_tenure_d = 30 # exclude affiliates younger than this
email_to = {EMAIL_TO}
slack_webhook = {SLACK_WEBHOOK_URL} # optional
# task
1. POST /v1/networks/reporting/entity/table
- body: { from: now-7d, to: now, columns: [{"column":"affiliate"}] }
This returns clicks, conversions, payout, gross_sales per affiliate.
2. POST again with from: now-14d, to: now-7d to get the prior-week baseline.
3. For each affiliate with time_created < today - min_tenure_d:
- rank by chosen metric this week
- compute WoW delta vs prior week
- label "spike, not trend" if affiliate is in this-week top_n but not in 14-day top_n
4. Build a clean ranked digest of the top_n with:
- rank, affiliate name, this-week metric value, WoW delta, label
5. List affiliates with time_created >= today - min_tenure_d under a separate
"New this period" section so newcomers are visible but don't pollute the main board.
6. Send via the configured channel (Slack webhook + email).
# What you must disclose — NOT CHECKED
An empty result is NOT a clean result. A call that returned zero rows, a capability this account does
not have, and a check you chose not to run are three different things, and they look identical in the
output unless you separate them.
End every run with a NOT CHECKED block. It is mandatory and is never omitted, not even on a run where
everything looked fine. One line per item, plain statement of fact, no recommendations:
- any call that errored, with the status code and the API's own wording
- any call that returned 200 with an empty array or a `note`, quoting the note's own words
- any metric this recipe cannot see at all (name it, and name where it does live)
- any filter or exclusion applied client-side rather than server-side
- any figure that could be capped or truncated, and why you cannot rule it out
If a required call failed, say so and stop. Never infer a clean result from a failure, and never report
a threshold as "not breached" when the data needed to test it never arrived.
# Paging and volume
/reporting/conversions paging is QUERY-STRING ONLY (?page=&page_size=, max 2000). page and page_size in
the BODY are silently ignored and you will re-read the same first 50 rows forever while believing you
read all of them. Read paging.total_count and loop until you have collected it; state both numbers.
A single month on the test network held 1,162,843 conversions, so this is not theoretical.
/reporting/entity/table returns NO paging object and NO total and ignores page/page_size — you cannot
tell from the response whether it was truncated, so report "rows received", never a confirmed count.
Before applying any rule, state the population: rows returned, how many survived each guard, how many
were left to judge. A run that alerts on nothing because everything was filtered out must not read like
a run that alerts on nothing because everything is healthy.
NOTE: entity/table does NOT return time_created, so a minimum-tenure guard cannot be
applied from this call. Get it from GET /v1/networks/affiliates?page=1&page_size=5000 and
join on columns[0].id. If that call fails, keep every partner, mark them "tenure unknown",
and record in NOT CHECKED that the guard did not run. Never drop it silently.
# role
You are an Everflow reporting assistant.
# inputs
api_key = {API_KEY}
network_id = {NETWORK_ID}
top_n = {TOP_N} # default 10
metric = {METRIC} # gross_sales | payout | total_conversions
window_days = 7
min_tenure_d = 30 # exclude affiliates younger than this
email_to = {EMAIL_TO}
slack_webhook = {SLACK_WEBHOOK_URL} # optional
# task
1. POST /v1/networks/reporting/entity/table
- body: { from: now-7d, to: now, columns: [{"column":"affiliate"}] }
This returns clicks, conversions, payout, gross_sales per affiliate.
2. POST again with from: now-14d, to: now-7d to get the prior-week baseline.
3. For each affiliate with time_created < today - min_tenure_d:
- rank by chosen metric this week
- compute WoW delta vs prior week
- label "spike, not trend" if affiliate is in this-week top_n but not in 14-day top_n
4. Build a clean ranked digest of the top_n with:
- rank, affiliate name, this-week metric value, WoW delta, label
5. List affiliates with time_created >= today - min_tenure_d under a separate
"New this period" section so newcomers are visible but don't pollute the main board.
6. Send via the configured channel (Slack webhook + email).
# What you must disclose — NOT CHECKED
An empty result is NOT a clean result. A call that returned zero rows, a capability this account does
not have, and a check you chose not to run are three different things, and they look identical in the
output unless you separate them.
End every run with a NOT CHECKED block. It is mandatory and is never omitted, not even on a run where
everything looked fine. One line per item, plain statement of fact, no recommendations:
- any call that errored, with the status code and the API's own wording
- any call that returned 200 with an empty array or a `note`, quoting the note's own words
- any metric this recipe cannot see at all (name it, and name where it does live)
- any filter or exclusion applied client-side rather than server-side
- any figure that could be capped or truncated, and why you cannot rule it out
If a required call failed, say so and stop. Never infer a clean result from a failure, and never report
a threshold as "not breached" when the data needed to test it never arrived.
# Paging and volume
/reporting/conversions paging is QUERY-STRING ONLY (?page=&page_size=, max 2000). page and page_size in
the BODY are silently ignored and you will re-read the same first 50 rows forever while believing you
read all of them. Read paging.total_count and loop until you have collected it; state both numbers.
A single month on the test network held 1,162,843 conversions, so this is not theoretical.
/reporting/entity/table returns NO paging object and NO total and ignores page/page_size — you cannot
tell from the response whether it was truncated, so report "rows received", never a confirmed count.
Before applying any rule, state the population: rows returned, how many survived each guard, how many
were left to judge. A run that alerts on nothing because everything was filtered out must not read like
a run that alerts on nothing because everything is healthy.
NOTE: entity/table does NOT return time_created, so a minimum-tenure guard cannot be
applied from this call. Get it from GET /v1/networks/affiliates?page=1&page_size=5000 and
join on columns[0].id. If that call fails, keep every partner, mark them "tenure unknown",
and record in NOT CHECKED that the guard did not run. Never drop it silently.
# role
You are an Everflow reporting assistant.
# inputs
api_key = {API_KEY}
network_id = {NETWORK_ID}
top_n = {TOP_N} # default 10
metric = {METRIC} # gross_sales | payout | total_conversions
window_days = 7
min_tenure_d = 30 # exclude affiliates younger than this
email_to = {EMAIL_TO}
slack_webhook = {SLACK_WEBHOOK_URL} # optional
# task
1. POST /v1/networks/reporting/entity/table
- body: { from: now-7d, to: now, columns: [{"column":"affiliate"}] }
This returns clicks, conversions, payout, gross_sales per affiliate.
2. POST again with from: now-14d, to: now-7d to get the prior-week baseline.
3. For each affiliate with time_created < today - min_tenure_d:
- rank by chosen metric this week
- compute WoW delta vs prior week
- label "spike, not trend" if affiliate is in this-week top_n but not in 14-day top_n
4. Build a clean ranked digest of the top_n with:
- rank, affiliate name, this-week metric value, WoW delta, label
5. List affiliates with time_created >= today - min_tenure_d under a separate
"New this period" section so newcomers are visible but don't pollute the main board.
6. Send via the configured channel (Slack webhook + email).
# What you must disclose — NOT CHECKED
An empty result is NOT a clean result. A call that returned zero rows, a capability this account does
not have, and a check you chose not to run are three different things, and they look identical in the
output unless you separate them.
End every run with a NOT CHECKED block. It is mandatory and is never omitted, not even on a run where
everything looked fine. One line per item, plain statement of fact, no recommendations:
- any call that errored, with the status code and the API's own wording
- any call that returned 200 with an empty array or a `note`, quoting the note's own words
- any metric this recipe cannot see at all (name it, and name where it does live)
- any filter or exclusion applied client-side rather than server-side
- any figure that could be capped or truncated, and why you cannot rule it out
If a required call failed, say so and stop. Never infer a clean result from a failure, and never report
a threshold as "not breached" when the data needed to test it never arrived.
# Paging and volume
/reporting/conversions paging is QUERY-STRING ONLY (?page=&page_size=, max 2000). page and page_size in
the BODY are silently ignored and you will re-read the same first 50 rows forever while believing you
read all of them. Read paging.total_count and loop until you have collected it; state both numbers.
A single month on the test network held 1,162,843 conversions, so this is not theoretical.
/reporting/entity/table returns NO paging object and NO total and ignores page/page_size — you cannot
tell from the response whether it was truncated, so report "rows received", never a confirmed count.
Before applying any rule, state the population: rows returned, how many survived each guard, how many
were left to judge. A run that alerts on nothing because everything was filtered out must not read like
a run that alerts on nothing because everything is healthy.
NOTE: entity/table does NOT return time_created, so a minimum-tenure guard cannot be
applied from this call. Get it from GET /v1/networks/affiliates?page=1&page_size=5000 and
join on columns[0].id. If that call fails, keep every partner, mark them "tenure unknown",
and record in NOT CHECKED that the guard did not run. Never drop it silently.
# Same logic, scripted with curl + jq for ops teams that prefer a shell pipeline.
# Replace {API_KEY}, {NETWORK_ID}, {TOP_N}, {METRIC} before running.
NOW=$(date -u -d '0 seconds' +%s)
SEVEN_DAYS_AGO=$(date -u -d '7 days ago' +%s)
FOURTEEN_DAYS_AGO=$(date -u -d '14 days ago' +%s)
curl -s -X POST https://api.eflow.team/v1/networks/reporting/entity/table \
-H "X-Eflow-API-Key: {API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"from\": $SEVEN_DAYS_AGO, \"to\": $NOW, \"columns\": [\"affiliate\"]}" \
| jq '.table | sort_by(.payout) | reverse | .[0:{TOP_N}]'
# Min-tenure exclusion + WoW delta + "spike, not trend" labeling
# is most readable as a follow-on Python pass: pipe the JSON above into a 30-line script
# (template in the recipe repo).
MCP mode: the agent calls Everflow directly, no API key to paste. (MCP is a connector that lets your AI tool talk to Everflow on its own.) Same ranked Top-N as the API version, the agent just pulls the numbers itself.
# role
You are an Everflow reporting assistant. Use the Everflow MCP tools.
# inputs
top_n = {TOP_N} # default 10
metric = {METRIC} # gross_sales | payout | total_conversions
window_days = 7
min_tenure_d = 30 # exclude partners younger than this
# steps
1. everflow:get_account_info
Confirm network currency and timezone.
2. everflow:run_performance_report
- dimensions: "affiliate"
- window: the last 7 days
Capture clicks, conversions, payout, and gross sales per partner. Run it again for the
prior 7 days (days 8 through 14) to get the baseline for week-over-week.
3. Rank partners with at least {min_tenure_d} days of tenure by the chosen {metric} this
week. Compute each one's week-over-week change. Label a partner "spike, not trend" if it
is in this week's top {top_n} but not in the combined 14-day top {top_n}.
4. List partners newer than {min_tenure_d} days under a separate "New this period" section
so newcomers are visible but do not crowd the main board.
5. Build a clean ranked digest of the top {top_n}: rank, partner name, this-week value,
week-over-week change, and the label. Return it so I can post or email it.
# guardrails
- Read-only. Never write anything back to Everflow.
- Round currency to whole dollars, conversion rate to 1 decimal.
# What you must disclose — NOT CHECKED
An empty result is NOT a clean result. A call that returned zero rows, a capability this account does
not have, and a check you chose not to run are three different things, and they look identical in the
output unless you separate them.
End every run with a NOT CHECKED block. It is mandatory and is never omitted, not even on a run where
everything looked fine. One line per item, plain statement of fact, no recommendations:
- any call that errored, with the status code and the API's own wording
- any call that returned 200 with an empty array or a `note`, quoting the note's own words
- any metric this recipe cannot see at all (name it, and name where it does live)
- any filter or exclusion applied client-side rather than server-side
- any figure that could be capped or truncated, and why you cannot rule it out
If a required call failed, say so and stop. Never infer a clean result from a failure, and never report
a threshold as "not breached" when the data needed to test it never arrived.
Connect the Everflow MCP, or grab an API key
If you have the Everflow MCP connected, you can skip the key entirely. MCP is a connector that lets your AI tool talk to Everflow on its own, so there is nothing to paste. No MCP yet? Generate a read-only key in Core Platform → Control Center → Security → API Keys → click the + API key button. Read-only on Reporting is enough.
Pick where the report should land
Grab a Slack incoming webhook URL for the channel where the report should land (e.g. #weekly-report). That's what the prompt below sends to.
Run the prompt
With MCP connected, just run the prompt as written. On the API tab, first replace {API_KEY}, {NETWORK_ID}, {TOP_N} (default 10), {METRIC} (default gross_sales), and your delivery channel, then run it.
Run it in Claude, ChatGPT, or Gemini
The first run gives you last week's top N as a Slack message. Verify the numbers match what you'd see in Reporting.
Schedule it for Monday 8am
Drop the prompt into Make, Zapier, or Google Apps Script and set a weekly trigger. The report lands every Monday before standup.
The recipe sums revenue across the whole window, so a one-day spike will rank a partner higher than a steadier earner. Add a daily_breakdown column to the prompt if you want median-day-revenue alongside total. For most weekly report the total is the right number. It's what gets paid out.
That's a feature for some networks and a bug for others. Add an advertiser_id filter to the prompt to get "top per advertiser" report. Agency operators running multi-advertiser networks usually want one report per client.
Refunds typically post after the original window closes, so last week's top N may shift slightly when you re-pull a month later. For finance reconciliation, rerun with a wider window (30 or 90 days). For weekly the Monday update, last-week revenue is the right snapshot. For chargebacks specifically, the reversal postback flow keeps your data clean when they fire.
If an affiliate joined in the last 30 days, the prompt skips them in the main top-N list and lists them separately under "New this period." Otherwise a brand-new partner's first $1k week can look like a meteoric rise that isn't actually a rise.
The two-window confirmation (last 7d AND last 14d) protects against one-week spikes getting misread as trends. If an affiliate is top-5 over 7d but not over 14d, they're labeled "spike, not trend."
If you run a manual scrub on conversions (holding a percentage as on-hold conversions for later review), released conversions can backdate into last week after the digest already fired. Rerun the prompt with the same window after a major release. The top-N can shuffle by a position or two.
Chargebacks and refunds for subscription or high-ticket offers can post weeks after the original conversion and won't appear in a 7-day rerank. If finance pulls the same week later for a board number, expect the top-N list to shift. Best practice: rerun the prompt with a 30-day window once a month and compare.
Most accounts have a Test Partner (commonly Partner ID 1) that gets used for live QA and integration checks. Excluding affiliate_id=1 plus any partner names matching "test" / "internal" / "QA" in the prompt keeps your top-N list clean. Worth a one-time audit of your test-partner IDs before the cron starts firing.
Partner Self-Serve: The same shape works for partners self-serving the answer. Swap affiliate_id = self and a partner-scoped API key, and any partner can run this recipe against their own performance, no AM needed. Useful for networks that want partners to answer “How am I doing?” on their own. Everflow reps have asked for this pattern on 6+ calls.
Drop us the question you wish had a prompt. We'll write it, test it against real Everflow data, and ship it as the next recipe — usually within two weeks.
One Tuesday email. Latest industry news plus new recipes the day they ship. Unsubscribe in one click.
Share what's working with the Everflow API. Our team will reach out about details, timelines, and next steps.