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

# Data Structures

> Canonical data models for accounts, capabilities, posts, slideshows, analytics, and more returned by the Genviral social media API.

> Canonical objects returned by the Genviral Partner API. These structures are designed for easy consumption by OpenClaw agents, AI automation pipelines, and custom integrations.

## Partner API Key

Represents the credential you create in **API Keys**. Every key is single-scope:
either `workspace` or `personal`.

| Field | Type | Description |
| - | - | - |
| `public_id` | `string` | Short identifier (e.g., `gva_live_2ff93c`). |
| `secret_suffix` | `string` | Last four characters of the secret portion, useful for audits. |
| `scope` | `string` | `workspace` or `personal`. |
| `workspace_id` | `string \| null` | Present for workspace keys. |
| `owner_user_id` | `string \| null` | Present for personal keys. |
| `is_active` | `boolean` | Key active state. |
| `created_at` | `string (ISO 8601)` | Timestamp when the key was issued. |
| `last_used_at` | `string \| null` | Updated whenever the key is used. |
| `revoked_at` | `string \| null` | Timestamp when key was revoked. |

```json theme={null}
{
  "public_id": "gva_live_2ff93c",
  "secret_suffix": "b4d5",
  "scope": "personal",
  "workspace_id": null,
  "owner_user_id": "5ec8f2fd-8d0a-4c68-b05d-9a8a85aa5d5d",
  "is_active": true,
  "created_at": "2026-02-13T15:32:11.402Z",
  "last_used_at": "2026-02-13T18:14:03.009Z",
  "revoked_at": null
}
```

## Social Account (BYO + Hosted)

Returned by `GET /accounts` and referenced when scheduling posts. Account IDs are UUIDs.

| Field | Type | Description |
| - | - | - |
| `id` | `string (UUID)` | Scope-constrained account identifier. |
| `platform` | `string` | `tiktok`, `instagram`, etc. |
| `type` | `string` | `byo` (user-connected) or `hosted` (Genviral-managed). |
| `username` | `string` | Handle shown on the platform. |
| `display_name` | `string` | Friendly label surfaced in the dashboard. |
| `status` | `string` | `active`, `paused`, `revoked`, etc. |
| `workspace_id` | `string \| null` | Workspace owner when account is workspace-scoped; `null` in personal scope. |
| `capabilities` | `object` | Per-account supported content kinds, caption/media limits, unsupported reasons, and provider settings JSON Schema. |
| `posting_times` | `string[]` | Times of day set for the account in the Social Hub, as wall-clock `HH:MM`, unique and earliest first. |

```json theme={null}
{
  "id": "0f4f54d4-8cce-4fb7-8c7b-befbcb8af812",
  "platform": "tiktok",
  "type": "hosted",
  "username": "ugc_trends_42",
  "display_name": "Hosted Trends 42",
  "status": "active",
  "workspace_id": "4cb5d3fd-8c8f-4ed7-a17c-4ffb52c7e6ac",
  "capabilities": {
    "supported_content_kinds": ["single_image", "multi_image", "single_video"],
    "caption_limit": 500,
    "media_limits": {
      "max_images": 35,
      "max_videos": 1
    },
    "unsupported_content_kind_reasons": {
      "text_only": "Text-only posts are only available for connected BYO accounts; hosted accounts require media."
    },
    "settings_schema": {
      "type": "object",
      "additionalProperties": false,
      "properties": {}
    }
  },
  "posting_times": ["09:00", "17:30"]
}
```

### Account Capabilities

Returned under `account.capabilities` by `GET /accounts`.

| Field | Type | Description |
| - | - | - |
| `supported_content_kinds` | `string[]` | Content kinds this account supports through Genviral: `text_only`, `single_image`, `multi_image`, `single_video`. |
| `caption_limit` | `number` | Account-aware caption limit. |
| `media_limits.max_images` | `number` | Maximum image count accepted for the account/platform. |
| `media_limits.max_videos` | `number` | Maximum video count accepted for the account/platform. |
| `media_limits.max_video_seconds` | `number` | Optional max video duration when the platform/account policy needs it. |
| `unsupported_content_kind_reasons` | `object` | Reason strings keyed by unsupported content kind. |
| `settings_schema` | `object` | JSON Schema for public provider settings: top-level `tiktok`/`pinterest`, otherwise `settings.<provider>`. |

