From listing to post.
A great listing deserves a great first impression.
Connect the workflow.
One authenticated request. An image and caption ready for n8n.
POST /render
Send JSON with Content-Type: application/json and Authorization: Bearer <RENDER_API_TOKEN>. Images under /img/ are public and require no credentials.
curl https://posts.gezz.az/render \ -H "Authorization: Bearer $RENDER_API_TOKEN" \ -H "Content-Type: application/json" \ --data @request.json
Request
{
"listingUrl": "https://tezsat.com/az/listing/…",
"title": "", "price": "", "photoUrl": "", "listingNo": "",
"photoPosition": "center center",
"captionTemplate": "{title}\n{price}\n{cta}\n{url}\n{hashtags}",
"cta": "Ətraflı məlumat üçün elana keçid edin",
"hashtags": "#tezsat #elanlar"
}Only listingUrl is required. Empty override fields use the listing data. An empty caption template uses the default. Missing prices display “Razılaşma yolu ilə”. Provide all four listing overrides to render without fetching the listing page.
Response · 200
{
"title": "Kiçik badə və sini dəsti",
"price": "53 ₼",
"listing_no": "01a140bc-b084-709d-8c28-dab7316d328d",
"image_url": "https://posts.gezz.az/img/<random-id>.jpg",
"caption": "Your completed caption…"
}Error responses
Errors use {"error":"Readable reason"}. 400: invalid input or caption. 401: missing or invalid token. 404: listing or image not found. 422: missing/invalid listing data or photo. 502: remote fetch failed. 503: render queue full; retry after 5 seconds. 504: timed out. Configure n8n to retry temporary failures.
Image contract
1080 × 1350 pixels, JPEG, under 8 MB. Filenames use 192 bits of randomness. Files are kept for the configured retention period (default 30 days). The final caption is limited to 2,200 Unicode code points; oversized captions are rejected so URLs and hashtags remain intact.
Health check
GET /healthz returns {"status":"ok"}. Startup verifies Chromium is available. The health check confirms the HTTP process is responding; it does not test Tezsat or Meta connectivity.
A home for your renderer.
Deploy on your own server at posts.gezz.az.
Use the included server guide
DEPLOYMENT.md in the project contains the complete setup for Ubuntu or Debian: Node, Chromium and fonts, environment variables, a systemd service, Nginx, HTTPS, smoke tests, backups and token renewal. A Docker Compose setup with automatic HTTPS via Caddy is also included.
- Point the domain’s DNS to your server.
- Install the app dependencies and Chromium on the server.
- Generate a renderer token and configure the production environment.
- Start the service behind Nginx with a valid TLS certificate, or use Docker Compose.
- Test the endpoint and open the returned JPEG without authentication.
- Give the renderer token to the n8n owner securely, then run the n8n dry run.
Separate Instagram setup
The renderer needs no Meta credentials. The Meta Developer app, professional Instagram account, publishing permission, Instagram User ID, supported API version and access token belong to n8n. Complete that account setup following the checklist in the deployment guide.
Image storage
Keep data/images on persistent storage. The service removes expired images at startup and every six hours, keeping published images for 30 days by default. Do not put login, bot challenges or redirects in front of /img/.
Restart and inspect
sudo systemctl restart tezsat-renderer sudo journalctl -u tezsat-renderer -n 100 --no-pager # Or with Docker Compose: docker compose restart renderer docker compose logs --tail=100 renderer