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, permissions Send 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.io already caches with a 15-min TTL on latest calls and 1h TTL on full data calls
  • Citations. Every command can be extended with meta.sources[0].url to drop a footer link
  • Reliability. When ABS or RBA upstream goes 5xx, ausdata.io serves stale-cache-fallback, so the bot keeps working

What it doesn't do (yet)

  • Per-user rate-limiting (a noisy member could spam !dashboard, add commands.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.

All posts · Get a free key · Docs