> ## Documentation Index
> Fetch the complete documentation index at: https://docs.madiad.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Profiles

> Model each brand, client, or sub-account as a profile.

A **profile** is one brand, client, or sub-account you publish on behalf of — a single set of connected social accounts. Every post targets exactly one profile.

It's the same object whichever way you work:

* **In the dashboard** — each brand appears under **Connections** as a profile. Most customers create and connect profiles here, with no code.
* **Via the API** — you reference that same profile by its `profile_id` (`prof_…`) on every post.

One API key manages all your profiles — there's no separate key per brand:

```
Your API key
├── profile: Acme Coffee   → Instagram, Facebook, TikTok
├── profile: Acme Tea      → Instagram, X
└── profile: Client — Nova → LinkedIn, YouTube
```

## How many profiles you get

Each plan includes a fixed number of profiles:

| Plan     | Profiles  |
| -------- | --------- |
| Starter  | 1         |
| Growth   | 4         |
| Business | 10        |
| Custom   | Unlimited |

When you reach your plan's limit, upgrade to add more profiles.

## Create a profile

### In the dashboard

Go to **Connections → Connect account** and authorize each platform you want to
publish to. The profile is created for you — no `profile_id` to manage by hand.

### Via the API

Starting a connection creates the profile and returns a branded, time-limited
connect URL in one call:

```bash theme={null}
curl -X POST https://api.madiad.com/v1/connections/start \
  -H "Authorization: Bearer $MADIAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "friendly_name": "Acme Coffee" }'
```

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "friendly_name": "Acme Coffee",
  "access_url": "https://connect.madiad.com/o/abc123def456",
  "expires_in": "48h"
}
```

Use the returned `profile_id` (`prof_…`) whenever you publish a post.

### Skip the platform picker

`POST /v1/connections/start` returns a link to a page where the user chooses which platform to
connect. If you would rather render that choice in your own UI, ask for one platform and get the
provider's own authorization URL back:

```bash theme={null}
curl -X POST https://api.madiad.com/v1/connections/start-platform \
  -H "Authorization: Bearer $MADIAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z", "platform": "instagram" }'
```

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "platform": "instagram",
  "authorize_url": "https://www.instagram.com/oauth/authorize?...",
  "expires_in": 900
}
```

Like `/v1/connections/start`, it creates the profile when `profile_id` is omitted, and accepts an
optional `friendly_name`.

<Warning>
  The `authorize_url` carries a **single-use** state that expires in about 15 minutes
  (`expires_in`, in seconds). Redirect the user to it immediately — never mint one ahead of time
  or cache it, unlike the 48-hour link from `/v1/connections/start`.
</Warning>

Every platform can be started this way except **Bluesky**, which authenticates with an app
password rather than OAuth and returns `400 platform_not_startable` — send those users to the
shared connect link instead.

## List your profiles via API

To fetch every profile on the account — each with the platforms it has connected — call
`GET /v1/connections/status` and **omit `profile_id`**. There is no separate `/v1/profiles`
endpoint; this is how you list profiles:

```bash theme={null}
curl "https://api.madiad.com/v1/connections/status" \
  -H "Authorization: Bearer $MADIAD_API_KEY"
```