## Post

Created via `POST /posts`, retrieved via `GET /posts` and `GET /posts/{id}`.

| Field | Type | Description |
| - | - | - |
| `id` | `string (UUID)` | Unique post ID. |
| `status` | `string` | `draft`, `pending`, `scheduled`, `retry`, `posted`, `failed`, `partial`, `canceled`, `deleted`, `expired`. |
| `caption` | `string` | Cross-platform caption. |
| `scheduled_at` | `string \| null` | Target publish timestamp. |
| `created_at` | `string` | ISO timestamp when the post was created. |
| `accounts` | `object` | Summary + per-account states (see below). |
| `media` | `object \| null` | Mirrors the create/update payload (`type` + `url`/`urls`), or `null` for text-only posts. |
| `music_url` | `string \| null` | TikTok post URL applied to the TikTok audio track. Not supported for Instagram targets. |
| `tiktok` | `object \| null` | Optional TikTok publish settings (only for TikTok BYO-targeted posts). |
| `pinterest` | `object \| null` | Optional Pinterest settings (`board_id`, `link`, `title`, `tags`). |

```json theme={null}
{
  "id": "11111111-1111-1111-1111-111111111111",
  "caption": "Holiday drops start Monday!",
  "status": "scheduled",
  "scheduled_at": "2025-02-01T15:00:00Z",
  "created_at": "2025-01-20T12:05:11.205Z",
  "tiktok": {
    "post_mode": "MEDIA_UPLOAD",
    "privacy_level": "PUBLIC_TO_EVERYONE"
  }
}
```

Top-level `tiktok` and `pinterest` settings are v1 convenience aliases.
New multi-platform clients should prefer canonical provider settings under
`settings.<provider>` in create/update requests.

### Media

Returned as submitted to `POST /posts` and `PATCH /posts/{id}`, or `null` for
text-only posts:

| Field | Type | Description |
| - | - | - |
| `type` | `string` | `video` or `slideshow`. Determines which property appears below. |
| `url` | `string` | Present when `type="video"`. Points to the ingested/validated clip. |
| `urls` | `string[]` | Present when `type="slideshow"`. Ordered list of image URLs (1–35 entries). |

When BYO accounts are present, Genviral re-hosts the assets behind the scenes so
these URLs point to first-party Cloudflare R2 buckets. Hosted-only posts reuse
the URLs you provided once reachability is confirmed.

### TikTok Settings

Optional settings persisted from `POST /posts` / `PATCH /posts/{id}` under the
`tiktok` field. These apply only when all targeted accounts are TikTok BYO
accounts.

| Field | Type | Description |
| - | - | - |
| `title` | `string` | Optional TikTok title override. Video posts: max 2,200 UTF-16 runes. Photo/slideshow posts: max 90 UTF-16 runes. |
| `description` | `string` | Optional TikTok description override. Photo/slideshow posts: max 4,000 UTF-16 runes. For video posts, Genviral keeps this field for compatibility and can use it as a fallback source when deriving the TikTok title if `title` is blank. |
| `post_mode` | `string` | `DIRECT_POST` or `MEDIA_UPLOAD` (TikTok inbox/drafts). |
| `privacy_level` | `string` | TikTok privacy level (`PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS`, `FOLLOWER_OF_CREATOR`, `SELF_ONLY`). |
| `disable_comment` | `boolean` | Optional comment toggle. |
| `disable_duet` | `boolean` | Optional duet toggle (video posts). |
| `disable_stitch` | `boolean` | Optional stitch toggle (video posts). |
| `video_cover_timestamp_ms` | `integer` | Optional video cover frame offset in milliseconds (`DIRECT_POST` video only). |
| `music_usage_confirmation` | `boolean` | Confirms the user has accepted TikTok's music-usage terms for this post. Preferred Partner API field. |
| `user_consent` | `boolean` | Legacy alias for `music_usage_confirmation`. |
| `is_commercial` | `boolean` | Optional commercial content flag. |
| `is_your_brand` | `boolean` | Optional own-brand flag. |
| `is_branded_content` | `boolean` | Optional third-party branded-content flag. |
| `auto_add_music` | `boolean` | Photo/`DIRECT_POST` only. Omitted defaults to `true` (TikTok auto-picks a soundtrack). `false` still publishes silent. Videos and hosted TikTok ignore this field. |

