Payload Formats [HowTo]

I have seen some examples on payload functions.

Is there any guide on writing payload functions - what language are you using - what functions are available?

1 Like

It looks like javascript, but either it is not or some of the convenient libraries are missing. Would have loved to use ArrayBuffer to convert from bytes to float. See


It’s JavaScript (ECMAScript 5) indeed. For uplinks:

  • Decoder is a JavaScript function that accepts the payload as byte array and returns an object containing the decoded values. It gets passed:
    • First parameter, typically called bytes: the binary payload as an array of numbers. Each number is a byte, 0 to 255 in decimal notation, which is the same as 0x00 to 0xFF in hexadecimal notitation.
    • Second parameter, typically called port: the port number from 1 to 223.
  • Converter is a JavaScript function that accepts the object as returned by Decoder and returns an object containing the converted values.
  • Validator is a JavaScript function that validates the data as returned by Converter and returns a boolean value indicating the validity of the data.
  • :warning: Converter and Validator will be dropped in V3.

For downlinks:

  • Encoder is a JavaScript function that encodes the data queued for a Downlink messages and returns the converted values as an array of bytes.


Only the application payload and the port can be accessed, not any of the metadata such as the gateway(s) that received an uplink. See Access Metadata in decoder for alternatives.

To add the approximate time an uplink was received, one could use the server time:

var now = new Date().toISOString();


A good JavaScript resource is MDN Web Docs (formerly Mozilla Developer Network), and “mdn” is a great keyword for search engines: mdn array.

Also, you can use auto-completion in the developer tools of your browser. Just start by defining your payload with something like:

var bytes = [0xFF, 0x31, 0xF9, 0x12, 0x00, 0x31]

Or, to easily copy/paste a hexadecimal string such as 0xff31f9120031:

var bytes = 'ff31f9120031'.match(/(..)/g).map(b => parseInt(b, 16))

Next, typing bytes. will show you the supported functions and all:



Anything you send to console.log is shown in TTN Console during testing:


You should always test your format using the Payload input field in TTN Console, and the error events in +/devices/+/events/# in the MQTT API can also be used to track errors at runtime, like:

Unable to decode payload fields: Internal error: Decoder threw error: ReferenceError: ‘myVariable’ is not defined

Unable to decode payload fields: Internal error: Interrupted javascript execution for Decoder after 153.496916ms

Payload Function output cannot be marshaled to JSON: json: unsupported value: NaN

Given the “Error” filter in the application/device’s Data page in TTN Console one might expect such errors to be shown there too, but: no. When not seeing payload fields in TTN Console, then paste the application payload bytes into the Decoder’s test input, or use MQTT to see any errors.