PoleFX Docs

Control API and Protocol

This page is for integrators who want to control PoleFX poles from their own software. It describes pole firmware release 2026.07, which has two network interfaces you can build on:

  • Pixel streaming (DDP, sACN or Art-Net over UDP) to send every pixel yourself. The Pixel Streaming page is the setup guide; this page adds the packet-level details.
  • The configuration API, plain HTTP and JSON at http://<pole>/json/cfg, to read a pole's identity, size and diagnostics and to change its settings.

Both talk to one pole directly. The web app, front panel and DMX control the Player instead, and the Player has no published API of its own.

Before you start

  • Firmware 2026.07 or newer, as the Pixel Streaming guide requires. Check it in the Player under Settings > Devices, or read info.fw from the pole (for example lg1-2026.07).
  • Wired Ethernet on a closed LED network. Poles use static addresses, usually 192.168.5.x with mask 255.255.255.0, and do not use DHCP.
  • Turn the Player's output off under Settings > Outputs before streaming, or the Player and your software will compete for the pole.
  • There is no login. The configuration API has no password or other authentication, and it uses plain HTTP on port 80. Anyone who can reach the pole on the network can change its settings, so keep poles on a network you control and do not route them to the internet.

Finding a pole

  • Player device list. Settings > Devices in the Player shows each pole's name, IP address and firmware.
  • By name. A pole answers to polefx-<name>.local, where <name> is its name in lowercase, with each run of spaces or punctuation between words turned into one hyphen and any at the start or end dropped. Give every pole a name that contains letters or digits. The hostname is set when the pole starts, so a renamed pole keeps its old .local name until it restarts. info.mdns_host reports the hostname (without .local). It is empty if name lookup is turned off or could not start; a hostname here does not by itself prove the pole is being advertised.
  • By service browsing. Poles advertise an _http._tcp service on port 80 with TXT entries product=polefx-pole, path=/json/cfg, strips=<n> and pixels=<n>. On a Mac, for example, dns-sd -B _http._tcp local lists them. Name lookup and browsing work only on the same network segment.
  • Confirm by opening http://<address>/json/cfg. A pole returns a JSON document that starts with its name and profile.

Poles do not answer Art-Net ArtPoll or sACN universe discovery, so a lighting console will not find them automatically. Enter each pole's IP address in your software.

Pixel streaming

Frame size and pixel order

Read led.strips and led.pixels from /json/cfg before sizing your output; do not rely on a table. On a current pole with the normal mapping (led.map_mode 1), the frame is:

  • width = led.pixels / 2 pixels along the pole (240 on a standard Gen 3 pole),
  • height = led.strips * 2 rows around the pole (12),
  • bytes = led.strips * led.pixels * 3 (8,640).

Send RGB, three bytes per pixel, in plain reading order: all of row 1 from the top of the pole down, then row 2, and so on. Pixel 0 is at the top of the pole. Do not use serpentine or zigzag order; the pole handles its own wiring. Send RGB even though the LEDs are GRB; the pole reorders colors itself.

Gen 1 and Gen 2 poles and shorter poles use different sizes. Always use the size the pole reports; a frame of the wrong size may be rejected.

UDP port 4048 by default (ports.ddp), on by default (ddp.enable). Send to the pole's own address, or to its multicast group (net.mcast).

Each packet has a 10-byte header followed by pixel data:

Byte Field Value to send
0 Flags 0x40 (version 1); add 0x01 (Push) on the last packet of a frame
1 Sequence Low four bits, 1 to 15, or 0 if unused
2 Data type 0x0B (RGB, 8 bits per color)
3 Destination 1 (display)
4–7 Byte offset of this packet's data in the frame Big-endian 32-bit
8–9 Number of data bytes in this packet Big-endian 16-bit
  • Split the frame into 1,440-byte packets at offsets 0, 1440, 2880 and so on, with a shorter last packet if needed. With the pole's normal pixel mapping, packets that do not start on a 1,440-byte boundary, or carry more than 1,440 bytes, are dropped. A standard 8,640-byte frame is six packets. WLED, xLights and LedFx already send this way.
  • Mark the end of the frame with Push on the last packet, or send a separate Push packet with no data.
  • The pole shows only complete frames. If any part of the frame is missing at Push, the pole keeps showing the previous frame. Setting ddp.atomic to 0 shows whatever has arrived instead.
  • A timecode header is accepted, but the time is ignored. DDP query, reply, storage and JSON control packets are not supported and are dropped.