### Pinterest Settings

Optional settings persisted from `POST /posts` / `PATCH /posts/{id}` under the
`pinterest` field. These apply only when at least one targeted account is
Pinterest.

| Field | Type | Description |
| - | - | - |
| `board_id` | `string` | Optional Pinterest board ID (max 128 chars). |
| `title` | `string` | Optional pin title override (max 100 chars). |
| `link` | `string` | Optional destination URL attached to the pin (max 2,048 chars). |
| `tags` | `string[]` | Optional topic tags (up to 30, spaces allowed). Genviral appends these to the final Pinterest description, which still must fit Pinterest's 800-character description ceiling. |

### Account States

Each post stores a normalized state for every targeted account (from `social_post_accounts`):

| Field | Type | Description |
| - | - | - |
| `account_id` | `string` | ID from `GET /accounts`. |
| `status` | `string` | One of `draft`, `pending`, `scheduled`, `retry`, `posted`, `failed`, `partial`, `canceled`, `deleted`, `expired`. |
| `published_at` | `string \| null` | Timestamp of successful publish. |
| `published_url` | `string \| null` | Platform URL when the provider shares one (hosted creators). |
| `error_message` | `string \| null` | Last error returned by the platform. |
| `last_attempted_at` | `string \| null` | When the scheduler last touched this account. |

```json theme={null}
{
  "accounts": {
    "total": 2,
    "states": [
      {
        "account_id": "0f4f54d4-8cce-4fb7-8c7b-befbcb8af812",
        "status": "scheduled",
        "published_at": null,
        "published_url": null,
        "error_message": null,
        "last_attempted_at": null
      },
      {
        "account_id": "6b0c8c9c-55ac-4fcb-85ec-70b5a8b0d089",
        "status": "scheduled",
        "published_at": null,
        "published_url": null,
        "error_message": null,
        "last_attempted_at": null
      }
    ]
  }
}
```

## Folder

Returned by folder endpoints under `/api/partner/v1/folders*`.

| Field | Type | Description |
| - | - | - |
| `id` | `string (UUID)` | Folder ID. |
| `name` | `string` | Folder display name. |
| `media_type` | `string` | `ai_image`, `ai_video`, `upload`, or `slideshow`. |
| `parent_folder_id` | `string \| null` | Parent folder ID (`null` for root). |
| `path` | `string` | Materialized folder path. |
| `file_count` | `number` | Count of direct items in the folder. |
| `subfolder_count` | `number` | Count of direct child folders. |
| `preview_files` | `array` | Up to 4 preview items (`id`, `url`, `content_type`). |
| `created_at` | `string` | Creation timestamp. |
| `updated_at` | `string` | Last update timestamp. |

```json theme={null}
{
  "id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
  "name": "March Campaign",
  "media_type": "upload",
  "parent_folder_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
  "path": "/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
  "file_count": 8,
  "subfolder_count": 1,
  "preview_files": [
    {
      "id": "11111111-1111-1111-1111-111111111111",
      "url": "https://cdn.vireel.io/partner-api/workspaces/workspace_123/asset-1.jpg",
      "content_type": "image/jpeg"
    }
  ],
  "created_at": "2026-03-01T09:00:00Z",
  "updated_at": "2026-03-01T09:10:00Z"
}
```

## Stats Snapshot

Analytics endpoints (and UI exports) reuse the same structures outlined in `other/docs/product/integrations/ugcinc/data-structures/account-stat.md` and `post-stat.md`.

| Field | Type | Description |
| - | - | - |
| `account_stats.id` | `string` | Unique stat row. |
| `account_stats.account_id` | `string` | Links back to the account in current key scope. |
| `account_stats.followers` | `number \| null` | Followers at the time of capture. |
| `account_stats.views` | `number \| null` | Aggregated views across all posts. |
| `post_stats.id` | `string` | Unique per-post stat row. |
| `post_stats.post_id` | `string` | Links to the Genviral post. |
| `post_stats.views` | `number \| null` | Views for the specific post. |
| `post_stats.likes` | `number \| null` | Likes for the specific post. |
| `created_at` | `string` | Snapshot timestamp. |

