Is Heroku Scheduler running your job? How to know
Heroku's own documentation describes Scheduler as a best-effort service: a job can occasionally be skipped or run more than once. That is fine for cache warming and not fine for invoices.
Add the ping to the job command
In the Scheduler dashboard, append the ping to the command so it only fires on success:
bin/rails billing:nightly && curl -fsS -m 10 https://cronpup.com/p/YOUR-UUID
Or report the exit code either way: bin/rails billing:nightly; curl -fsS -m 10 https://cronpup.com/p/YOUR-UUID/$?
Pick the schedule
Scheduler offers every 10 minutes, hourly or daily at a chosen time (UTC). Create a period monitor with the same interval and a grace period that covers the job's runtime plus dyno start-up, which can take a minute or two.
Running twice
A heartbeat monitor doesn't mind an extra ping, but your job might. Make important jobs idempotent, for example by recording the last processed date. Monitor your Scheduler jobs; 10 are free.