Home / Blog / Build a Discord bot that knows the AU economy in 15 minutes
2026-05-23 · Harry Vass
Build a Discord bot that knows the AU economy in 15 minutes
A working Discord bot with !cpi, !cashrate, !unemployment, !dashboard commands, full source, deploy instructions, free hosting on Fly.io.
A few hundred AU finance discord servers exist (r/AusFinance adjacent, FIRE communities, investing book clubs). Most of them have an #economy channel where someone occasionally pastes an ABS link.
Better: a bot that posts the live CPI, cash rate, unemployment, and real-wages numbers on command.
This post walks through building exactly that in Python with discord.py. The bot:
- Responds to
!cpi,!cashrate,!unemployment,!real-wages,!dashboard - Pulls live numbers from
ausdata.io(free tier, 500 calls/month) - Cites the source URL in every response
- Deploys to Fly.io free tier ($0/month)
The code (full source)
import os
import discord
import requests
from discord.ext import commands
API_KEY = os.environ["AUSDATA_API_KEY"]
DISCORD_TOKEN = os.environ["DISCORD_TOKEN"]
BASE = "https://api.ausdata.io"
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)
def _get(path, **params):
r = requests.get(
f"{BASE}{path}",
headers={"Authorization": f"Bearer {API_KEY}"},
params=params, timeout=30,
)
r.raise_for_status()
return r.json()
@bot.command()
async def cpi(ctx):
d = _get("/v1/data/abs/CPI", limit=1)["data"][0]
await ctx.send(f"📊 AU CPI ({d['period']}): **{d['value']}%**")
@bot.command()
async def cashrate(ctx):
d = _get("/v1/economic-dashboard")["data"]
await ctx.send(
f"🏦 RBA cash rate: **{d['cash_rate_pct']}%** "
f"(as of {d['cash_rate_period']})"
)
@bot.command()
async def dashboard(ctx):
d = _get("/v1/economic-dashboard")["data"]
msg = (
f"**🇦🇺 AU Economy Dashboard**\n"
f"• Cash rate: {d['cash_rate_pct']}%\n"
f"• CPI annual: {d['cpi_annual_pct']}%\n"
f"• Unemployment: {d['unemployment_rate_pct']}%\n"
f"• Real wages YoY: {d['real_wages_yoy_pct']:+.1f}%\n"
f"_Source: ausdata.io_"
)
await ctx.send(msg)
if __name__ == "__main__":
bot.run(DISCORD_TOKEN)
That's it. 30 lines including imports.
Setup steps (15 min)
1. Free ausdata.io key (60s)
- Go to ausdata.io, enter email, get key (
ak_...) - Free tier is 500 calls/month, plenty for a 50-person discord server
2. Discord bot (5 min)
- Open https://discord.com/developers/applications → New Application → Bot
- Copy the Bot Token
- Enable Message Content Intent under Privileged Gateway Intents
- OAuth2 → URL Generator → scopes
bot, permissionsSend Messages+Read Message History - Open the generated URL, add the bot to your server
3. Local run (2 min)
git clone https://github.com/Bigred97/ausdata-recipes
cd ausdata-recipes/07-discord-bot
pip install -r requirements.txt
export AUSDATA_API_KEY=ak_...
export DISCORD_TOKEN=MTIz...
python main.py
Type !cpi in your discord server. Should respond instantly.
4. Deploy to Fly.io free tier (5 min)
brew install flyctl
fly auth signup
fly launch --no-deploy --name ausdata-discord-bot
fly secrets set AUSDATA_API_KEY=ak_... DISCORD_TOKEN=MTIz...
fly deploy
Fly.io has a generous free tier, the bot runs on a 256MB shared-CPU Machine for $0/month. Logs via fly logs.
What the bot does well
- Live numbers. No caching at the bot level,
ausdata.ioalready caches with a 15-min TTL onlatestcalls and 1h TTL on full data calls - Citations. Every command can be extended with
meta.sources[0].urlto drop a footer link - Reliability. When ABS or RBA upstream goes 5xx,
ausdata.ioserves stale-cache-fallback, so the bot keeps working
What it doesn't do (yet)
- Per-user rate-limiting (a noisy member could spam
!dashboard, addcommands.cooldown) - Multilingual responses (English only)
- Charts (you could attach a matplotlib PNG to the message)
- Personal portfolio context (not the bot's role; this is public data only)
Extending it
Each new command is 4 lines. Examples:
@bot.command()
async def trade(ctx):
d = _get("/v1/trade-balance")["data"]
await ctx.send(f"Trade balance: ${d['trade_balance_aud_m']/1000:.1f}B")
@bot.command()
async def gender_pay(ctx):
d = _get("/v1/gender-pay-context")["data"]
await ctx.send(f"AU gender pay gap: {d['gender_pay_gap_pct']:.1f}%")
@bot.command()
async def energy(ctx):
d = _get("/v1/data/aemo/trading_price")["data"]
await ctx.send(f"NSW1 24h avg: ${d['nsw1_24h_avg_aud_mwh']}/MWh")
19 endpoints; pick the ones your server cares about.
Pricing, when do you upgrade?
The free tier is 500 calls/month. If your server runs !cpi 20 times/day = 600/month, you'll hit the cap. Upgrade to Analyst $29/mo for 10k calls. Embed $99/mo if you want webhooks (bot auto-posts when ABS releases new CPI without anyone asking).
Source: github.com/Bigred97/ausdata-recipes/07-discord-bot
Get a free ausdata.io key: ausdata.io.