What we access and store from Meta
We request least-privilege Meta permissions, store comments and their author display names in an append-only ledger, encrypt access tokens at rest, and delete data on disconnect or on a verified Meta data-deletion request. We cannot post to your Page, and the base connect flow above cannot touch your ad accounts at all — see Ad comments (opt-in) for the one place that changes.
This page is written for a procurement or security reviewer. Every claim maps to the product’s actual behavior. Where a fact is not yet confirmed, it is marked with an explicit TODO rather than softened.
The short version
Section titled “The short version”- We connect to Meta through OAuth. You approve a fixed set of permissions (“scopes”).
- We store comment text and the comment author’s display name and avatar URL, plus the raw provider payload, in an append-only ledger called interactions.
- Access tokens are encrypted at rest (AES-256-GCM).
- The connect flow above requests no advertising permissions, and we cannot create, edit, or delete your Page posts. Opting in to the ad-comments feature requests two read-only advertising scopes separately — see Ad comments (opt-in).
- Disconnecting an account, or a verified Meta data-deletion request, deletes the stored comment data.
Meta permissions we request
Section titled “Meta permissions we request”There are two ways to connect a Meta account, and they request different permissions.
Facebook Login (Facebook Pages + linked Instagram)
Section titled “Facebook Login (Facebook Pages + linked Instagram)”| Permission (scope) | Why we request it | What it grants |
|---|---|---|
email | Identify the connected account | Read the connected account’s email |
pages_show_list | Let you pick which Page to monitor | List your Facebook Pages |
pages_read_engagement | Read the comments to moderate | Read Page posts and comments |
pages_read_user_content | See comments left by other people | Read comments authored by other users |
pages_manage_engagement | Run the Flag / Allow / Reply / Delete actions | Reply to, hide, unhide, and delete comments |
pages_manage_metadata | Real-time comment delivery | Subscribe the Page to webhooks |
pages_messaging | Read and reply to DMs on the Page | Read/reply Messenger conversations |
instagram_basic | Read the linked Instagram account | Read the IG account linked to the Page |
instagram_manage_comments | Moderate Instagram comments | Read, hide, reply to, and delete IG comments |
instagram_manage_engagement | Like Instagram comments | Publish or remove a like on an IG comment |
instagram_manage_messages | Read and reply to Instagram DMs | Read/reply IG direct messages |
This table is what we request at the consent screen. Liking a Facebook comment is covered by pages_manage_engagement, and liking an Instagram comment by instagram_manage_engagement. You can decline any individual permission, in which case the matching capability is simply unavailable on that account.
We deliberately do not request pages_manage_posts (which would let us create or edit Page posts). This base dialog also carries none of ads_read, business_management, ads_management, or pages_manage_ads — see Ad comments (opt-in) for the one flow that requests any of them, and for which two.
Ad comments (opt-in)
Section titled “Ad comments (opt-in)”A separate, explicit re-authorization — never part of the connect flow above — requests exactly two additional scopes: ads_read and business_management. Both are read-only: they let us name which ad, ad set, and campaign a comment landed under, and read that ad’s spend from Meta’s Marketing API. We never request ads_management or pages_manage_ads, which would let us create, edit, or pause ads — that capability does not exist in this product on any plan.
This re-request is a distinct OAuth URL your account only sees if you choose to enable ad comments; it widens the grant (every base-connect scope above still applies) rather than replacing it. The base scope list and the ad-comments rerequest are proven to never overlap by an automated test pinning both URLs independently (build_facebook_rerequest_auth_url_requests_rerequest_and_ad_scopes, platforms/src/facebook.rs) — a scope added to one accidentally would turn that test red.
Instagram Login (standalone Instagram)
Section titled “Instagram Login (standalone Instagram)”If you connect a standalone Instagram Business or Creator account instead of going through a Facebook Page, we request only:
| Permission (scope) | Why we request it | What it grants |
|---|---|---|
instagram_business_basic | Read the account and its media | Read profile and media |
instagram_business_manage_comments | Moderate comments | Read, hide, reply to, and delete comments |
instagram_business_manage_messages | Read and reply to Instagram DMs | Read/reply Instagram direct messages |
Both Instagram connection methods request a DM permission — this one under Instagram’s own instagram_business_* naming, the Facebook Page route under instagram_manage_messages above.
The difference between the two methods is Like, not DMs: liking an Instagram comment needs instagram_manage_engagement, which exists only on the Facebook Login dialog, so a standalone Instagram connection cannot like a comment at all.
What the product can never do
Section titled “What the product can never do”Based on the scopes above:
- It cannot post, edit, or delete your Page posts. We do not request
pages_manage_posts. We can reply to comments and send DMs, but we cannot publish or change posts on your timeline. - It cannot manage your ad accounts, ads, or ad spend, on any plan. The base connect flow requests no advertising scopes at all. Opting in to ad comments (see above) grants two read-only scopes so a comment can be labelled with its ad, campaign and spend — nothing broader, and nothing that can create, edit, pause, or spend against an ad account.
What we store versus discard
Section titled “What we store versus discard”When a comment (or DM) is ingested, it is written to an append-only interactions ledger. We store, rather than discard, the following:
| Data element | Stored? | Notes |
|---|---|---|
| Comment text | Stored | The full comment body |
| Author display name | Stored | The commenter’s public display name |
| Author avatar URL | Stored | Link to the commenter’s public avatar |
| Platform comment ID | Stored | Meta’s identifier for the comment |
| Posted-at timestamp | Stored | When the comment was posted |
| Media attachments | Stored | Attachment metadata (JSON) |
| Computed sentiment + confidence | Stored | Derived by us from the comment text |
| Source type | Stored | organic or ad |
| Raw provider payload | Stored | The verbatim Meta webhook/API envelope, retained for audit and replay |
Be precise about this with reviewers: the ledger is append-only and retains the full Meta payload in a raw_payload field, which can include author identifiers beyond the display name. We do not have a documented “process-and-discard” path where comment or author data is used transiently and then thrown away — ingested data is stored.
Nothing is stripped from that payload before it is stored. The comment object exactly as Meta sent it is kept verbatim, including the commenter’s platform user ID — which is also what a private reply is addressed to.
How long we keep it
Section titled “How long we keep it”- Active (non-deleted) comments have no maximum retention period. They are kept for as long as the account and Page stay connected; there is no time-based purge of live interaction data.
- Deleted data is purged 30 days after deletion. When a row is soft-deleted (
deleted_atset), a cleanup job hard-deletes it once it is older than the retention window — 30 days by default. This applies to interactions, audit logs, Workflows, webhooks, Pages, and accounts. So once you disconnect an account or delete data, it is gone within 30 days at most — and immediately in the cases described below.
How deletion works
Section titled “How deletion works”There are three ways stored data is removed.
Disconnecting an account
Section titled “Disconnecting an account”A hard disconnect deletes, in a single transaction, all interactions for that account’s Pages, the Page records, and the account itself. A soft disconnect instead marks the account deleted and disables its Workflows; the cleanup job then purges it after the 30-day retention window.
Meta data-deletion request
Section titled “Meta data-deletion request”Meta requires a data-deletion callback. When Meta sends a signed deletion request, we verify its signature and then perform a synchronous hard delete in one transaction: audit logs, interactions (including system lifecycle rows), Pages, and accounts are deleted, and associated Workflows are deactivated. We record a completed data-deletion request with a 32-character confirmation code and send a best-effort confirmation email. You can check status at the /data-deletion/status/{code} page.
While an account is disconnected
Section titled “While an account is disconnected”If a token expires or an account becomes invalid, ingestion for that Page pauses — it does not silently drop comments. The poll cursor is not advanced while paused, so on reconnect the backlog is re-fetched and processed, bounded by whatever Meta’s API still returns. Comments that fall outside Meta’s retrievable window before you reconnect can be permanently missed. This is the only situation in which ingestion pauses. Ingestion is not metered and has no allowance, so it cannot be stopped by billing: reaching your plan’s included automations pauses automated processing only, and the backlog re-fetched here is free to receive however large it is. For the full behavior, see the connection pages below.