# Best time to post

Find the hours of the week when your own posts get the most engagement, and how often to post on each platform, from your publishing history.

`GET /v1/analytics/best-time` looks at the posts an account (or a whole profile) already published and tells you which hours of the week earned the most engagement. It is your own history, not an industry average, so it gets better as you post more.

## Get the best slots

```bash cURL
curl "https://api.pozy.ai/v1/analytics/best-time?accountId=6650c1e2a3b4c5d6e7f80a22" \
  -H "Authorization: Bearer $POZY_API_KEY"
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/analytics/best-time?accountId=6650c1e2a3b4c5d6e7f80a22", {
  headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);

const top = [...data.slots]
  .filter((s) => s.post_count >= 3)
  .sort((a, b) => b.avg_engagement - a.avg_engagement)
  .slice(0, 5);
console.log(top);
```
```python Python
import os
import requests

resp = requests.get(
    "https://api.pozy.ai/v1/analytics/best-time",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    params={"accountId": "6650c1e2a3b4c5d6e7f80a22"},
    timeout=30,
)
slots = [s for s in resp.json()["slots"] if s["post_count"] >= 3]
print(sorted(slots, key=lambda s: s["avg_engagement"], reverse=True)[:5])
```

```json
{
  "slots": [
    { "day_of_week": 1, "hour": 17, "avg_engagement": 412.5, "post_count": 8 },
    { "day_of_week": 3, "hour": 12, "avg_engagement": 388.0, "post_count": 6 },
    { "day_of_week": 6, "hour": 9, "avg_engagement": 120.3, "post_count": 2 }
  ]
}
```

## How to read a slot

| Field | Meaning |
| --- | --- |
| `day_of_week` | `0` is Monday, `6` is Sunday |
| `hour` | Hour of the day in **UTC**, 0 to 23 |
| `avg_engagement` | Average likes, comments, shares and saves of the posts published in that slot |
| `post_count` | How many posts fell in that slot |

Pozy groups every published post by the weekday and UTC hour it went out, then averages engagement per group. Slots with no posts are left out, so a sparse history returns few slots.

> **Trust slots with enough posts:**
> 
> A slot with one viral post looks great and means little. Filter on `post_count` (3 or more is a reasonable floor) before you rank. Until an account has a few weeks of history, combine this with [online followers](#when-followers-are-online) on Instagram.

### Filters

| Parameter | Use |
| --- | --- |
| `accountId` | One account. Usually what you want, since audiences differ per account |
| `profileId` | Every account in a customer profile |
| `platform` | One platform across the profile |
| `source` | `all` (default), `pozy` for posts published through Pozy, `external` for posts made on the platform |

## Convert to the account's timezone

Slots are in UTC. Convert them before you show them or schedule against them:

```ts
function slotToLocal(slot: { day_of_week: number; hour: number }, timeZone: string) {
  // Pick any Monday at 00:00 UTC, then move to the slot.
  const base = Date.UTC(2026, 9, 26); // Monday 26 October 2026
  const at = new Date(base + (slot.day_of_week * 24 + slot.hour) * 3_600_000);
  return new Intl.DateTimeFormat("en-GB", { timeZone, weekday: "long", hour: "2-digit", minute: "2-digit" }).format(at);
}

slotToLocal({ day_of_week: 1, hour: 17 }, "America/New_York"); // "Tuesday 13:00"
```

## Schedule into the best slots

Two common patterns:

- **Pick a time per post.** Take the best slot after now and pass it as `scheduledFor` when you [create the post](https://pozy.ai/docs/publishing). Keep the timezone explicit, as described in [Scheduling](https://pozy.ai/docs/publishing/scheduling).
- **Feed a queue.** Turn the top slots into a recurring queue schedule, so every post you add goes out at one of them. See [Queues](https://pozy.ai/docs/publishing/queues).

## How often to post

[`GET /v1/analytics/posting-frequency`](https://pozy.ai/docs/api/getPostingFrequency) answers a different question: does posting more often help or hurt? It groups past weeks by how many posts went out and reports the engagement of each group, per platform.

| Field | Meaning |
| --- | --- |
| `platform` | The platform the row describes |
| `posts_per_week` | A posting cadence that occurred in your history |
| `avg_engagement_rate` | Average engagement rate (0 to 100) across the weeks with that cadence |
| `avg_engagement` | Average raw engagement (likes, comments, shares and saves) |
| `weeks_count` | How many calendar weeks had that cadence |

Look for the cadence where the engagement rate stops rising. As with slots, ignore rows backed by one or two weeks.

## When followers are online

For Instagram accounts with at least 100 followers, [`GET /v1/analytics/instagram/online-followers`](https://pozy.ai/docs/api/getInstagramOnlineFollowers) returns how many followers were online in each hour of each of the last 30 days. It works before you have a posting history. Instagram does not document the timezone of its hour keys, so compare it with your own best-time slots before relying on the exact hour.

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/analytics/best-time`](https://pozy.ai/docs/api/getBestTimeToPost) | Get best times to post |
| [`GET /v1/analytics/posting-frequency`](https://pozy.ai/docs/api/getPostingFrequency) | Get frequency vs engagement |
| [`GET /v1/analytics/instagram/online-followers`](https://pozy.ai/docs/api/getInstagramOnlineFollowers) | Get Instagram online followers |
