Guides

Choose what the sink receives

Five output shapes, what each costs you, and how to compose your own.

The output structure decides the shape of the JSON posted to a sink. It is set per source → sink pair, in Flow → Routing, so each destination can get exactly what it wants.

The examples below are the same Sigfox message delivered five ways, so you can compare them directly.

Full message

Everything the Center knows, wrapped around the payload. The default, and the right answer unless you have a reason to pick another.

{
  "provider": "SIGFOX",
  "deviceIdentifier": "1A2B3C",
  "messageType": "DATA_BIDIR",
  "receivedAt": "2026-08-15T13:47:45.000Z",
  "idempotencyKey": "SIGFOX:1A2B3C:DATA_BIDIR:18",
  "payload": {
    "device": "1A2B3C",
    "data": "00018d460000300040e12402",
    "seqNumber": 18,
    "decoded": { "index": 18.061, "unit": "m3", "battery": 100 }
  },
  "raw": { "device": "1A2B3C", "data": "00018d46…", "seqNumber": 18 }
}

Note idempotencyKey — the Center delivers at least once, and that is how your side recognises a repeat.

Raw provider frame

Exactly what the provider POSTed, untouched:

{
  "device": "1A2B3C",
  "data": "00018d460000300040e12402",
  "seqNumber": 18,
  "time": 1755265665
}

Right when the receiving system already speaks the provider's format — you are using the Center for routing and retries, not translation.

No idempotency key, no resolved device
This shape carries only the provider's own fields. A sink on it must de-duplicate using those — for Sigfox, device plus sequence number. Choose it deliberately.

Decoded telemetry only

The envelope, with payload replaced by what your decoder returned:

{
  "provider": "SIGFOX",
  "deviceIdentifier": "1A2B3C",
  "idempotencyKey": "SIGFOX:1A2B3C:DATA_BIDIR:18",
  "payload": { "index": 18.061, "unit": "m3", "battery": 100 },
  "raw": { }
}

Two things surprise people:

  • It falls back. No decoder, a decoder that threw, or a callback with no payload — and payload stays the full message payload instead. The same sink can see two different shapes. Check payload.decodeError.
  • Only three Sigfox callbacks are decoded. DATA_UPLINK, DATA_BIDIR and SERVICE_DATA_ADVANCED carry a payload frame; the other four have nothing to decode.

Everything decoded

Everything the decoder returned, with its two groups kept apart:

{
  "provider": "SIGFOX",
  "payload": {
    "telemetry": { "index": 18.061, "unit": "m3", "battery": 100 },
    "meta": { "seqNumber": 18, "rssi": -103.41 }
  }
}

They stay separate on purpose: merged, a key your decoder puts in both would silently lose one, and nothing downstream could tell a reading from a piece of radio metadata. If your decoder returns only telemetry, only telemetry appears.

Custom

You compose the entire body. Nothing is wrapped around your fields — no envelope, no payload:

{
  "device": "1A2B3C",
  "idempotencyKey": "SIGFOX:1A2B3C:DATA_BIDIR:988",
  "reading": 18.061,
  "tag": "maski"
}

It starts you with four fields — device, event type, timestamp and the de-duplication key — because an empty document looks broken and those are what a sink usually needs. Every one is removable.

You pick fields, you do not type paths

The Center remembers what your decoder returns — every field, including nested ones, with its type and last value — and lists them as buttons grouped From the message, telemetry and meta. Click to include; rename if you want a different key.

Until a source's decoder has run once there is nothing to list, and the editor says so. Send one message and the fields appear.

Four kinds of row

RowWhat it does
a picked fieldcopies it, under whatever name you type
a fixed valuethe same constant on every message
text from fields{device}-{seqNumber}"1A2B3C-988"
a computed valuearithmetic or a condition

Text rows need no quotes and no operators — write the field names in braces and everything else literally. A missing field renders as nothing, and the row still arrives.

Nested objects

Add a nested object creates a container you can put fields inside, to any depth:

device            = deviceIdentifier
meter             { }
  battery         = decoded.battery
  reading         { }
    value         = decoded.index
    unit          = "m3"

which delivers:

{
  "device": "1A2B3C",
  "meter": { "reading": { "value": 18.061, "unit": "m3" }, "battery": 100 }
}

Drag the handle beside a field to move it — onto an object to put it inside, onto another field to reorder. A name containing a dot nests too: meter.reading is the same as putting reading inside meter.

An object with nothing in it is not sent; there is no reason to deliver {}.

Missing fields are omitted, not nulled
A field absent from a given message is left out rather than sent as null. That is not an error — and the editor tells you it happened, and why, so a field never just disappears on you.

Choosing

WantPick
Everything, safest defaultFull message
The receiver already parses the provider's formatRaw provider frame
Just the readings, with an envelopeDecoded telemetry only
Readings and radio metadata, kept apartEverything decoded
An exact contract the receiver already definesCustom

When unsure, start with Full message. It is the only one that never loses information, and narrowing later is easy.

Where the default comes from

A sink can carry its own default output structure, used by any pair that has not set one. A pair's own setting always wins; clearing it falls back to the sink's default.

Next

Filter with rules
Decide which messages reach the sink at all.
When delivery fails
What to do when the shape is right but nothing lands.
Copyright © 2026