# Connecting accounts

How social, messaging, ads, store and workspace accounts get into Pozy, and how to keep them connected.

An account is one connected identity on a platform: an Instagram profile, a Facebook Page, a Slack channel, a Shopify store, a Gmail mailbox. Every account lives inside a [profile](https://pozy.ai/docs/build/profiles). You connect it once, then post, read and reply through its `accountId`.

This page explains the connect methods, the flow most platforms use, and what to do after an account is connected.

## Connect methods

Each platform uses one of four methods. The method decides whether the user leaves your app and what you have to collect.

| Method | What happens | Platforms |
| --- | --- | --- |
| OAuth | You request a connect URL, the user approves on the platform, and Pozy sends them back to your `redirect_url`. | Instagram, Facebook, TikTok, YouTube, LinkedIn, X, Threads, Pinterest, Google Business Profile, Snapchat, Google, Microsoft, HubSpot, Shopify, WordPress.com, Wix, Webflow, Google Analytics and the ad networks |
| Credentials | You send a token or app password the user created on the platform. No redirect. | Bluesky, self-hosted WordPress and WooCommerce, Webflow site tokens, Shopify custom apps, WhatsApp system user tokens, ChatGPT Ads |
| Bot install | The user adds Pozy's bot to a workspace, then picks the channels it posts to. | Slack. Discord and Telegram are coming soon |
| Phone number | You buy or port a number in Pozy, and it becomes an account. | SMS, RCS, iMessage, WhatsApp numbers bought in Pozy |

[Credentials and bots](https://pozy.ai/docs/connect/credentials) covers the second and third rows. Phone numbers are covered in [Phone, SMS & voice](https://pozy.ai/docs/telephony).

| Platform | Publish | Analytics | DMs | Comments | Reviews | Connect |
| --- | --- | --- | --- | --- | --- | --- |
| Instagram | Yes | Yes | Yes | Yes | – | OAuth |
| TikTok | Yes | Yes | Yes | Yes | – | OAuth |
| YouTube | Yes | Yes | – | Yes | – | OAuth |
| Facebook | Yes | Yes | Yes | Yes | Yes | OAuth |
| LinkedIn | Yes | Yes | – | Yes | – | OAuth |
| X | Yes | Yes | Yes | Yes | – | OAuth |
| Threads | Yes | Yes | – | Yes | – | OAuth |
| Pinterest | Yes | Yes | – | – | – | OAuth |
| Bluesky | Yes | Yes | Yes | Yes | – | Credentials |
| Google Business Profile | Yes | Yes | – | – | Yes | OAuth |
| Snapchat (beta) | Yes | Yes | – | – | – | OAuth |
| Reddit (paused) | Yes | Yes | Yes | Yes | – | OAuth |
| WhatsApp | Yes | – | Yes | – | – | Credentials |
| Telegram (coming soon) | Yes | – | Yes | – | – | Bot token |
| Discord (coming soon) | Yes | – | – | – | – | Bot token |
| Slack | Yes | – | Yes | – | – | Bot token |
| iMessage | – | – | Yes | – | – | Phone number |
| SMS | – | – | Yes | – | – | Phone number |
| RCS | – | – | Yes | – | – | Phone number |
| Meta Ads | – | – | – | – | – | OAuth |
| Google Ads | – | – | – | – | – | OAuth |
| TikTok Ads | – | – | – | – | – | OAuth |
| LinkedIn Ads | – | – | – | – | – | OAuth |
| Pinterest Ads | – | – | – | – | – | OAuth |
| X Ads | – | – | – | – | – | OAuth |
| ChatGPT Ads | – | – | – | – | – | API token |
| Reddit Ads | – | – | – | – | – | OAuth |
| Whop Ads | – | – | – | – | – | API token |
| Shopify | – | – | – | – | – | OAuth |
| WooCommerce | – | – | – | – | – | Credentials |
| WordPress | – | – | – | – | – | OAuth |
| Wix | – | – | – | – | – | OAuth |
| Webflow | – | – | – | – | – | API token |
| HubSpot | – | – | – | – | – | OAuth |
| Google Analytics | – | – | – | – | – | OAuth |
| Google Workspace | – | – | – | – | – | OAuth |
| Microsoft 365 | – | – | – | – | – | OAuth |

## The OAuth flow

Most connects follow the same five steps, whatever the platform.

### Request a connect URL

Call `GET /v1/connect/{platform}` with the `profileId` the account should join and the `redirect_url` the user returns to.

```bash cURL
curl "https://api.pozy.ai/v1/connect/linkedin?profileId=6650c1f2a9e4b7d3c8a1f0e2&redirect_url=https://app.example.com/connected" \
  -H "Authorization: Bearer $POZY_API_KEY"
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/connect/linkedin?profileId=6650c1f2a9e4b7d3c8a1f0e2&redirect_url=https:%2F%2Fapp.example.com%2Fconnected", {
  headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
// Send the user's browser to data.authUrl
```
```python Python
import os
import requests

resp = requests.get(
    "https://api.pozy.ai/v1/connect/linkedin",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    params={"profileId": "6650c1f2a9e4b7d3c8a1f0e2", "redirect_url": "https://app.example.com/connected"},
    timeout=30,
)
auth_url = resp.json()["authUrl"]
```

### Send the user to `authUrl`

Redirect the browser, or open it in a new tab or an in-app browser. The link works for 30 minutes.

### The user approves on the platform

They sign in on the platform and approve the permissions Pozy asks for. You can [ask for fewer permissions](https://pozy.ai/docs/connect/scopes) with `scopes`.

### The user picks a Page, location or board

Facebook, Instagram (with Facebook Login), LinkedIn, Pinterest, Google Business Profile, Snapchat, WhatsApp, Slack and Google Analytics end with a choice. Pozy shows its own picker, or you build one in [headless mode](https://pozy.ai/docs/connect/headless).

### Pozy redirects back

The browser lands on your `redirect_url` with the result in the query string:

```text
https://app.example.com/connected?connected=linkedin&profileId=6650c1f2a9e4b7d3c8a1f0e2&accountId=6651d3a7b2c9e4f1a0b8c7d6&username=acme&stage=callback&request_id=req_...
```

Store `accountId`. It is the id every other endpoint takes.

The [hosted connect pages](https://pozy.ai/docs/connect/hosted-connect) guide covers every parameter, the success and error redirects, and what your users see along the way.

## After an account is connected

| Job | Call |
| --- | --- |
| List a profile's accounts | `GET /v1/accounts?profileId=...` ([listAccounts](https://pozy.ai/docs/api/listAccounts)) |
| Check tokens and permissions | `GET /v1/accounts/{accountId}/health` ([account health](https://pozy.ai/docs/connect/account-health)) |
| Reconnect the same account | `GET /v1/connect/{platform}` with `reconnectAccountId` |
| Move it to another profile | `PATCH /v1/accounts/{accountId}` with `{ "profileId": "..." }` ([moveAccountToProfile](https://pozy.ai/docs/api/moveAccountToProfile)) |
| Disconnect it | `DELETE /v1/accounts/{accountId}` ([deleteAccount](https://pozy.ai/docs/api/deleteAccount)) |

A profile can hold several accounts on the same platform. Connecting a different account adds a new one. Connecting the same account again keeps its `accountId` and its history, so a reconnect never breaks your stored ids. Ads connections are the exception: one per platform per profile.

> **Listen instead of polling:**
> 
> Subscribe to `account.connected` and `account.disconnected`. A connect started in one tab and finished on a phone still reaches your backend, and you hear about expired tokens without checking every account.

## Billing gates

Connecting an account can return `402 payment_required` when:

| Reason | What it means |
| --- | --- |
| `free_tier_exceeded` | The workspace already has its free accounts and no payment method. |
| `twitter_passthrough` | X bills every API call, so connecting any X account needs a payment method. |
| `enterprise_required` | The workspace hit a cap set in its contract. |

The response carries a `dashboard_url` that opens billing in the dashboard. Send the workspace owner there. See [Pricing](https://pozy.ai/docs/billing) for what each account costs.

## Webhook events

| Event | When it fires |
| --- | --- |
| [`account.connected`](https://pozy.ai/docs/webhooks/events#account-connected) | Account connected. |
| [`account.rate_limited`](https://pozy.ai/docs/webhooks/events#account-rate-limited) | Mailbox sending cooldown started. |
| [`account.disconnected`](https://pozy.ai/docs/webhooks/events#account-disconnected) | Account disconnected. |
| [`account.permissions_changed`](https://pozy.ai/docs/webhooks/events#account-permissions-changed) | Account permissions changed. |
| [`account.ads.initial_sync_completed`](https://pozy.ai/docs/webhooks/events#account-ads-initial-sync-completed) | Ads initial sync completed. |
| [`account.ads.sync_failed`](https://pozy.ai/docs/webhooks/events#account-ads-sync-failed) | Ads sync failed. |
| [`account.ads.sync_recovered`](https://pozy.ai/docs/webhooks/events#account-ads-sync-recovered) | Ads sync recovered. |

## In this section

- [Hosted connect pages](https://pozy.ai/docs/connect/hosted-connect): Connect URLs, redirects, results and errors.
- [Headless selection](https://pozy.ai/docs/connect/headless): Build your own Page, location and board picker.
- [Credentials and bots](https://pozy.ai/docs/connect/credentials): Bluesky, WordPress, Webflow, Shopify, WhatsApp and Slack.
- [Welcome screen](https://pozy.ai/docs/connect/welcome-screen): Show your brand before the platform's consent screen.
- [Phone handoff](https://pozy.ai/docs/connect/phone-handoff): Let desktop users finish on their phone with a QR code.
- [Scopes](https://pozy.ai/docs/connect/scopes): Ask only for the permissions your product uses.
- [Your own platform apps](https://pozy.ai/docs/connect/own-apps): Coming soon. Put your app's name on the consent screen.
- [Account health](https://pozy.ai/docs/connect/account-health): Tokens, permissions, sync status and reconnects.
- [Account groups](https://pozy.ai/docs/connect/account-groups): Save sets of accounts you post to together.

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/connect/{platform}`](https://pozy.ai/docs/api/getConnectUrl) | Get OAuth connect URL |
| [`GET /v1/connect/{platform}/ads`](https://pozy.ai/docs/api/connectAds) | Connect ads for a platform |
| [`GET /v1/connect/handoffs/{handoffId}`](https://pozy.ai/docs/api/getConnectHandoff) | Get a phone handoff |
| [`GET /v1/connect/pending-data`](https://pozy.ai/docs/api/getPendingOAuthData) | Get pending OAuth data |
| [`GET /v1/accounts`](https://pozy.ai/docs/api/listAccounts) | List accounts |
| [`GET /v1/accounts/health`](https://pozy.ai/docs/api/getAllAccountsHealth) | Check accounts health |
| [`GET /v1/accounts/{accountId}/health`](https://pozy.ai/docs/api/getAccountHealth) | Check account health |
| [`PUT /v1/accounts/{accountId}`](https://pozy.ai/docs/api/updateAccount) | Update account |
| [`PATCH /v1/accounts/{accountId}`](https://pozy.ai/docs/api/moveAccountToProfile) | Move account to another profile |
| [`DELETE /v1/accounts/{accountId}`](https://pozy.ai/docs/api/deleteAccount) | Disconnect account |

Every connect endpoint, including each platform's selection and credential calls, is listed under **Connect** in the [API reference](https://pozy.ai/docs/api#connect).
