Resolve message attachment
Resolve one attachment on a message to a media url that works right now.
Instagram and Facebook sign DM media urls per request and expire them, so
the url on a message is a snapshot: it works when you read the message
and stops working later. This endpoint checks the stored url and, when it
has gone stale, re-mints the message's media from Meta and persists it
before answering. The message id never expires, so this URL is the one to
store — it is returned on each attachment as refreshUrl.
By default it responds 302 to the live media url, so it can be used
directly as an <img src> on a browser session. API-key integrators
should pass ?format=json and read url off the body, since a browser
cannot attach an Authorization header to an image request.
Only Instagram and Facebook media can be re-minted. On other platforms
the stored url is returned as-is when it still resolves, and 404
otherwise.
API key authentication - use your Zernio API key as a Bearer token
In: header
Path Parameters
The conversation ID (Zernio id or platform conversation id)
The message id as returned by the list-messages endpoint (the platform message id)
Zero-based position of the attachment in the message's attachments array
0 <= valueQuery Parameters
Social account ID
redirect (default) answers 302 to the media; json returns the url in the body
"redirect""redirect" | "json"Response Body
application/json
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.messages.getMessageAttachment({ path: { conversationId: 'conversation_abc123', messageId: 'message_abc123', index: 0, }, query: { accountId: 'account_abc123', },});console.log(data);{
"status": "success",
"url": "string",
"refreshed": true
}{
"error": "string",
"type": "invalid_request_error",
"code": "string",
"param": "string",
"platform": "string",
"platformError": {},
"details": {}
}{
"error": "Unauthorized"
}Send typing indicator POST
Show a typing indicator in a conversation. Platform support: - Facebook Messenger: Shows "Page is typing..." for 20 seconds - Instagram: Shows "typing..." to the recipient (works for both Instagram Login and Facebook Login accounts). The recipient must be signed in to Instagram to see it. - Telegram: Shows "Bot is typing..." for 5 seconds - WhatsApp: Shows "typing..." for up to 25 seconds. Requires a recent inbound message in the conversation (Meta references the inbound message id) and also marks that message as read as a side-effect. - All others: Returns 200 but no-op (platform doesn't support it) Typing indicators are best-effort. The endpoint always returns 200 even if the platform call fails; `success` reports whether a typing indicator was actually sent to the platform (`false` on unsupported platforms or when the platform call failed).
List commented posts GET
Returns posts with comment counts from all connected accounts. Aggregates data across multiple accounts. For users with the Ads add-on (Metronome plans always qualify), the user's Meta ads (boosted/dark posts) are included too. There's one row per (ad, placement-with-comments): an ad that runs on both Facebook feed and Instagram feed produces up to two rows (the Page dark post and the IG media have separate comment threads), each flagged `isAd: true` with `adId` and `placement` (`id` is `{adId}:{placement}`). Use `?platform=metaads` to return *only* ad rows; passing `facebook`/`instagram` returns *organic* posts only (no ads); omitting `platform` returns both. Fetch a row's thread from GET /v1/ads/{adId}/comments?placement={placement}. Ad comment counts are read with the Marketing API token (Facebook side) or the connected Instagram account's token (Instagram side); a row whose count can't be read is omitted. Pagination walks each account's platform listing. Following `nextCursor` reaches past the first page on Facebook and Instagram only, since they are the platforms that support a server-side date window; on the others the listing stops at its first page.