Posts from your endpoint
Let a schedule call a small service of yours when the collection runs dry; the service answers with the posts to publish.
Instead of an agent, a few lines of code can keep a collection fed: a schedule with Call an endpoint that returns posts POSTs to your URL whenever it finds nothing to publish, and publishes whatever your endpoint answers with, at that same slot.
What you need
- Staqly running (Quickstart) with a connected channel.
- Its access token in
STAQLY_API_KEYfor the curl commands:export STAQLY_API_KEY=$(staqly serve token)(Docker:$(docker exec staqly server token)). - Somewhere to run a tiny HTTP service that staqly can reach (the
network policy applies: LAN targets are fine
in Staqly Community Edition, loopback needs
WEBHOOK_ALLOW_LOOPBACK=true).
Build it
Write the endpoint
It verifies the signature, picks something to say and answers {"posts": [...]}:
import { createHmac, timingSafeEqual } from 'node:crypto'
import { createServer } from 'node:http'
const SECRET = process.env.STAQLY_ENDPOINT_SECRET!
const tips = ['Drag a post on the calendar to move it.', 'Customize the text per channel.', 'Retry one channel, not the whole post.']
createServer((req, res) => {
let raw = ''
req.on('data', (c) => (raw += c))
req.on('end', () => {
const ts = String(req.headers['x-staqly-timestamp'] ?? '')
const sig = String(req.headers['x-staqly-signature'] ?? '')
const expected = 'sha256=' + createHmac('sha256', SECRET).update(`${ts}.${raw}`).digest('hex')
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300 || sig.length !== expected.length || !timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
res.writeHead(401).end()
return
}
const { slot } = JSON.parse(raw) // also: schedule, collection_id, channels
const tip = tips[new Date(slot).getDate() % tips.length]
res.writeHead(200, { 'content-type': 'application/json' })
res.end(JSON.stringify({ posts: [{ content: `Tip of the day: ${tip}`, tags: ['tips'] }] }))
})
}).listen(8787)A post without targets goes to the schedule's channels; add targets, media (ids from
POST /v1/media) or metadata when you need them. Up to 50 posts per answer are used.
Create the schedule
curl -s -H "Authorization: Bearer $STAQLY_API_KEY" -X POST http://localhost:3333/v1/schedules -H 'Content-Type: application/json' -d '{
"collection": "Daily tips",
"name": "Tip of the day",
"kind": "recurring",
"rule": { "times": ["09:00"], "tz": "Europe/Warsaw" },
"channels": ["ch_7h2kq9xw3nbvd5yhzm6a"],
"pick": "next",
"source": "endpoint",
"endpoint_url": "http://192.168.1.20:8787/tips",
"endpoint_secret": "a-long-random-secret"
}'Set endpoint_secret yourself, or leave it empty: staqly then generates one and returns it in
full once, in the create response (the dashboard shows it once after Create schedule); copy it
then, since every later read shows it masked as **** plus its last 4 characters. In the dashboard the same is New schedule → When
nothing is waiting → Call an endpoint that returns posts, with the URL and the secret.
Try it
Run now on the schedule (or POST /v1/schedules/{id}/run). With no draft in the
collection, the run calls your endpoint, creates the post with source: "schedule:Tip of the day" and publishes it. last_result on the schedule says what happened; a bad answer records
schedule.failed with the reason and is retried with backoff.
Variations
- Drafts first. Drafts written by hand or by an agent are always picked before the endpoint is asked; the endpoint only fills the gaps.
- An LLM behind the endpoint. Call your model inside the handler; the 60-second budget is enough for a short post.
- Different content per channel. Return
targetswith acontentper channel instead of onecontent.
Reference
- Schedules: the request, the signature and the answer format.
- Verifying signatures: the same code in Python and Go.
Publish through n8n
Add a channel on your own automation, receive each post in an n8n workflow, publish it wherever you like and report the result back.
Manage from your phone
Connect your phone to a staqly running on your laptop and check the calendar, move a post or publish one from anywhere on your Wi-Fi.