To generate Open Graph images or website screenshots in n8n, use the built-in HTTP Request node: method POST, URL https://shareglint.com/v1/images?wait=true (or /v1/screenshots?wait=true), a Bearer Auth credential holding your sk_live_… key, and a JSON body with the template and the fields mapped from your trigger. The response carries the finished image's public url, which the next node can store, post or send. There is no official Shareglint node in n8n's directory and no community node to install — the HTTP Request node is the supported way, and it reaches every endpoint.
Each image is one render against your monthly quota (100 on the Free plan); an image identical to one you already have costs nothing.
Set up the credential once
n8n's HTTP Request node has a Generic Credential Type authentication with a Bearer Auth option (n8n credential docs). Create it once and reuse it in every node:
- In the HTTP Request node, set Authentication to Generic Credential Type, then Generic Auth Type to Bearer Auth.
- Create a new credential and paste your key into Bearer Token. n8n sends it as
Authorization: Bearer sk_live_….
Header Auth works too: Name Authorization, Value Bearer sk_live_…. Either way the key lives in n8n's encrypted credential store, not in the workflow JSON, so exporting or sharing the workflow does not leak it. Create a separate key for n8n in the Shareglint dashboard, so you can revoke it without touching anything else.
Recipe 1: an OG image per new blog post (RSS)
RSS Feed Trigger → HTTP Request → wherever the image goes.
The RSS Feed Trigger polls a feed URL and emits one item per new entry, with fields such as title and link. Configure the HTTP Request node (node reference):
- Method:
POST - URL:
https://shareglint.com/v1/images?wait=true - Authentication: the Bearer credential above
- Send Body: on, Body Content Type:
JSON, Specify Body:Using JSON - JSON:
{
"template": "blog-og",
"format": "jpeg",
"modifications": {
"title": {{ JSON.stringify($json.title) }},
"eyebrow": "Blog",
"site": "yourblog.com"
}
}
JSON.stringify matters: a title with a quote in it (The "boring" stack) would otherwise break the JSON. Writing "{{ $json.title }}" inside quotes is the usual cause of a 400/422 on the second or third post.
?wait=true holds the connection until the image is ready and returns 200 with the render (abridged):
{
"id": "img_01m08…",
"kind": "image",
"status": "completed",
"format": "jpeg",
"size": "og",
"width": 1200,
"height": 630,
"url": "https://…/img_01m08….jpg"
}
In the next node use {{ $json.url }} — a Google Sheets Update Row, a CMS update, a Slack or Discord message, or a social scheduler. To render the same post for Instagram as well, send "sizes": ["og", "square"] instead of a single size; the response becomes {"renders": [...]}, one entry per size and one render each.
Recipe 2: rows of a Google Sheet
Google Sheets Trigger (row added) → HTTP Request → Google Sheets (Update Row).
Column values arrive under their header names, so with columns Title and Author the JSON body is:
{
"template": "blog-og",
"modifications": {
"title": {{ JSON.stringify($json.Title) }},
"author": {{ JSON.stringify($json.Author) }}
}
}
Write {{ $json.url }} back into an Image column of the same row. For a sheet that already has hundreds of rows, do not loop: one POST /v1/batches with csv_url set to the sheet link renders them all, checks the quota for the whole batch first and returns a ZIP — see bulk images from a sheet.
Recipe 3: a webhook from your app or CMS
Webhook → HTTP Request → Respond to Webhook.
Point your CMS's "post published" webhook at the n8n Webhook node. Its output puts the request body under body, so map {{ JSON.stringify($json.body.title) }}. The workflow can answer the caller with the image URL, or update the post through the CMS's API.
Recipe 4: a screenshot of a page
Same node, different endpoint — POST https://shareglint.com/v1/screenshots?wait=true with the page URL from the trigger:
{
"url": {{ JSON.stringify($json.link) }},
"device": "iphone-15",
"full_page": true,
"lazy_load": true,
"block_cookie_banners": true,
"format": "webp"
}
The response has the same shape, with kind: "screenshot" and the file in url. A viewport screenshot costs 1 render and a full page 2; the same URL with the same options within 24 hours returns the existing file for free. Only public http(s) pages can be captured; a page that fails to load comes back as status: failed with the reason (with ?wait=true, as a 500), and its render is refunded.
Handling errors: 402, 429, 503
By default a 4xx or 5xx answer stops the workflow. Either set Settings → On Error to Continue (using error output) (node settings) so a failed call becomes an item on the error branch, or turn on Never Error and Include Response Headers and Status in the node's Response options so the status code travels with the item and an If node can branch on it. Then handle each status deliberately:
| Status | error |
What to do in n8n |
|---|---|---|
402 |
quota_exceeded |
Stop and notify (email, Slack). Retrying will not help until the quota renews or you add a top-up; nothing was charged. |
429 |
— | Too many requests per minute. Retry later; the Retry-After header says when. |
503 |
sync_overloaded |
The render is still running. The body has its id; fetch it later with GET /v1/images/{id}. |
422 |
— | A field is wrong (the message says which) — usually broken JSON or an unknown template. Fix the mapping; retrying sends the same mistake. |
For 429, three settings help: Retry On Fail in the node settings, the Batching option (Items per Batch and Batch Interval) to pace a long list, and for big runs a single POST /v1/batches instead of one call per row. The per-minute limit depends on your plan.
Retries without paying twice. Add a header Idempotency-Key with a value unique to the item, such as {{ $json.link }} or the sheet row number. A retried request with the same key and body returns the first response instead of rendering again. Even without it, the same template with the same fields reuses the existing image and costs nothing.
Async instead of wait
?wait=true is the simplest in n8n because one node yields the URL. For animated gif/mp4 renders or heavy batches you can drop wait: the API answers 202 with an id at once, and either a Wait node plus GET /v1/images/{id}, or a webhook_url pointing at a second workflow's Webhook node (events image.completed, image.failed, screenshot.completed), collects the result.
AI Agent workflows
If you build an n8n AI Agent rather than a fixed pipeline, its MCP client tool can call Shareglint's MCP server at https://shareglint.com/mcp with Bearer authentication — the same tools Claude and Cursor use. The server speaks the Streamable HTTP transport only (not the older SSE one), so check that your n8n version offers it. For fixed workflows like the recipes above, the plain HTTP Request node is simpler, cheaper to debug and fully predictable.
The full API reference, every template field and the error codes are in the docs. For the same recipes in Make, see the Make guide.