MathNet’s reward system is opt-in and parent-configured. It’s off by default. When you turn it on, MathNet doesn’t decide what a reward is — it just fires an HTTP request to a URL you control. You decide what that URL does.
This is what makes it useful: instead of a sticker chart or a hardcoded “buy this gem with your gold,” every family wires it into whatever they already use. Some use Home Assistant to flash lights. Some use Pushover to ping a parent’s phone. Some use a Raspberry Pi to dispense a piece of candy. It’s a generic mechanism.
The flow
- Answer problems. Every correct answer earns points = base points × speed multiplier.
- Bank points. Points accumulate in the Bank view as the student practices.
- Exchange for credits. Tap the Exchange button to convert points to credits at the configured rate (default 50 points = 1 credit). This is a deliberate step, so a student can’t accidentally burn a session’s worth of work in one tap.
- Redeem credits. Tap Redeem in the Bank view. MathNet sends a single HTTP POST to the configured webhook URL with a small JSON payload, then increments the redemption count.
That’s it. Once the webhook fires, MathNet’s job is done. Whatever happens next is whatever you’ve wired the webhook URL to do.
The webhook payload
When a credit is redeemed, MathNet sends a POST request like this:
POST /your-webhook-endpoint HTTP/1.1
Content-Type: application/json
Authorization: Bearer <admin password, if configured>
{
"event": "redeem",
"credits": 1,
"balance_after": 4,
"timestamp": "2026-05-11T18:42:00Z",
"device_name": "Alex's iPad"
}
The Authorization header is included only if the user has set an admin password in Settings. This lets your receiving endpoint verify the request came from a configured MathNet install rather than someone who guessed the URL.
Tip: pick a webhook URL with a long, unguessable path (e.g.
https://your-host/mathnet-webhook-9f2a1b/). Treat it like a secret. The admin password header is a second factor; a private URL is the first.
Setting it up
- Open MathNet → Settings (admin password required).
- Toggle Enable reward system on.
- Paste your webhook URL into the Webhook URL field.
- Set Points per credit (default 50) — the number of points needed to mint one credit.
- Optionally set an Admin password; if set, it’s sent as the
Authorization: Bearer …header on every redeem. - Tap Save Settings, then Test webhook to confirm reachability.
The Bank view shows a live status indicator for the webhook. If MathNet can’t reach the URL (DNS failure, 500 response, etc.), the Redeem button is disabled and the status line explains why. MathNet re-probes the URL every 30 seconds while the Bank view is open.
Choosing a good points-per-credit rate
The default of 50 means a student needs roughly 5–10 minutes of focused practice to earn one credit, depending on what category they’re working on. Tune it to match how scarce or abundant you want credits to feel:
- Cheap credits (10–20 points/credit) — for younger students, where each credit triggers something small (a sticker, a song, a quick light show)
- Default (50 points/credit) — for one-redemption-per-session-feels-right balance
- Expensive credits (200+ points/credit) — for credits that trigger something bigger (TV time, dessert, allowance, etc.)
You can change this at any time. Old credits remain at their original value — the rate only affects new exchanges.
Failure handling
Sometimes the webhook will fail — your home server is rebooting, your internet is down, the cloud provider is having a moment. MathNet handles this gracefully:
- If the webhook is unreachable when the user opens the Bank view, Redeem is disabled and the status line shows why. There’s no half-redemption state.
- If the webhook returns a non-2xx response during a redeem attempt, the credit is returned to the balance and the failure is logged in the transaction history with the error response.
- The user can always retry once the issue is resolved.
A note on the reachability probe
While the Bank view is open, MathNet sends a HEAD request to your webhook URL every 30 seconds to keep the reachability indicator current. It treats:
- 2xx — server up and willing to handle the method → reachable
- 4xx (including 405 Method Not Allowed) — server up but doesn’t accept HEAD → still reachable
- 5xx — server problem → unreachable, Redeem disabled
Almost every realistic webhook receiver does the right thing here — Home Assistant, Cloudflare Workers, AWS Lambda function URLs, nginx with a 405 fallback, Express, Flask, etc. The one case to know about: Python’s stdlib http.server returns 501 (Not Implemented) for any unhandled method. If you’re hacking together a quick endpoint with it, make sure it responds to HEAD with something < 500, or the Bank’s status indicator will look broken even though POST works fine. The dev-tool at tools/webhook-echo.py in the MathNet repo already handles this correctly.
HTTPS and App Transport Security (ATS)
MathNet uses the iOS networking stack with its default settings. That means TLS is validated against iOS’s built-in trusted root certificate store — anything with a valid public cert (Let’s Encrypt, ZeroSSL, GoDaddy, Cloudflare, etc.) just works. We don’t pin certificates and we don’t override the trust store, so user-installed or MDM-deployed root CAs also work.
App Transport Security is iOS’s policy, not MathNet’s. ATS is the default network security policy Apple enforces on every iOS app since iOS 9 — it requires TLS 1.2+ with a trusted certificate chain for outbound HTTPS, and blocks plain HTTP to non-local hosts entirely. We haven’t set any ATS exception, so the system defaults apply.
What this means for your webhook URL:
https://anything-with-a-valid-cert.com/— workshttp://127.0.0.1:…/(testing from the iOS Simulator only) — works, ATS exempts localhosthttp://my-pi.lan:8080/(plain HTTP to a LAN box from a real device) — blocked by ATShttps://my-self-signed-host/(self-signed cert) — blocked by ATS
If you need to expose a LAN service to your real device, put it behind something with a real cert: Caddy + Let’s Encrypt, Cloudflare Tunnel, Tailscale + HTTPS, or a tiny VPS reverse-proxy. Apps Apple ships in the App Store can’t loosen these rules without justifying ATS exceptions in their Info.plist, and we don’t ship any.
Privacy
The webhook URL is set by the user and the request goes directly from the user’s device to that URL. MathNet doesn’t proxy it, log it on any MathNet server (there are no MathNet servers), or share it with anyone. The payload contains no personally identifiable information — just enough context for your endpoint to know which redemption just happened.
Now go wire something up
The full list of integration recipes is on the integrations page. The most popular one — and the one I’d recommend if you don’t already have a preference — is Home Assistant.