sACN (E1.31) and Art-Net

sACN uses UDP port 5568 and must be sent unicast to the pole. Art-Net uses UDP port 6454, unicast or broadcast. Both are on by default (dmx.sacn_enable, dmx.artnet_enable). Only Art-Net ArtDmx and sACN data packets are used.

  • Each universe carries 170 pixels (510 channels), starting at channel 1. The last universe carries what is left: 480 channels on a standard pole, which needs 17 universes.
  • Universes must be consecutive, starting at dmx.start_uni (default 1). Art-Net software often counts from 0; set the pole or the software so they match. sACN cannot use universe 0, so a pole set to 0 accepts Art-Net only.
  • A frame is shown only when every universe has arrived. A partial frame older than 250 ms is discarded.
  • sACN priority and synchronization packets are not acted on, and sACN preview data is ignored.

One sender at a time

Use one sender and one protocol per pole. A different protocol can take over after the current one has been silent for 0.5 seconds. A second sender on the same protocol is ignored until the first stops. When streaming stops, the pole returns to its built-in patterns after a few seconds, if they are turned on (led.shimmer is true, the default). The Pixel Streaming guide recommends at most 60 frames per second.

The info.ddp, info.sacn and info.artnet counters in /json/cfg show what the pole is receiving; see Pixel Streaming for troubleshooting by counter.

Configuration API

Request What it does
GET /json/cfg Returns every setting plus a read-only info block
POST /json/cfg Changes the settings you include
GET /json/info Currently returns the same document as GET /json/cfg

Backup and restore (provisional). This is how the firmware is written to behave, but it has not yet been verified on a real pole, so treat it as provisional and keep your own record of important settings. Save the GET document as a backup. To restore it, POST it back with "save": true added at the top level. The info block is ignored. If the reply says "restart_required": true, restart the pole before checking the result.

Changing settings

POST a JSON object containing only the settings you want to change, under the same names that GET returns. Add "save": true to keep the change after a power cycle. The body must be 8,192 bytes or less.

curl -X POST http://192.168.5.12/json/cfg \
  -H 'Content-Type: application/json' \
  -d '{"dmx":{"start_uni":0},"save":true}'

A successful reply looks like this:

{"ok":true,"applied":1,"saved":true,"save_error":0,"restart_required":false}

applied counts the settings the pole accepted. Check that it matches what you sent, then GET the document again to confirm live changes.

Live settings and restart settings. Most settings take effect immediately. Some only take effect after the pole restarts; they are marked Restart in the tables below. For those:

  • you must include "save": true, or the request is rejected with HTTP 400;
  • if a request changes any restart setting, nothing in that request takes effect until the pole restarts, including live settings sent with it, and the reply says "restart_required": true;
  • until the pole restarts, GET still shows the old values, so it cannot confirm the change, and further POSTs return HTTP 503;
  • the pole does not restart itself. Restart it (for example by cycling its power), then GET to confirm.

Send restart settings in their own request. A restart setting sent with its current value does not count as a change.

What gets checked. A value out of range for a known setting rejects the whole request with HTTP 400 naming the first bad field, and nothing changes; values are not clamped. Setting names are case-sensitive. Unknown names, read-only fields and values of the wrong JSON type (for example true where a number is expected) are ignored without an error, which is why applied is worth checking.

Errors.

Status Meaning
400 Not valid JSON, body missing or over 8,192 bytes, a value out of range, or a restart setting without "save": true
408 The request body did not arrive in time
500 The pole could not allocate memory or save
503 The pole is busy, updating firmware, or waiting for a restart

Errors other than 503 come back as a short plain-text message, not JSON. If a save fails (500), the running settings are unchanged, but some of the new values may already be stored and will load at the next restart. A GET shows only the running settings, so it cannot tell you which. Resend the complete change with "save": true, or restore a full backup, before the pole restarts.

Only one program should change a pole's settings at a time. The pole handles one request at a time, but it has no revision check, so one program can overwrite another's changes without warning. It accepts up to three HTTP connections at once.

Settings

These tables are for standard pole controllers; TS-ESP controller boards differ (see Not covered here). Use whole numbers, and 0 or 1 (not true/false) for on/off settings unless the table says otherwise. Text lengths are in bytes.

Identity and network

