Every private plugin has a Strategy, which decides how data reaches TRMNL before your markup turns it into a screen. You pick it on the plugin's settings page, and the form then hides everything except the fields that strategy actually needs.
Prerequisites
A TRMNL account with the Developer add-on, or a BYOD license
A private plugin to configure
Which one to pick
Polling is the default, and the right choice when your data sits behind a URL TRMNL can reach.
Webhook is for when your own script or automation sends data to us whenever it changes.
Static works when the data rarely changes, so you paste it in once and forget about it.
Plugin Merge builds one screen from data your other plugins already fetch.
Async Polling is for servers that need minutes, not seconds, to build the answer.
None is for markup that needs no data at all, or fetches its own with JavaScript.
Polling
With Polling, TRMNL fetches your URL on every refresh, and you tell us how with these fields:
Polling URL(s) takes one URL per line, and JSON, XML, CSV and plain text responses all work.
Polling Verb is either GET or POST.
Polling Headers takes one header per line, written as Name: Value or name=value.
Polling Body is optional, and comes in handy for GraphQL and other POST requests.
The URL, headers and body all accept Liquid, so you can insert form field values such as {{ api_key }} wherever you need them. We recommend keeping keys out of the URL itself, so put them in a password form field and reference that instead.
With one URL, the response fields become top-level variables, while with several URLs each response sits under its own IDX_0, IDX_1 and so on. If a response is a list rather than an object, it arrives under data.
TRMNL polls as often as Max refresh rate allows, which is every 15 minutes at the fastest, or every 5 minutes with TRMNL+. The plugin's author can also set a slower floor with Fastest refresh rate.
Limits:
TRMNL waits 10 seconds for an answer, then tries once more before giving up.
TRMNL refuses URLs that resolve to a private address such as 192.168.x.x, so your server must be reachable from the internet.
The combined data must stay under 100 KB, and if you need more than that, reduce it with Serverless first.
Webhook
Save the plugin, then copy the Webhook URL from its settings and POST JSON to it, with your data inside a merge_variables object, for example {"merge_variables": {"temperature": 21}}.
By default each push replaces whatever is stored. Add "merge_strategy": "deep_merge" to merge into the stored data instead, or use "merge_strategy": "stream" with "stream_limit": 10 to append to top-level lists and keep only the latest 10 items. A GET to the same URL returns what is stored right now, which is handy when you want to check your work.
Limits:
Stored data may be 5 KB, or 10 KB with TRMNL+, and this counts the stored total after a merge, not only the latest push.
By default each plugin accepts 12 pushes an hour, or 30 with TRMNL+.
If the plugin has a Serverless script, a push may be up to 1 MB, because the script runs first and only its result has to fit the 5 KB or 10 KB limit.
A push renders a new screen soon after it arrives, but at most once every 15 minutes, so a push inside that window waits for the next refresh. Either way, your device shows the new screen at its next check-in.
If you'd rather push a finished image than data, use Webhook Image instead.
Static
Paste valid JSON into Static Data and its keys become your variables. Because TRMNL fetches nothing, the data only changes when you edit it, which makes Static a good fit for lists you keep by hand, such as holidays.
Plugin Merge
Plugin Merge reads data that your other plugins on this account already fetched, whether they're native or private. If you want to redesign a native plugin's screen this way, see Using Data Mode to Redesign a Native Plugin.
Each plugin's data sits under its keyname and settings id, for example weather_12345, and you can see the exact names by opening Edit Markup, then Your Variables. TRMNL only loads the plugins your markup names, plus any picked in a plugin instance form field, and they don't need to be on a playlist. When a webhook plugin among them receives data, the merge refreshes too, so your combined screen stays current.
Async Polling
On each refresh TRMNL calls your first Polling URL and expects HTTP 202 straight away, which tells us your server is on it. When the data is ready, your server POSTs {"merge_variables": {...}} to the callback URL.
Put {{ callback_url }} in your Polling URL so your server receives the right address. Each request carries its own version, which means a copy of the Callback URL field on its own is refused.
Limits:
The callback must arrive within 15 minutes, and until it does, the screen keeps showing the previous data.
The same size limits as Webhook apply, so 5 KB, or 10 KB with TRMNL+.
Async Polling never runs a Serverless script.
None
With None, TRMNL passes no data except the global trmnl variables, which is all you need for a clock, a fixed message, or markup whose JavaScript fetches what it needs on its own.
Troubleshooting
A "degraded" or error banner on the plugin
A fetch or push failed, and the banner tells you why. After repeated failures TRMNL stops refreshing the plugin altogether, so fix the cause, then click Reset Health to get it going again.
"the url resolves to a private address"
The URL points at your home network, which we can't reach. Either make the server public, or push from inside your network with Webhook.
"no response within 10s"
Your server took too long to answer, so cache the answer on your server, or switch to Async Polling.
"Large payload received ..., should be less than 5kb"
Send fewer fields, upgrade to TRMNL+ for 10 KB, or add a Serverless script to trim the push before it's stored.
A push answers 429
You hit the hourly limit, so combine your changes into fewer pushes.
A push answers 422 saying "Strategy" must be set to Webhook
The plugin uses another strategy, so change Strategy to Webhook and save.
The callback answers 410
Either the 15 minutes passed, a newer request started, or the version is wrong, so make sure you use the {{ callback_url }} from the request itself.
Variables are missing with several polling URLs
Read them through IDX_0, IDX_1 and so on, and see Missing Data in Multiple Polling URLs for more.
Related