It returns a `profiles` array — each element has `profile_id`, `friendly_name`, `connected`, and
`accounts` (detailed under [Check which platforms are connected](#check-which-platforms-are-connected)
below). To see **how many profile slots remain** on your plan, call
[`GET /v1/usage`](/concepts/usage) — its `profiles` field returns `used` / `limit` / `remaining`.

## Connect social accounts

Each profile starts empty. Open its connect page in a browser and sign in to every
platform you want to publish to. MADIAD Hub stores the authorization, so you never
handle platform tokens yourself.

<Steps>
  <Step title="Open the connect page">
    In the dashboard, click **Connect account**. Via the API, send the user (or
    yourself) to the `access_url` returned by `/v1/connections/start`.
  </Step>

  <Step title="Authorize each platform">
    Sign in to Instagram, Facebook, TikTok, and so on. Connections persist until revoked.
  </Step>

  <Step title="Publish">
    Reference the profile by its `profile_id` in any post request.
  </Step>
</Steps>

## Supported platforms

A profile can connect any of: TikTok, Instagram, YouTube, Facebook, LinkedIn, X, Threads, Pinterest, Reddit, Bluesky, Google Business Profile, Telegram, and Discord.

A post only succeeds on platforms the target profile has actually connected. Listing a platform that isn't connected returns an error for that platform.

### Connect Telegram & Discord

TikTok, Instagram, and the other nine platforms connect by signing in on the connect page. **Telegram and Discord work differently** — they don't have an OAuth login, so instead you link your own bot or channel webhook:

<AccordionGroup>
  <Accordion title="Telegram — bring your own bot">
    1. Message **@BotFather** on Telegram and send `/newbot` to create a bot. Copy its **bot token**.
    2. Add the bot to your target channel or group as an **administrator** so it can post.
    3. In the dashboard, open **Connections → Telegram**, paste the **bot token** and the **chat ID** (`@yourchannel` or a numeric id like `-100123456789`), then connect.

    **Via the API**

    ```bash theme={null}
    curl -X POST https://api.madiad.com/v1/connections/telegram \
      -H "Authorization: Bearer $MADIAD_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
        "bot_token": "123456:ABC-DEF...",
        "chat_id": "@yourchannel",
        "name": "Announcements"
      }'
    ```

    Required fields: `profile_id`, `bot_token`, `chat_id`. `name` is an optional label. The bot must be an administrator of the target channel or group. `chat_id` is either `@channelname` or a numeric id like `-100123456789`. Returns 400 if any required field is missing.

    ```json theme={null}
    {
      "profiles": [
        {
          "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
          "friendly_name": "Acme Coffee",
          "connected": ["telegram"],
          "accounts": [
            { "platform": "telegram", "display_name": "Announcements", "username": null, "avatar": null }
          ]
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Discord — channel webhook">
    1. In Discord, go to **Server Settings → Integrations → Webhooks → New Webhook**, pick the channel you want to post to, and click **Copy Webhook URL**.
    2. In the dashboard, open **Connections → Discord**, paste the **webhook URL**, then connect.

    **Via the API**

    ```bash theme={null}
    curl -X POST https://api.madiad.com/v1/connections/discord \
      -H "Authorization: Bearer $MADIAD_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
        "webhook_url": "https://discord.com/api/webhooks/...",
        "name": "Marketing channel"
      }'
    ```

    Required fields: `profile_id`, `webhook_url`. `name` is an optional label. Returns 400 if either required field is missing.

    ```json theme={null}
    {
      "profiles": [
        {
          "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
          "friendly_name": "Acme Coffee",
          "connected": ["discord"],
          "accounts": [
            { "platform": "discord", "display_name": "Marketing channel", "username": null, "avatar": null }
          ]
        }
      ]
    }
    ```
  </Accordion>
</AccordionGroup>

<Note>
  Telegram and Discord are **not** covered by [Analytics](/concepts/analytics) — follower, reach, and engagement metrics aren't available for these platforms.
</Note>

<Note>
  **Uploads are unlimited on every paid plan.** FFmpeg minutes are still metered, and the allowance is **account-wide**: all your brands draw from one monthly pool, so a busy brand can borrow from a quieter one. The number of profiles is the cap to plan around. See [Usage](/concepts/usage).
</Note>

## Discover Page & board IDs

Some platforms require an ID you need to look up before posting. Use these endpoints to retrieve those IDs for a given profile.

### Facebook Pages

If a profile has more than one connected Facebook Page, pass `facebook_page_id` in your post request to choose which Page to publish to. List the available Pages with:

```bash theme={null}
curl "https://api.madiad.com/v1/connections/facebook/pages?profile_id=prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z" \
  -H "Authorization: Bearer $MADIAD_API_KEY"
```

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "pages": [
    { "id": "1029384756102938", "name": "Acme Coffee", "picture": "https://..." }
  ]
}
```

Each page has `id`, `name`, and `picture` (avatar URL, may be `null`). Pass the chosen `id` as `facebook_page_id` when posting. If the profile has exactly one Page it is selected automatically — this endpoint is only needed when there are several. Returns 400 if `profile_id` is missing, 404 if the profile is not yours.

### Pinterest boards

Pinterest requires a board ID on every pin. List the boards available to a profile with:

```bash theme={null}
curl "https://api.madiad.com/v1/connections/pinterest/boards?profile_id=prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z" \
  -H "Authorization: Bearer $MADIAD_API_KEY"
```

```json theme={null}
{
  "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
  "boards": [
    { "id": "987654321012345678", "name": "Seasonal Menu" }
  ]
}
```

Each board has `id` and `name`. Pass the chosen `id` as `pinterest_board_id` when posting — this field is always required for Pinterest. Returns 400 if `profile_id` is missing, 404 if the profile is not yours.

## Check which platforms are connected

To see which social platforms a profile currently has linked, call:

```bash theme={null}
curl "https://api.madiad.com/v1/connections/status?profile_id=prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z" \
  -H "Authorization: Bearer $MADIAD_API_KEY"
```

```json theme={null}
{
  "profiles": [
    {
      "profile_id": "prof_01HZX9F2K4M7N6QR8T0V2W4Y6Z",
      "friendly_name": "Acme Coffee",
      "connected": ["instagram", "facebook", "tiktok"],
      "accounts": [
        { "platform": "instagram", "display_name": "Acme Coffee", "username": "acmecoffee" }
      ]
    }
  ]
}
```

`connected` lists the platform slugs currently linked to the profile, and `accounts` carries the
connected account name/handle per platform. Omit `profile_id` to get the status of every profile on
your account. This is the on-demand way to check state; to be **notified** the moment a connection
changes, subscribe to the `connection.connected` / `connection.disconnected`
[webhooks](/concepts/webhooks).

## When to use multiple profiles

* **Agencies** — one profile per client.
* **Multi-brand teams** — one profile per brand.
* **Environments** — separate profiles for test vs production audiences.
