RoastLinkRoastLink Developer guideBack to portal

INVITE-ONLY BETA · VERSION 1

Connect your temperature logger.

RoastLink Cloud receives Celsius measurements from your ESP32, Raspberry Pi, Python application or logger. Your own application reads the physical sensors. No equipment controls, external recording uploads or third-party Live View are provided.

Your first device

  1. Open the portal address from your administrator.
  2. Sign in with your RoastLink account or create one and verify your email.
  3. Paste the separate one-time invitation code. It is tied to your invited email and expires after seven days.
  4. Select Add device, enter a name and choose 1–4 actual physical channels.
  5. Copy or export the one-time device credential. You cannot retrieve it later. Keep it private.
  6. Run the example below, then Refresh readings to see your device online.

Two active external devices are permitted. At most five registrations per account per rolling day. Revoking a credential keeps history; rotating immediately invalidates the old key. Administrator suspension stops protected access and ingestion.

API reference

Base URL:

https://zsugchuvhqzkfyiagclm.supabase.co/functions/v1/developer-api

Owner endpoints use Authorization: Bearer <RoastLink access token>. Obtain the session through normal RoastLink/Supabase Auth; never use a device key for account endpoints. Device telemetry uses Authorization: Bearer <device credential>. Send Content-Type: application/json. The portal handles account authentication for you.

MethodPathPurpose
POST/v1/external-devicesRegister: name, channel_count; optional channel_labels object
GET/v1/devicesYour external devices
GET/v1/devices/{id}Latest reading and bounded history
POST/v1/devices/{id}/credentials/rotateOne-time new credential
DELETE/v1/devices/{id}/credentials/currentImmediate revocation
POST/v1/device/telemetrySend measurements using device key
GET/v1/beta/statusYour beta access
POST/v1/beta/redeemAccept code with verified invited account

Registration

{"name":"Four-channel logger","channel_count":4,"channel_labels":{"1":"Probe A","2":"Probe B","3":"Probe C","4":"Probe D"}}

Response: {"status":"ok","device_id":"UUID","generation":1,"credential":"ONE_TIME_SECRET"}. Do not submit an owner ID, model or device class. The server assigns an external identity.

Telemetry schema

{
  "version": 2,
  "device_id": "YOUR_DEVICE_UUID",
  "message_id": "NEW_UUID_FOR_THIS_SAMPLE",
  "boot_id": "UUID_CREATED_ONCE_PER_PROCESS_BOOT",
  "sequence": 0,
  "sampled_at": "2026-10-14T04:00:00Z",
  "sample_age_ms": 0,
  "channels": [
    {"id": 1, "temperature_c": 22.5, "valid": true, "fault": null},
    {"id": 2, "temperature_c": null, "valid": false, "fault": "sensor_disconnected"}
  ]
}

Channel identifiers are integers 1–4 within the registered channel count. No mirrored virtual channels. Canonical temperatures are Celsius, −100 to 600 °C. Valid samples require a finite temperature and no fault; invalid samples require null temperature. Fault strings are optional, maximum 64 characters. Timestamps must be UTC/offset ISO8601, at most ten minutes old or two minutes ahead. Sample age is 0–600000 ms. Sequence increases within each boot; a boot identifier is 16–64 alphanumeric/hyphen characters. Payload limit: 2048 bytes. Message UUIDs identify samples. Retry the identical body and message ID; a duplicate returns status duplicate and adds no second history row. Reusing an ID with different bytes conflicts. Older sequence within a boot is rejected.

Successful new reading: HTTP201 {"status":"accepted"}. Identical duplicate: HTTP200 {"status":"duplicate"}. Report every 30 seconds by default, never faster than once per five seconds. Account ingestion and owner operations each allow 30 requests per fixed 60-second bucket; invitation/access actions use a separate 30-request bucket. Invitation creation is limited to 50 per administrator per rolling day. Account request limits also apply. Responses contain a server_time_ms diagnostic clock.

Current deployed history is 48 hours, with up to 600 recent samples returned by the developer API. The intended 24-hour reduction has not been deployed. Standard Cloud recording quota remains 10000000 bytes; external devices cannot upload recordings. Offline status means no recent reading; it does not erase history.

Python and Raspberry Pi quick start

Download temperature_client.py. Python 3 uses verified system HTTPS certificates; no third-party packages are required. Set these environment variables privately; do not paste keys into shared terminals, notebooks or logs.

export ROASTLINK_API_URL=https://zsugchuvhqzkfyiagclm.supabase.co/functions/v1/developer-api
export ROASTLINK_DEVICE_ID=YOUR_DEVICE_UUID
# Load ROASTLINK_DEVICE_KEY securely from your secret manager.
python3 temperature_client.py --synthetic --channels 4 --samples 3

This sends three explicitly synthetic four-channel readings, useful for a first integration check. They are not physical sensor measurements. For real sensors, replace read_channels() in the example with your sensor acquisition and remove --synthetic. Unconfigured or disconnected sensors send null/fault values. Raspberry Pi uses the same client: keep acquisition independent of transport, maintain a bounded latest sample, and protect the key with restrictive OS permissions or a secret manager.

ESP32 / Arduino quick start

Download temperature_client.ino and secrets.example.h. Copy the example header to a private secrets.h. Install ESP32 Arduino core and ArduinoJson 6, set Wi-Fi, device ID/key and use the included verified GTS Root R4 certificate. The API currently uses Google Trust Services WE1 → GTS Root R4; the trusted root must be updated if that chain changes. Its official source is Google Trust Services. Never call setInsecure. Keep secrets.h out of version control. Choose CHANNEL_COUNT 1–4 and implement readChannel() for your physical sensors.

The example waits for Wi-Fi and NTP, generates a boot UUID, uses canonical Celsius, rejects redirects and retries an identical serialized packet up to three times with bounded exponential backoff. It reports unconfigured sensors as null. Sensor timing in production should run independently of blocking network work; the example is a starting point, not RoastLink firmware.

Beta administration API

Administrator role is assigned server-side. Ordinary and invited developer accounts cannot call these management actions.

Invite redemption uses POST /v1/beta/redeem with {"code":"PRIVATE_ONE_TIME_CODE"}. Never put the code in a URL.

Troubleshooting

400 invalidCheck IDs, channel count, timestamp, sample range and null/valid/fault consistency.
401 unauthorizedIncorrect, rotated or revoked credential, or suspended account. Stop sending; fix access first.
403 forbiddenAccount is uninvited, suspended, unverified, wrong email or origin. No self-enrollment.
404 not_foundNo owned device or supported endpoint at that address.
409 conflict / replay / usedConflicting message or older sequence; stop retrying that packet. Invitation already accepted: sign in normally.
410 expired / revokedAsk the administrator for a valid invitation.
413 invalidJSON payload exceeds 2048 bytes.
429 rate_limited / quotaBack off exponentially. Device cadence is at least five seconds; account quotas also apply.
503 unavailableRetry the same packet with bounded backoff. Do not create an unlimited queue.

Sensor disconnected: send null, valid:false and a descriptive fault. Network interruption: keep at most one pending packet, retry identically, and discard it when its timestamp exceeds the ten-minute window. Offline device: verify power, Wi-Fi, clock and credential; normal readings resume on valid upload. Never use public Storage URLs or account passwords inside a sensor client.

Privacy and access

Credentials are shown once and only hash verifiers are stored server-side. The portal keeps account sessions in memory and clears them on logout or page close. No account/device tokens are placed in URLs, analytics or localStorage. Your clipboard or downloaded credential file remains your responsibility. Only your account can read its device history. Beta access can be suspended by the administrator; historical measurements are preserved.