Connecting accounts

Account health

Check token status, granted permissions and sync status for every connected account, and catch disconnects before your users do.

Connected accounts break for reasons outside your control: a password change on the platform, a revoked app, an expired token, a Page role removed. Account health tells you, per account, whether Pozy can still post and read analytics, what is wrong if not, and what to do about it.

#Check every account

GET /v1/accounts/health returns a summary and one row per account. Filter with profileId, platform or status.

curl "https://api.pozy.ai/v1/accounts/health?status=error" \
  -H "Authorization: Bearer $POZY_API_KEY"
Response
{
  "summary": { "total": 14, "healthy": 11, "warning": 2, "error": 1, "needsReconnect": 1 },
  "accounts": [
    {
      "accountId": "6651d3a7b2c9e4f1a0b8c7d6",
      "platform": "linkedin",
      "username": "acme",
      "profileId": "6650c1f2a9e4b7d3c8a1f0e2",
      "status": "error",
      "canPost": false,
      "canFetchAnalytics": false,
      "tokenValid": false,
      "needsReconnect": true,
      "issues": ["The access token is no longer valid."],
      "disconnectionType": "unintentional",
      "unhealthySince": "2026-10-29T18:04:11.000Z",
      "analyticsSync": { "status": "failing", "lastSyncedAt": "2026-10-28T06:00:00.000Z" }
    }
  ]
}

A profile-scoped key only sees the accounts in its profiles, and the summary counts only those.

#Check one account in detail

GET /v1/accounts/{accountId}/health adds the token details, the scope-by-scope permission list and recommendations.

Field What it tells you
status healthy, warning or error.
tokenStatus valid, expiresAt, expiresIn and needsRefresh. Pozy refreshes tokens on its own; this is for diagnosis.
permissions Each scope in the posting, analytics and optional groups with granted and required, plus canPost, canFetchAnalytics and missingRequired. See Scopes.
issues Plain-language problems, ready to show an operator.
recommendations What to do next, for example reconnecting through a specific endpoint.
analyticsSync ok, failing, stalled or never_synced, with lastSyncedAt. A failing or stalled sync raises a healthy account to at least warning.
messagingRestriction Set when the platform has paused messaging on the account, with the platform's code, message and pausedUntil.
platformConnection WhatsApp only: a live check of the number behind the account. See below.
disconnectReason, disconnectionType, unhealthySince Why and since when the account stopped working.

#What status means

status Meaning Typical action
healthy Posting and analytics work. None.
warning The account works, but something needs attention, for example a failing analytics sync. Read issues.
error Pozy cannot use the account for at least one core job. Reconnect, or fix the cause in issues.

#Meta accounts

For Facebook, Instagram and Threads, Pozy also checks the token live with Meta. Meta sometimes refuses a valid token for a moment, so a refusal does not mark the token invalid if an analytics sync succeeded with it in the last six hours; issues then says the check was inconclusive. Health checks never disconnect an account on their own.

#WhatsApp

A WhatsApp account's token can be valid while Meta no longer serves the number behind it, for example after the number was disconnected from the WhatsApp Business app on the phone. platformConnection is the live check:

  • platformConnection.status: "disconnected" sets the overall status to error.
  • inboundWebhookSubscribed: false means incoming messages are not reaching Pozy. It adds an issue and sets status to at least warning.

For WhatsApp, poll health rather than relying only on the account.disconnected event. See WhatsApp phone numbers.

#How disconnects reach you

account.disconnected fires when an account stops working or is removed. How fast depends on what happened:

Cause disconnectionType When the event fires
You called DELETE /v1/accounts/{accountId} intentional Immediately.
WhatsApp number disconnected from the phone unintentional Within seconds of Meta's notice. reason carries Meta's explanation.
A publish or analytics sync gets a definitive auth error unintentional On that call. For publishing, Pozy tries a token refresh first, so the event means the refresh failed too.
Access revoked quietly on the platform side unintentional When Pozy's periodic checks confirm it, from minutes to about a day later.

Do not treat the absence of account.disconnected as proof an account works. Combine the webhook with a scheduled health check.

#Reconnect an account

Send the user through the connect flow again with reconnectAccountId. The account keeps its id, posts and analytics history.

Terminal
curl "https://api.pozy.ai/v1/connect/linkedin?profileId=6650c1f2a9e4b7d3c8a1f0e2&reconnectAccountId=6651d3a7b2c9e4f1a0b8c7d6&redirect_url=https://app.example.com/connected" \
  -H "Authorization: Bearer $POZY_API_KEY"

For standalone ads connections (Google Ads, Reddit Ads), recommendations points to GET /v1/connect/{platform}/ads instead. Its authUrl reconnects the same ads account.

A reconnect banner that works

Show a banner in your app for every account with needsReconnect: true. Name the platform and the handle, and add a button that calls your backend to create the reconnect URL.

#Facebook Page events

Lead ads, comments and messages on a Facebook Page arrive through the Page's webhook subscription. If one of them stops while the rest still work, read the subscription live with GET /v1/accounts/{accountId}/webhook-subscription and repair it with POST /v1/accounts/{accountId}/webhook-subscription.

#Disconnect an account

DELETE /v1/accounts/{accountId} disconnects the account and fires account.disconnected with disconnectionType: "intentional". Calling it again for the same account returns 404.

#A daily health job

health-check.ts
export async function dailyHealthCheck() {
  const res = await fetch("https://api.pozy.ai/v1/accounts/health", {
    headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error);
  const broken = data.accounts.filter((a) => a.status === "error" || a.needsReconnect);
  for (const a of broken) {
    await notifyOwner(a.profileId, `Your ${a.platform} account @${a.username} needs to be reconnected.`);
  }
}

notifyOwner is your own code: email, in-app message, or a Slack alert to your support team.

#Webhook events

Event When it fires
account.connected Account connected.
account.disconnected Account disconnected.
account.permissions_changed Account permissions changed.

#Endpoints

Endpoint What it does
GET /v1/accounts/health Check accounts health
GET /v1/accounts/{accountId}/health Check account health
GET /v1/accounts List accounts
DELETE /v1/accounts/{accountId} Disconnect account
GET /v1/accounts/{accountId}/webhook-subscription Read a Facebook Page's webhook subscription
POST /v1/accounts/{accountId}/webhook-subscription Re-subscribe a Facebook Page to Pozy's webhooks