# CRM · Social

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /sync/social-activities/profiles/{platform}

**Get connected social profiles**

`operationId: SocialActivityController_getProfiles`

Fetches the account details of the org's connected social accounts **live from each platform** — one call per platform, made now, not read from the activity store.

Name the platforms in the `platform` **query** parameter, comma-separated (`?platform=facebook,instagram`). Omit it and every platform in the org's social sync settings is fetched. For each platform the account asked about is the one saved for it in those settings, through the `default` integration config.

The result is an object keyed by platform; each value is what the platform returned for the account. A platform that fails — not in the sync settings, not connected, or refused by the platform — is left out, so a missing key means "could not fetch", not "no account".

#### Signature

```http
GET /sync/social-activities/profiles/{platform} (platform: string, platform?: string) -> Account details keyed by platform
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- `/profiles/instagram` returns every platform, not just Instagram — the path segment is not read. Use `?platform=instagram`.
- With no `platform` and no social sync settings saved for the org, the call fails with a 500 rather than returning `{}`.
- Each call goes to the platforms and counts against their rate limits.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platforms`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `platform` | path | string | yes | Optional segment, accepted but **ignored** — only the `platform` query parameter is read. `GET /sync/social-activities/profiles` reaches the same handler. |
| `platform` | query | string | — | Comma-separated platforms to fetch, from `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. Omit for every platform in the sync settings. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Account details keyed by platform |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /sync/social-activities/reply

**Reply to a social message or comment**

`operationId: SocialActivityController_replyToActivity`

Sends a reply to a customer on the platform they wrote on — a direct message stays a direct message, a comment reply goes on the comment — and records it in the conversation thread.

Name the message being answered by our own id (`activityId`, the `social_activity` record) and give the reply. The server works out everything else from that record: the platform, whether it is a message or a comment, the customer to send to, the page or account they wrote to (the reply is sent from it), and the comment and post ids. The reply is signed with the name of the signed-in user.

The reply is recorded as an outbound `social_activity` (`isAiGenerated: false`), so it shows in the thread and the platform's echo of the same message is not recorded twice.

#### Signature

```http
POST /sync/social-activities/reply (body) -> `success: true` and the page or account it was sent from; or `success: false` with the reason (e.g. the message was not found, no connected page, or the platform refused it).
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- A reply to a public comment is public. Move anything sensitive to a direct message first.
- Older callers may still send platform, to, pageId, commentId and postId themselves; with `activityId` those are worked out by the server.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/conversation-thread`
- `POST /sync/social-activities/ai-hold`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The message being answered, and the reply.

```json
{
  "activityId": "6ab60d3a4501ae658d446b10",
  "message": "It is back in stock now — thanks for waiting!"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | `success: true` and the page or account it was sent from; or `success: false` with the reason (e.g. the message was not found, no connected page, or the platform refused it). |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/ai-hold

**Get AI hold state for a customer**

`operationId: SocialActivityController_getAiHold`

Whether AI replies to one customer on one platform are paused, and the trail behind it — who paused or resumed, when and why — so an agent can tell whether the pause still makes sense.

#### Signature

```http
GET /sync/social-activities/ai-hold (platform?: string, customerId?: string) -> Current state and the trail
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- If the lookup itself fails the answer is "not paused" with an empty trail, not an error.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | HOLD_TARGET_REQUIRED | platform and customerId are required | `platform` or `customerId` is missing. | Send both — a hold is always for one customer on one platform. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /sync/social-activities/ai-hold`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `platform` | query | string | yes | The platform. |
| `customerId` | query | string | yes | Platform id of the customer. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Current state and the trail |
| `400` | platform and customerId are required — `platform` or `customerId` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

Example response:

```json
{
  "platform": "instagram",
  "customerId": "17841400000000000",
  "aiHold": true,
  "since": "2026-09-24T14:05:00.000Z",
  "by": "ada@example.com",
  "trail": [
    {
      "at": "2026-09-24T14:05:00.000Z",
      "hold": true,
      "by": "ada@example.com",
      "reason": "Complaint — needs a human"
    }
  ]
}
```

## POST /sync/social-activities/ai-hold

**Pause or resume AI replies to a customer**

`operationId: SocialActivityController_setAiHold`

Pauses or resumes AI replies to one customer on one platform, so a person can handle the conversation without an assistant answering over them.

It holds **replies only**. Assistants still run on the conversation — tickets, notes and notifications still happen — they just do not message the customer. A hold never expires: it stays until someone resumes it.

Every call adds a record to the conversation (`social_activity` with `standardActivityType: ai-hold`); nothing is updated or deleted, so the trail of who paused and resumed, and why, is kept. The current state is the latest record. The signed-in user's email is recorded as who did it.

#### Signature

```http
POST /sync/social-activities/ai-hold (body) -> The new state
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- A hold is per customer id per platform — it covers that customer on every one of our accounts on the platform. The same person on another platform has a different id and still gets AI replies.
- Pausing twice is harmless: it adds a second record and the state stays paused.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | HOLD_TARGET_REQUIRED | platform and customerId are required | `platform` or `customerId` is missing. | Send both — a hold is always for one customer on one platform. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/ai-hold`
- `POST /sync/social-activities/reply`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Whose replies to pause or resume.

```json
{
  "platform": "instagram",
  "customerId": "17841400000000000",
  "hold": true,
  "reason": "Complaint — needs a human"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The new state |
| `400` | platform and customerId are required — `platform` or `customerId` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/conversations

**List social conversations**

`operationId: SocialActivityController_getSocialConversations`

The social inbox: message, comment and mention activity grouped into conversations, the most recently active first. Grouping, the account filter, account names and paging are all done on the server.

A direct-message conversation is one customer on one of our accounts on one platform. Comments are also split by post, so one person commenting on two posts is two conversations.

Separate from `/crm/inbox`, which covers email, SMS and chat.

#### Signature

```http
GET /sync/social-activities/conversations (account?: string, page?: integer, pageSize?: integer) -> One page of conversations
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Pages are **0-based** here, unlike most list endpoints, and no `total` is returned — page on until `hasMore` is `false`.
- The account filter matches the account id on the record, the author or recipient id, or a post id that starts with `<account>_`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/conversation-thread`
- `GET /crm/inbox/conversations`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `account` | query | string | — | Only conversations on this connected account (page or account id). `all`, or leaving it out, means every account. |
| `page` | query | integer | — | Page number, **0-based**. |
| `pageSize` | query | integer | — | How many to return. Capped at 100; `0` or omitted gives 30. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | One page of conversations |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/conversation-thread

**Get a social conversation thread**

`operationId: SocialActivityController_getSocialThread`

The messages in one conversation, both sides, oldest first.

For a direct-message thread pass the customer's id: that matches what they sent us and what we sent them. For a comment thread pass `postId`: that returns the comments on the post, narrowed to one commenter when `customer` is given too. Instagram comment webhooks often carry no commenter id, so `postId` alone is the usual call there.

Only `message`, `comment` and `mention` rows are returned — the per-conversation summary row the sync writes, and AI-hold records, are left out. Reactions to a message are attached to it as `data.reactions`: the latest reaction from each person, with withdrawn reactions dropped.

#### Signature

```http
GET /sync/social-activities/conversation-thread (platform?: string, customer?: string, postId?: string, page?: integer, pageSize?: integer) -> One page of the thread, oldest first
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- With neither `customer` nor `postId` — or with them sent as the strings `null` or `undefined` — the result is an empty page, not an error.
- Pages are **0-based**.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /sync/social-activities/reply`
- `GET /sync/social-activities/conversations`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `platform` | query | string | yes | The platform. Not checked by the server, but always send it — without it nothing from a real platform matches. |
| `customer` | query | string | — | Platform id of the customer. Needed unless `postId` is given. |
| `postId` | query | string | — | The post, for a comment thread. |
| `page` | query | integer | — | Page number, **0-based**. |
| `pageSize` | query | integer | — | How many to return. Capped at 200; `0` or omitted gives 100. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | One page of the thread, oldest first |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/messages

**Get social messages**

`operationId: SocialActivityController_getAllMessages`

Direct messages across social platforms — both what customers sent and the replies we sent. These are **not** in the `/crm/inbox` store; social DMs live in `social_activity`.

Matches `standardActivityType` = `message`.

#### Signature

```http
GET /sync/social-activities/messages (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/comments

**Get social comments**

`operationId: SocialActivityController_getAllComments`

Comments on the org's social posts, across platforms — customers' comments and our replies to them.

Matches `standardActivityType` = `comment`.

#### Signature

```http
GET /sync/social-activities/comments (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/posts

**Get social posts**

`operationId: SocialActivityController_getAllPosts`

The org's own posts (`standardActivityType` `post` or `article`), reshaped into a single "unified feed" layout for display: one object with the posts under `feed.data`, each post with its counts, attachments and author in a fixed shape whatever platform it came from.

#### Signature

```http
GET /sync/social-activities/posts (startDate?: string, endDate?: string, platform?: string) -> The posts in unified feed form
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- At most 50 posts, most recently modified first; there is no paging and no total.
- Unlike the other feeds this does not return the stored records — only the unified shape.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/dashboard/analytics/{platform}`
- `GET /sync/social-activities/refresh/{platform}/{action}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The posts in unified feed form |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/engagement

**Get engagement activity**

`operationId: SocialActivityController_getAllEngagement`

Likes, reactions, shares and retweets recorded across platforms.

Matches `standardActivityType` of `like`, `reaction`, `share`, `retweet`.

#### Signature

```http
GET /sync/social-activities/engagement (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/leads

**Get social leads**

`operationId: SocialActivityController_getAllLeads`

Leads captured from social platforms, such as lead-ad form fills.

Matches `standardActivityType` = `lead`.

#### Signature

```http
GET /sync/social-activities/leads (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/ads

**Get social ad activity**

`operationId: SocialActivityController_getAllAds`

Ad records synced into the social store — distinct from the campaign management under `/crm/ads`.

Matches `standardActivityType` = `ad`.

#### Signature

```http
GET /sync/social-activities/ads (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/campaigns

**Get social campaign activity**

`operationId: SocialActivityController_getAllCampaigns`

Campaign records synced into the social store.

Matches `standardActivityType` = `campaign`.

#### Signature

```http
GET /sync/social-activities/campaigns (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/analytics

**Get social analytics records**

`operationId: SocialActivityController_getAllAnalytics`

The analytics, insight and metric records synced from the platforms, as stored — not aggregated.

Matches `standardActivityType` of `analytics`, `insight`, `metric`.

#### Signature

```http
GET /sync/social-activities/analytics (startDate?: string, endDate?: string, platform?: string) -> The first page of matching social activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |
| `platform` | query | string | — | Restrict to one platform (exact match), e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching social activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/platform/{platform}/type/{activityType}

**Get activity by platform and type**

`operationId: SocialActivityController_getActivitiesByPlatformAndType`

Activity of one `standardActivityType` on one platform — for combinations the fixed feeds do not cover, such as `story`, `reel`, `mention` or `follower`.

#### Signature

```http
GET /sync/social-activities/platform/{platform}/type/{activityType} (platform: string, activityType: string, startDate?: string, endDate?: string) -> The first page of matching activity
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first page comes back: at most 50 records, ordered by when the record was last modified (not by `timestamp`). There is no paging parameter — narrow with the date range or platform, and read `total` for how many matched.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /sync/social-activities/search`
- `GET /sync/social-activities/platforms`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `platform` | path | string | yes | The platform, e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |
| `activityType` | path | string | yes | A standard activity type — `GET /sync/social-activities/platforms` lists them all. Not validated: an unknown type returns an empty page. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The first page of matching activity |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/summary/platforms

**Get a per-platform summary**

`operationId: SocialActivityController_getActivitySummaryByPlatform`

How many activity records each platform has, broken down by activity type, busiest platform first.

#### Signature

```http
GET /sync/social-activities/summary/platforms (startDate?: string, endDate?: string) -> One row per platform
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Give either date alone and the other is filled in: `startDate` defaults to the beginning of time, `endDate` to now.
- If the summary cannot be computed the response is `[]`, not an error.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/dashboard/analytics`
- `GET /sync/social-activities/platforms`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | One row per platform |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/metrics/engagement

**Get engagement metrics**

`operationId: SocialActivityController_getEngagementMetrics`

Engagement counts per platform over a period: the number of like, comment, share and reaction records, and their sum. Counts of records, not rates. Most engaged platform first.

#### Signature

```http
GET /sync/social-activities/metrics/engagement (startDate?: string, endDate?: string) -> One row per platform
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Give either date alone and the other is filled in: `startDate` defaults to the beginning of time, `endDate` to now.
- Retweets are not counted in `totalShares`.
- If the metrics cannot be computed the response is `[]`, not an error.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/metrics/business`
- `GET /sync/social-activities/dashboard/analytics`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | One row per platform |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/metrics/business

**Get business metrics from social**

`operationId: SocialActivityController_getBusinessMetrics`

Ad, campaign and lead figures per platform over a period: how many of each record, and the spend, reach, impressions and clicks summed from them. Highest spend first.

#### Signature

```http
GET /sync/social-activities/metrics/business (startDate?: string, endDate?: string) -> One row per platform
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Give either date alone and the other is filled in: `startDate` defaults to the beginning of time, `endDate` to now.
- If the metrics cannot be computed the response is `[]`, not an error.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/metrics/engagement`
- `GET /sync/social-activities/dashboard/analytics`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | One row per platform |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /sync/social-activities/search

**Search social activity**

`operationId: SocialActivityController_searchActivitiesByContent`

Searches social activity by text, with optional platform, type and date filters.

With `searchTerm`, it runs a full-text search, best matches first. If that finds nothing it falls back to a case-insensitive "contains" match on the text — and that fallback **drops the other filters**, so it can return activity from other platforms, types or dates. Without `searchTerm`, only the filters apply, most recently modified first.

#### Signature

```http
POST /sync/social-activities/search (body) -> Matching activity — at most 50, no total
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Only the first 50 matches come back and there is no paging.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/platform/{platform}/type/{activityType}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

What to search for. Every field is optional; an empty body returns the most recently modified activity.

```json
{
  "searchTerm": "refund",
  "platforms": [
    "instagram"
  ],
  "activityTypes": [
    "comment"
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Matching activity — at most 50, no total |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/author/{authorId}

**Get activity by author**

`operationId: SocialActivityController_getActivitiesByAuthor`

Activity one person authored — their messages, comments and engagement — matched on their platform id, or also on a name when `authorName` is given. Replies we sent them are not included (they are authored by us).

**The response is not a plain list of activity.** It is a one-element array whose only item is the page object `{ data, total, page, pageSize, hasNext, … }`, with the activity in `[0].data` (first 50, most recently modified first). And because the `platform`, `startDate` and `endDate` filters are applied to that page object rather than to the activity, sending any of them returns `[]`.

#### Signature

```http
GET /sync/social-activities/author/{authorId} (authorId: string, authorName?: string, platform?: string, startDate?: string, endDate?: string) -> A one-element array holding the page of the author's activity; `[]` when a filter is sent
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Author ids are per platform — the same person has a different id on each.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/conversation-thread`
- `POST /sync/social-activities/search`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `authorId` | path | string | yes | Platform id of the author. |
| `authorName` | query | string | — | Also match activity whose author name contains this, case-insensitively. Read as a regular expression. |
| `platform` | query | string | — | Meant to restrict to one platform — currently empties the result instead (see above). |
| `startDate` | query | string | — | Meant to bound the period — currently empties the result instead (see above). |
| `endDate` | query | string | — | Meant to bound the period — currently empties the result instead (see above). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | A one-element array holding the page of the author's activity; `[]` when a filter is sent |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/platforms

**List platforms with activity**

`operationId: SocialActivityController_getAvailablePlatforms`

The platforms that have activity in the store, with a count per activity type, plus the full list of standard activity types.

Built from stored activity over all time, not from connections: a platform connected but not yet synced is missing, and one disconnected keeps appearing while its records remain.

#### Signature

```http
GET /sync/social-activities/platforms () -> Platforms and activity types
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/summary/platforms`
- `GET /sync/social-activities/profiles/{platform}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Platforms and activity types |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/dashboard/analytics

**Get social dashboard analytics**

`operationId: SocialActivityController_getDashboardAnalytics`

The per-platform summary, engagement metrics and business metrics in one call, over the same period — what a social dashboard needs.

#### Signature

```http
GET /sync/social-activities/dashboard/analytics (startDate?: string, endDate?: string) -> Summary, engagement and business figures
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Give either date alone and the other is filled in: `startDate` defaults to the beginning of time, `endDate` to now.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/dashboard/analytics/{platform}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Summary, engagement and business figures |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/dashboard/analytics/{platform}

**Get dashboard analytics for one platform**

`operationId: SocialActivityController_getPlatformDashboardAnalytics`

Post performance on one platform: totals of likes, comments, shares, views and reach, and the ten most recently modified posts.

The figures come from the counts stored on the post records themselves, and only from the **50 most recently modified** posts (`post` or `article`) in the period — on a busy account the totals cover those 50, not every post.

#### Signature

```http
GET /sync/social-activities/dashboard/analytics/{platform} (platform: string, startDate?: string, endDate?: string) -> Post totals and recent posts
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Give either date alone and the other is filled in: `startDate` defaults to the beginning of time, `endDate` to now.
- An unknown platform returns zero totals and no posts, not an error.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/dashboard/analytics`
- `GET /sync/social-activities/posts`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `platform` | path | string | yes | The platform, e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |
| `startDate` | query | string | — | Start of the period, as a date or ISO timestamp. Compared with the activity's `timestamp`. A value that is not a date matches nothing. |
| `endDate` | query | string | — | End of the period, inclusive of that exact instant. A bare date is midnight UTC at the **start** of that day, so the day itself is left out — pass the next day, or a full timestamp, to include it. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Post totals and recent posts |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /sync/social-activities/refresh/{platform}/{action}

**Refresh social data from a platform**

`operationId: SocialActivityController_refreshPlatformData`

Calls the platform now for one kind of data, saves what comes back into the social store, and returns it in the unified feed shape.

The platform must be in the org's social sync settings (Instagram and WhatsApp can use the Facebook entry). The integration used is `configId`, else the one named in those settings, else `default`, and it must hold valid tokens. The account comes from `accountId`, else the settings (for Facebook and Instagram a saved `pageId/instagramId` pair is split into `pageId` and `instagramId`). **Every** query parameter is passed through to the platform call, so extra ones such as `limit` reach it; `feed` and `posts` default `limit` to 25.

`action` picks the call: `feed` and `posts` → getFeed, `insights` and `analytics` → getInsights, `comments`, `messages`, `notifications`, `reactions`, `engagement`, `leads`, `ads`, `campaigns`, `followers`, `profile`; any other value calls `get<Action>` on the provider.

Each returned item that has an `id` or `name` is saved as a `social_activity` with `platform`, `sourceType` (`<platform>-<action>`), `sourceId` (the item's id) and `timestamp` (the time of the refresh, unless the item has its own) added to the platform's fields. An item whose `sourceId` is already stored is skipped — the stored copy is not updated.

#### Signature

```http
GET /sync/social-activities/refresh/{platform}/{action} (platform: string, action: string, configId?: string, accountId?: string, limit?: integer) -> Always HTTP 200 — check `success`. On success, the saved items in unified feed form; on failure, the reason.
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- A write on `GET`, and a live platform call that counts against its rate limits — do not put it behind a prefetchable link.
- Failures (no sync settings, no configuration for the platform, integration missing or without valid tokens, the platform refusing the call) come back as `success: false`, not as an HTTP error.
- Whatever the action, the response is shaped as a feed of posts — messages or insights are squeezed into the post layout.
- Items saved here carry no `standardActivityType`, so the typed feeds (`/messages`, `/comments`, `/posts`, …) do not show them; they appear in `/platforms`, `/summary/platforms` and search.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /sync/social-activities/posts`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `platform` | path | string | yes | The platform, e.g. `facebook`, `instagram`, `whatsapp`, `tiktok`, `twitter`, `linkedin`, `pinterest`. |
| `action` | path | string | yes | What to fetch: `feed`, `posts`, `insights`, `analytics`, `comments`, `messages`, `notifications`, `reactions`, `engagement`, `leads`, `ads`, `campaigns`, `followers`, `profile`, or another provider `get…` operation. |
| `configId` | query | string | — | Integration config to use. Defaults to the one in the sync settings, then `default`. |
| `accountId` | query | string | — | Account to fetch for, passed to the platform as `accountId`. Defaults to the account in the sync settings. |
| `limit` | query | integer | — | Passed to the platform, like any other query parameter. Defaults to 25 for `feed` and `posts`. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Always HTTP 200 — check `success`. On success, the saved items in unified feed form; on failure, the reason. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

Example response:

```json
{
  "success": false,
  "platform": "tiktok",
  "action": "posts",
  "error": "No sync configuration found for platform: tiktok",
  "timestamp": 1788000000000
}
```