Setting Values Default Applies
id.name text, up to 24 bytes depends on pole Live; the .local name changes at the next restart
net.ip IPv4 address, e.g. "192.168.5.12" depends on pole Restart
net.gw IPv4 address 192.168.5.1 Restart
net.mask IPv4 address 255.255.255.0 Restart
net.mcast IPv4 multicast address for DDP 239.192.0.1 on most poles Restart
mdns_enable 0 or 1 1 Restart

Changing net.ip moves the pole to a new address after it restarts. Make sure the new address is free and that you can still reach it.

Streaming receivers

Setting Values Default Applies
ddp.enable 0 or 1 1 Restart
ports.ddp 1–65535 4048 Restart
ddp.atomic 0 or 1; 1 shows only complete frames 1 Live
dmx.sacn_enable 0 or 1 1 Restart
dmx.artnet_enable 0 or 1 1 Restart
dmx.start_uni 0–63999; sACN needs 1 or more; keep Art-Net within 0–32767 1 Live

LED output

Setting Values Default Applies
led.color_order 0 RGB, 1 RBG, 2 GRB, 3 GBR, 4 BRG, 5 BGR 2 Live
led.gamma 0.1–5.0 (decimals allowed) 1.0 Restart
led.max_power power limit in milliwatts, 0–1000000 30000 Live

led.strips, led.pixels, led.map_mode and led.strip_order describe how the pole is built and wired. Read them to size your frames; do not change them unless PoleFX support asks you to.

Text on the pole

The pole can draw a short text message over its built-in patterns. This feature is provisional: it is documented from the firmware source and has not yet been verified on a real pole.

Setting Values Default Applies
text.msg text, up to 63 bytes empty Live
text.color [r, g, b], each 0–255 [255,255,255] Live
text.brightness 0–100 (percent) 100 Live
text.flags add together: 4 show text, 1 add a second copy on the far side of the pole, 2 repeat the message along the pole, 8 keep lowercase letters (otherwise all capitals) 0 (text off) Live
text.h_mode 0 still, 1 scroll left, 2 scroll right 0 Live
text.v_mode 0 still, 1 up, 2 down, 3 bounce 0 Live
text.fx_mode 0 none, 1 pulse, 2 pulse and fade, 3 ripple 0 Live
text.h_rate, text.v_rate scroll speed, −2000 to 2000 pixels per second 20 Live
text.fx_rate effect speed, 0–2000 5 Live

Use the values listed. The API accepts wider numbers for the modes and rates, but when the pole saves them it turns an unknown mode into 0 and limits rates to the ranges above, so a reading after a restart can differ from what you sent.

Other settings in the document (built-in pattern rotation under idle, report and service ports, and the remaining led fields) are for the Player and PoleFX tools. Keep them when you back up and restore a pole, but do not change them.

Read-only info

info is ignored if you POST it back. Fields can be added in later firmware, so ignore ones you do not recognize.

Field Meaning
info.fw, info.built Firmware version (for example lg1-2026.07) and build date
info.mac Ethernet MAC address
info.uptime_s Seconds since the pole started
info.mdns_host .local hostname without the suffix, or empty
info.ddp DDP counters, including packets, published, incomplete, malformed, unaligned, foreign_source, stream_busy
info.sacn, info.artnet sACN and Art-Net counters, including packets, published, incomplete_frame, wrong_universe, bad_stride, malformed, foreign_source, stream_busy; want_uni_first, want_uni_last and last_bad_universe appear when a wrong universe has arrived

Counters start from zero when the pole starts. Record info.fw alongside any counter readings you keep.

Not covered here

  • Player control. Patterns, scenes and brightness across a show are set through the Player's web app, front panel or DMX. There is no published Player API.
  • Firmware updates. Use the Player.
  • OSC. Poles still accept an older OSC settings channel on UDP 7878, used by older Players. It is not a supported integration interface; use the configuration API instead.
  • TS-ESP controller boards (firmware versions starting ts1-) differ from the tables above: their hostname is ts-esp-<MAC address>.local, led.max_power is 1–1000000 and needs a restart, and the configuration API rejects changes to net.ip, net.gw, net.mask and net.report_ip, which go through a separate commissioning process. Contact PoleFX before integrating with one.

Tested status

This page is written from the pole firmware source for release 2026.07 (source revision 9499e1e). The request and packet formats match that source; other builds may differ. The example commands have not yet been run on a real pole. Check them, and the Gen 1, Gen 2 and short-pole frame sizes, on your pole before a show. Text on the pole and backup and restore are provisional until they have been verified on a real pole. OSC is not supported.