Navigate to Applications > your application > Payload Formatters > Uplink in The Things Stack console.
Select 'Custom Javascript formatter' and implement a decodeUplink(input) function that reads input.bytes (a JavaScript byte array), input.fPort, and input.recvTime, and returns an object with a data field containing the decoded measurements.
Return a warnings array in the output object for non-fatal decode issues; return errors for fatal ones — messages with errors are still forwarded but flagged.
Test the formatter using the built-in 'Test' panel by supplying a sample hex payload and FPort before saving.
Keep the formatter script under the documented size limit (currently 40 KB for inline scripts; scripts loaded from the Device Repository can be larger).
For downlink commands, implement an encodeDownlink(input) function that converts input.data fields into a bytes array for the target FPort.
Known gotchas
The formatter runs in a sandboxed JavaScript environment without access to external libraries or network calls; all decoding logic must be self-contained.
Returning an invalid type from decodeUplink (e.g., a non-object or missing the data field) causes the formatter to silently fail and the raw bytes are forwarded instead.
Application-level formatters override device-level formatters set in the device repository; check which scope is active if decoded output is unexpected.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp