Twilio charges in USD. The billing platform converts USD costs to AUD using a live exchange rate with an optional markup percentage.
Live USD/AUD rate (from exchangerate-api.com, fetched hourly)
×
(1 + markup_percent / 100)
=
Effective rate (used for all CDR pricing)
Example:
| Setting Key | Description |
|---|---|
| USD_TO_AUD_RATE | Current live rate (updated hourly by Celery) |
| USD_TO_AUD_UPDATED_AT | Timestamp of last update |
| FX_MARKUP_PERCENT | Your markup percentage (0-50%) |
https://billing.yealin.com.au/settingsTOKEN=$(curl -s -X POST https://billing.yealin.com.au/api/auth/token/ \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"YOUR_PASS"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access'])")
# Get current FX info
curl -s https://billing.yealin.com.au/api/fx/ -H "Authorization: Bearer $TOKEN"
# Set markup to 3.5%
curl -s -X POST https://billing.yealin.com.au/api/fx/markup/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"markup_percent": 3.5}'
# Force immediate refresh
curl -s -X POST https://billing.yealin.com.au/api/fx/refresh/ \
-H "Authorization: Bearer $TOKEN"
The FX rate refreshes automatically every hour via Celery Beat. The task is registered as core.refresh_fx_rate in the django_celery_beat_periodictask table.
To verify it's scheduled:
python manage.py shell
from django_celery_beat.models import PeriodicTask
for t in PeriodicTask.objects.filter(enabled=True):
print(f'{t.name} — {t.interval}')
Source: https://api.exchangerate-api.com/v4/latest/USD
data['rates']['AUD']Changing the FX rate does NOT retroactively reprice existing CDRs. Only new CDRs imported after the change use the new rate. This is by design — it ensures invoices are stable and predictable.
To reprice existing CDRs, you would need to: