This is the most fun integration. The MathNet webhook can fire actual things in the physical world if you put a $5 ESP32 or a spare Raspberry Pi between it and your hardware.

A few example builds families have shared:

  • LED celebration strip above the desk that does a 3-second rainbow on every redeem
  • Servo-driven gumball machine that dispenses one gumball per credit
  • Thermal printer that prints a paper banknote-style “credit voucher” — this one is so much fun it gets its own page
  • Relay box that powers the TV on for a fixed duration

ESP32 (Arduino or ESPHome)

The easiest path is ESPHome — declarative YAML config, OTA updates, and a webhook trigger:

esphome:
  name: math-rewards

esp32:
  board: nodemcu-32s

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

web_server:
  port: 80

# Reward output — an LED strip on GPIO 2 for this example
light:
  - platform: fastled_clockless
    chipset: WS2811
    pin: GPIO2
    num_leds: 30
    rgb_order: GRB
    name: "Reward Strip"
    id: reward_strip

# HTTP endpoint MathNet will POST to
http_request:
  useragent: mathnet-esp32

api:
  services:
    - service: redeem
      then:
        - light.turn_on:
            id: reward_strip
            effect: rainbow
        - delay: 3s
        - light.turn_off:
            id: reward_strip

Then expose this via Home Assistant or a small bridge (the ESPHome api is internal; for an external webhook, use the Home Assistant approach with the ESP32 as the actuator).

If you don’t run Home Assistant, plain Arduino code on the ESP32 can listen on an HTTPS endpoint directly — but you’ll need to manage certificates yourself, which is fiddly. Going through Home Assistant or a small relay is much easier.

Raspberry Pi

A Pi with Python + Flask makes this almost trivial:

from flask import Flask, request
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)  # relay on GPIO 17

app = Flask(__name__)

@app.route('/mathnet', methods=['POST'])
def redeem():
    GPIO.output(17, GPIO.HIGH)   # close relay
    time.sleep(0.5)
    GPIO.output(17, GPIO.LOW)
    return '', 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Stick that behind nginx with TLS (or use Tailscale for transport security), and you’ve got a webhook → physical relay pipeline.

Security note

Anything running on your home network with an open webhook port deserves a thought:

  • Don’t expose the Pi/ESP directly to the internet. Use Tailscale, WireGuard, or a Cloudflare Tunnel.
  • If you must expose, use the MathNet Admin password header as a check on incoming requests.
  • A long, random URL path is your first line of defense.