Device Ingest API#

Self Hosted Cloud Hosted

This page covers the public device-ingest endpoints only — the ones a device firmware author or integrator needs. The full internal API (batches, taps, vessels, devices, auth, admin, etc.) is not repeated here.

On the hosted service, devices post to ingest.brewgraph.com. Use the URL the app shows when you add a device (for example https://ingest.brewgraph.com/ingest/ispindel); the /api/ingest/... paths below work there too. HTTPS is the default; plain http:// is accepted for firmware that cannot do TLS.

Authentication#

Each device is issued its own token at registration time. The token is included in the request payload (field name varies slightly per endpoint — see below), not as a bearer header — this lets devices authenticate without implementing OAuth/JWT in constrained firmware.

Ingest endpoints#

Endpoint

Device

Notes

POST /api/ingest/ispindel

iSpindel, Tilt Hydrometer (via TiltBridge)

Native iSpindel JSON payload

POST /api/ingest/gravitymon

GravityMon

GravityMon-native payload format

POST /api/ingest/pressuremon

PressureMon

Pressure, temperature, battery, RSSI. Coming soon to Cloud Hosted; not available in the beta

POST /api/ingest/kegmon

KegMon

Pour detection pulses. Coming soon to Cloud Hosted; not available in the beta

POST /api/ingest/kegmon/beer

KegMon

Beer-assignment and pour-report payloads. Coming soon to Cloud Hosted; not available in the beta

POST /api/ingest/dispatch

Any supported ingest device

Detects the compatible payload shape and routes it to the appropriate handler

Request examples#

These are the three gravity device paths that work in the Cloud Hosted beta. Replace YOUR-DEVICE-TOKEN with the token shown when you registered the device, and use the exact URL the app shows for that device. On the hosted service the URL starts with https://ingest.brewgraph.com. Every request returns 200 with no body on success. An unknown token returns 401, a request sent too soon after the device’s plan interval returns 429, and a value that cannot be stored returns 422.

Measurements are stored as sent: numeric values are not range-checked or clamped, so negative pressure is accepted. A request returns 422 when its body cannot be parsed, a required value is missing, a number is not finite, or a unit is unsupported. Unit names are case-insensitive. An omitted optional field is shown as empty, not as zero. Negative volume is rejected with the field name in the ingestion log. On Self Hosted, a KegMon volume above vessel capacity is stored and raises the vessel capacity to match.

Battery voltage and percentage are stored independently and shown independently when present; neither is calculated from the other. Reading responses expose them as batteryVoltage and batteryPercent. On the hosted service, a native RAPT Pill reports gravity as specific gravity (SG) and battery as a percentage.

The token always goes in the JSON body as token. The examples use a placeholder, never a real token. The device ID is accepted but can never authenticate a request on the hosted service. Fields not listed as stored are ignored.

GravityMon#

curl -X POST https://ingest.brewgraph.com/ingest/gravitymon \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Gravitymon_01",
    "ID": "12345678",
    "token": "YOUR-DEVICE-TOKEN",
    "angle": 42.15,
    "temperature": 19.5,
    "temp_units": "C",
    "battery": 4.12,
    "gravity": 1.045,
    "corr-gravity": 1.044,
    "gravity-unit": "G",
    "velocity": -1.5,
    "interval": 900,
    "RSSI": -65,
    "run-time": 2.14
  }'
  • gravity-unit must be G (specific gravity). P (Plato) is rejected with 422.

  • temp_units must be C or F; any other value is rejected with 422. Fahrenheit is converted to Celsius. If you leave it out, Celsius is assumed.

  • corr-gravity is deliberately ignored: BrewGraph records the raw gravity value. name and interval are accepted but not stored.

iSpindel#

curl -X POST https://ingest.brewgraph.com/ingest/ispindel \
  -H "Content-Type: application/json" \
  -d '{
    "name": "[SG] iSpindel",
    "ID": 13065051,
    "token": "YOUR-DEVICE-TOKEN",
    "angle": 66.79,
    "temperature": 20.56,
    "temp_units": "C",
    "battery": 4.13,
    "gravity": 1.045,
    "interval": 900,
    "RSSI": -77
  }'
  • In the iSpindel firmware, set the device name to start with the exact prefix [SG]. The iSpindel’s calibration must output specific gravity. BrewGraph does not guess the scale from the number.

  • temp_units follows the same rule as for GravityMon.

  • name and interval are accepted but not stored.

Tilt Hydrometer (via TiltBridge)#

TiltBridge posts to the same route as the iSpindel, using the iSpindel HTTP format. TiltBridge can send a color field (for example "blue") in place of ID. Use the token for the Tilt device you added in BrewGraph.

curl -X POST https://ingest.brewgraph.com/ingest/ispindel \
  -H "Content-Type: application/json" \
  -d '{
    "name": "[SG] Tilt",
    "color": "blue",
    "token": "YOUR-DEVICE-TOKEN",
    "temperature": 20.5,
    "temp_units": "C",
    "gravity": 1.045
  }'

The [SG] name prefix and the temp_units rule above apply here as well.

See Devices for the full per-device setup guide (colour matching for Tilt, calibration for gravity sensors, etc.) — this page is just the wire protocol reference.