Caption & Social Post Endpoints
Write captions with AI and schedule clips to the social accounts the user connected in Klap (YouTube, TikTok, Instagram, LinkedIn, Facebook). Users connect their social accounts in Klap at https://klap.app/calendar; this API can’t connect new accounts.
Write Caption
Write a social media caption for a clip with AI. The caption is platform-agnostic: use the same text for every platform you post the clip to.
Endpoint: GET /projects/{clip_id}/caption
Request
GET /projects/{clip_id}/caption?tone=casual&prompt=Mention%20our%20free%20trial
Authorization: Bearer <access_token>Path Parameters
| Parameter | Type | Description |
|---|---|---|
clip_id | string | ID of the clip |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
tone | string | No | ”casual” | Tone of the caption, e.g. casual, professional, funny, inspirational, educational |
prompt | string | No | - | Extra instructions for the caption, up to 1000 characters |
Response
{
"caption": "Most startups don't die from competition. They die from building something nobody asked for 👀 #startups #founders"
}Writing a caption takes a few seconds. Returns 404 if the clip isn’t in the user’s account.
List Social Accounts
List the social accounts the user connected in Klap.
Endpoint: GET /integrations/accounts
Request
GET /integrations/accounts
Authorization: Bearer <access_token>Response
Returns an array of Social Account Objects:
[
{
"id": "UCx8Zk2mQv7LpR4tN9wB1cDe",
"provider": "youtube",
"name": "Startup Stories",
"username": "startupstories",
"profile_picture": "https://yt3.ggpht.com/abc123",
"settings": {},
"needs_reconnect": false
},
{
"id": "-000Ab12Cd34Ef56Gh78",
"provider": "tiktok",
"name": "Startup Stories",
"username": "startupstories",
"profile_picture": "https://p16-sign.tiktokcdn.com/abc123.jpeg",
"settings": {},
"needs_reconnect": true
}
]Notes
- This request can take up to about 5 seconds: Klap fetches each account’s current name and picture from the platform.
- An account with
needs_reconnect: truelost its connection to the platform. The user must reconnect it at https://klap.app/calendar before you can post to it.
Schedule Posts
Schedule a clip to one or more of the user’s social accounts. At the scheduled time, Klap exports the clip and publishes it. Users can review and change scheduled posts in Klap at https://klap.app/calendar.
Endpoint: POST /integrations/publications/batch
Request
POST /integrations/publications/batch
Authorization: Bearer <access_token>
Content-Type: application/json
{
"time_zone": "Europe/Paris",
"expected_publications": [],
"updates": [],
"delete_ids": [],
"creates": [
{
"id": "8d0c5f3e-6a1b-4c2d-9e7f-0a1b2c3d4e5f",
"project_id": "hT4kq9ZpW2xe",
"account_id": "UCx8Zk2mQv7LpR4tN9wB1cDe",
"provider": "youtube",
"scheduled_at": "2026-10-08T18:00:00+02:00",
"post_info": {
"title": "Why most startups fail",
"description": "Most startups don't die from competition. They die from building something nobody asked for.",
"tags": [],
"visibility": "public",
"category_id": "22"
}
},
{
"id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"project_id": "hT4kq9ZpW2xe",
"account_id": "-000Ab12Cd34Ef56Gh78",
"provider": "tiktok",
"scheduled_at": "2026-10-08T18:00:00+02:00",
"post_info": {
"title": "Most startups don't die from competition. They die from building something nobody asked for.",
"privacy_level": "PUBLIC_TO_EVERYONE",
"disable_duet": false,
"disable_stitch": false,
"disable_comment": false,
"video_cover_timestamp_ms": 0,
"brand_content_toggle": false,
"brand_organic_toggle": false,
"is_aigc": false
}
}
]
}Request Parameters
All five fields are required, and no other fields are accepted.
| Parameter | Type | Required | Description |
|---|---|---|---|
time_zone | string | Yes | The user’s IANA time zone (e.g., “UTC”, “Europe/Paris”) |
creates | array | Yes | Posts to schedule (up to 1000). See Post Object |
expected_publications | array | Yes | Send [] |
updates | array | Yes | Send [] |
delete_ids | array | Yes | Send [] |
Post Object
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | A new UUID (v4) that you generate for this post. Re-sending a post with the same id returns 409 publication_exists instead of posting twice, so retries are safe. |
project_id | string | Yes | ID of the clip to post (a clip id, despite the field’s name) |
account_id | string | Yes | id of the Social Account to post to |
provider | string | Yes | provider of that account: "youtube", "tiktok", "instagram", "linkedin" or "facebook" |
scheduled_at | string | Yes | When to publish, as an ISO 8601 date-time with a UTC offset (e.g., “2026-10-08T16:00:00Z” or “2026-10-08T18:00:00+02:00”). To post right away, use the current time plus 2 minutes. |
post_info | object | Yes | Platform-specific settings. See Post Info |
Post Info
Captions can be up to 2200 characters. Use the shape that matches the account’s provider:
YouTube
{
"title": "Why most startups fail",
"description": "<caption>",
"tags": [],
"visibility": "public",
"category_id": "22"
}title: Video title, up to 100 characters (for example the first 100 characters of the caption).visibility:"public","unlisted"or"private".category_id: YouTube video category ID ("22"is People & Blogs).
TikTok
{
"title": "<caption>",
"privacy_level": "PUBLIC_TO_EVERYONE",
"disable_duet": false,
"disable_stitch": false,
"disable_comment": false,
"video_cover_timestamp_ms": 0,
"brand_content_toggle": false,
"brand_organic_toggle": false,
"is_aigc": false
}privacy_level(required): Who can see the post:"PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR"or"SELF_ONLY". Let the user choose it; don’t assume one.
{
"caption": "<caption>",
"share_to_feed": true
}{
"caption": "<caption>"
}{
"share_commentary": "<caption>",
"media_title": "",
"media_description": "",
"visibility": "PUBLIC"
}visibility:"PUBLIC"or"CONNECTIONS".
If the user leaves the caption empty, you can write one with Write Caption.
Response
Returns the scheduled posts:
{
"publications": [
{
"id": "8d0c5f3e-6a1b-4c2d-9e7f-0a1b2c3d4e5f",
"project_id": "hT4kq9ZpW2xe",
"account_id": "UCx8Zk2mQv7LpR4tN9wB1cDe",
"provider": "youtube",
"scheduled_at": "2026-10-08T16:00:00+00:00",
"status": "scheduled",
"post_info": {
"title": "Why most startups fail",
"description": "Most startups don't die from competition. They die from building something nobody asked for.",
"tags": [],
"visibility": "public",
"category_id": "22"
},
"created_at": "2026-10-07T12:30:00.000000+00:00",
...
}
],
"deleted_ids": []
}- publications
(array): One entry per scheduled post, with itsid,project_id(the clip ID),account_id,provider,scheduled_at,post_infoandstatus("scheduled"). Entries can include other fields. - deleted_ids
(array): Always empty for requests that only create posts.
Notes
- All or nothing: The posts in one request are saved together. If one is refused, none are saved.
- One post per platform per clip: A clip can’t be posted to two accounts on the same platform, or scheduled again on a platform where it is already scheduled or published (
409 duplicate_post). - Retries: Re-send the same request with the same post
ids. If the first attempt went through, you get409 publication_exists. - Errors:
409 account_disconnected(an account needs reconnecting in Klap),409 youtube_capacity(YouTube’s daily posting capacity is reached for that day),402(plan or subscription),503(scheduling is busy: retry shortly with the sameids). See Errors.