```json theme={null}
{
  "account_stats": {
    "id": "acc_stat_1",
    "account_id": "6b0c8c9c-55ac-4fcb-85ec-70b5a8b0d089",
    "followers": 15420,
    "views": 1250000,
    "likes": 89500,
    "created_at": "2025-01-19T10:00:00Z"
  },
  "post_stats": {
    "id": "post_stat_1",
    "post_id": "11111111-1111-1111-1111-111111111111",
    "views": 48200,
    "likes": 3200,
    "created_at": "2025-01-21T04:00:00Z"
  }
}
```

## Analytics Summary

Returned by `GET /api/partner/v1/analytics/summary`.

| Field | Type | Description |
| - | - | - |
| `range.start` | `string` | Start date (`YYYY-MM-DD`) of selected range. |
| `range.end` | `string` | End date (`YYYY-MM-DD`) of selected range. |
| `filters.platforms` | `string[]` | Applied platform filters. |
| `filters.accountIds` | `string[]` | Applied analytics target ID filters. |
| `kpis.<metric>.value` | `number` | Current-period value for metric. |
| `kpis.<metric>.delta` | `number` | Difference from previous equivalent period. |
| `interactionSeries[]` | `object[]` | Daily interactions (`views`, `likes`, `comments`, `shares`). |
| `engagementSeries[]` | `object[]` | Daily engagement-rate values. |
| `postingHeatmap[]` | `object[]` | Daily post counts for heatmap rendering. |
| `postingStreak` | `number` | Consecutive posting-day streak ending at selected `range.end`. |
| `contentMix[]` | `object[]` | Post distribution by platform (`platform`, `posts`, `percentage`). |

## Analytics Target

Returned by `GET /api/partner/v1/analytics/targets` and target-management
endpoints.

| Field | Type | Description |
| - | - | - |
| `id` | `string (UUID)` | Canonical analytics target identifier used across analytics endpoints. |
| `target_id` | `string (UUID)` | Legacy alias currently included in list rows for backward compatibility. |
| `platform` | `string` | `tiktok`, `instagram`, or `youtube`. |
| `identifier` | `string` | Original account handle/input. |
| `normalized_identifier` | `string` | Normalized identifier used for dedupe. |
| `display_name` | `string \| null` | Optional display label. |
| `last_refreshed_at` | `string \| null` | Last successful refresh timestamp. |
| `last_snapshot_totals` | `object \| null` | Latest aggregate totals from snapshot. |
| `last_refresh_status` | `string \| null` | Status from latest refresh row. |
| `last_refresh_error` | `string \| null` | Latest refresh error text when failed. |
| `free_refresh_available` | `boolean` | Whether free daily refresh is currently available. |

## Analytics Refresh

Returned by `POST /api/partner/v1/analytics/targets/{id}/refresh` and
`GET /api/partner/v1/analytics/refreshes/{id}`.

| Field | Type | Description |
| - | - | - |
| `id` | `string (UUID)` | Refresh ID. |
| `target_id` | `string (UUID)` | Target this refresh belongs to. |
| `workspace_id` | `string \| null` | Workspace scope for billing/context. |
| `status` | `string` | `pending`, `processing`, `completed`, or `failed`. |
| `credits_used` | `number` | Credits consumed for this refresh (0 if free). |
| `free_refresh_used` | `boolean` | Whether free refresh window was used. |
| `started_at` | `string` | Start timestamp. |
| `completed_at` | `string \| null` | Completion timestamp when done. |
| `error` | `string \| null` | Failure reason when status is `failed`. |

<Tip>
  When available, `GET /api/partner/v1/analytics/summary/posts` returns both `analyticsId`,
  `genviralPostId`, and `externalId`. Use `genviralPostId` or `externalId` as the preferred
  correlation fields for mapping analytics rows back to the originating Partner API post.
  `analyticsId` and legacy `id` are the analytics-dataset row ID, not the post-creation ID.
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.