curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/social-calendar/posts \
--header 'Content-Type: application/json' \
--header 'api_key: <api-key>' \
--data @- <<EOF
{
"platform": "linkedin",
"title": "Ship a CRM in an afternoon",
"body": "We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.",
"scheduled_at": "2026-09-15T14:00:00Z",
"scheduled_timezone": "Asia/Jerusalem",
"hook": "pain_point",
"best_time_reason": "Weekday afternoons get the most engagement for this audience.",
"hashtags": [
"buildinpublic",
"crm"
],
"image_url": "https://cdn.example.com/posts/crm-launch.png",
"image_prompt": "A freelancer closing a deal on a laptop, warm morning light"
}
EOFimport requests
url = "https://app.base44.com/api/apps/{app_id}/social-calendar/posts"
payload = {
"platform": "linkedin",
"title": "Ship a CRM in an afternoon",
"body": "We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.",
"scheduled_at": "2026-09-15T14:00:00Z",
"scheduled_timezone": "Asia/Jerusalem",
"hook": "pain_point",
"best_time_reason": "Weekday afternoons get the most engagement for this audience.",
"hashtags": ["buildinpublic", "crm"],
"image_url": "https://cdn.example.com/posts/crm-launch.png",
"image_prompt": "A freelancer closing a deal on a laptop, warm morning light"
}
headers = {
"api_key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_key: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
platform: 'linkedin',
title: 'Ship a CRM in an afternoon',
body: JSON.stringify('We replaced our lead spreadsheet with an app we built in an afternoon. Here\'s what changed.'),
scheduled_at: '2026-09-15T14:00:00Z',
scheduled_timezone: 'Asia/Jerusalem',
hook: 'pain_point',
best_time_reason: 'Weekday afternoons get the most engagement for this audience.',
hashtags: ['buildinpublic', 'crm'],
image_url: 'https://cdn.example.com/posts/crm-launch.png',
image_prompt: 'A freelancer closing a deal on a laptop, warm morning light'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/social-calendar/posts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/social-calendar/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'platform' => 'linkedin',
'title' => 'Ship a CRM in an afternoon',
'body' => 'We replaced our lead spreadsheet with an app we built in an afternoon. Here\'s what changed.',
'scheduled_at' => '2026-09-15T14:00:00Z',
'scheduled_timezone' => 'Asia/Jerusalem',
'hook' => 'pain_point',
'best_time_reason' => 'Weekday afternoons get the most engagement for this audience.',
'hashtags' => [
'buildinpublic',
'crm'
],
'image_url' => 'https://cdn.example.com/posts/crm-launch.png',
'image_prompt' => 'A freelancer closing a deal on a laptop, warm morning light'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"api_key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/social-calendar/posts"
payload := strings.NewReader("{\n \"platform\": \"linkedin\",\n \"title\": \"Ship a CRM in an afternoon\",\n \"body\": \"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.\",\n \"scheduled_at\": \"2026-09-15T14:00:00Z\",\n \"scheduled_timezone\": \"Asia/Jerusalem\",\n \"hook\": \"pain_point\",\n \"best_time_reason\": \"Weekday afternoons get the most engagement for this audience.\",\n \"hashtags\": [\n \"buildinpublic\",\n \"crm\"\n ],\n \"image_url\": \"https://cdn.example.com/posts/crm-launch.png\",\n \"image_prompt\": \"A freelancer closing a deal on a laptop, warm morning light\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.base44.com/api/apps/{app_id}/social-calendar/posts")
.header("api_key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"platform\": \"linkedin\",\n \"title\": \"Ship a CRM in an afternoon\",\n \"body\": \"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.\",\n \"scheduled_at\": \"2026-09-15T14:00:00Z\",\n \"scheduled_timezone\": \"Asia/Jerusalem\",\n \"hook\": \"pain_point\",\n \"best_time_reason\": \"Weekday afternoons get the most engagement for this audience.\",\n \"hashtags\": [\n \"buildinpublic\",\n \"crm\"\n ],\n \"image_url\": \"https://cdn.example.com/posts/crm-launch.png\",\n \"image_prompt\": \"A freelancer closing a deal on a laptop, warm morning light\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/social-calendar/posts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"platform\": \"linkedin\",\n \"title\": \"Ship a CRM in an afternoon\",\n \"body\": \"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.\",\n \"scheduled_at\": \"2026-09-15T14:00:00Z\",\n \"scheduled_timezone\": \"Asia/Jerusalem\",\n \"hook\": \"pain_point\",\n \"best_time_reason\": \"Weekday afternoons get the most engagement for this audience.\",\n \"hashtags\": [\n \"buildinpublic\",\n \"crm\"\n ],\n \"image_url\": \"https://cdn.example.com/posts/crm-launch.png\",\n \"image_prompt\": \"A freelancer closing a deal on a laptop, warm morning light\"\n}"
response = http.request(request)
puts response.read_body{
"id": "6886b8d390dc7e2f4a2c91b3",
"app_id": "6820f3a4e7b91d003c45a1f2",
"plan_id": "8c1f9a2e-3b7d-4c5e-9f01-2a3b4c5d6e7f",
"source_post_id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
"platform": "linkedin",
"title": "Ship a CRM in an afternoon",
"body": "We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.",
"hook": "pain_point",
"cover_index": 0,
"scheduled_at": "2026-09-15T14:00:00",
"scheduled_local_at": "2026-09-15T17:00:00+03:00",
"scheduled_timezone": "Asia/Jerusalem",
"best_time_reason": "Weekday afternoons get the most engagement for this audience.",
"hashtags": [
"buildinpublic",
"crm"
],
"image_url": "https://cdn.example.com/posts/crm-launch.png",
"image_prompt": "A freelancer closing a deal on a laptop, warm morning light",
"status": "scheduled",
"workflow_id": "68a1c4f0d21b4e0a3c77e912"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Create scheduled post
Adds a post to the app’s social calendar. The post starts as a proposal, which means it’s on the calendar but nothing publishes it yet: approve it with Approve scheduled posts, then run Start scheduling posts to hand it to the publisher.
instagram and linkedin are the only platforms Base44 can publish to, so they’re the only ones this endpoint accepts. The app needs a connected account for that platform with publishing permission by the time you schedule the post, not when you create it.
Set scheduled_at far enough ahead that it’s still in the future when you schedule the post. Scheduling refuses an instant that has already passed and marks the post failed, and a failed post can’t be revived. Send an offset-aware timestamp, or a naive one that Base44 reads as UTC. scheduled_timezone only decides the wall-clock time reported back in scheduled_local_at; it never moves the instant the post goes out.
The social calendar endpoints share two rate limits: 20 requests per minute across creating, editing, deleting and approving posts, and 40 requests per minute across the rest. This endpoint counts against the 20.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/social-calendar/posts \
--header 'Content-Type: application/json' \
--header 'api_key: <api-key>' \
--data @- <<EOF
{
"platform": "linkedin",
"title": "Ship a CRM in an afternoon",
"body": "We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.",
"scheduled_at": "2026-09-15T14:00:00Z",
"scheduled_timezone": "Asia/Jerusalem",
"hook": "pain_point",
"best_time_reason": "Weekday afternoons get the most engagement for this audience.",
"hashtags": [
"buildinpublic",
"crm"
],
"image_url": "https://cdn.example.com/posts/crm-launch.png",
"image_prompt": "A freelancer closing a deal on a laptop, warm morning light"
}
EOFimport requests
url = "https://app.base44.com/api/apps/{app_id}/social-calendar/posts"
payload = {
"platform": "linkedin",
"title": "Ship a CRM in an afternoon",
"body": "We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.",
"scheduled_at": "2026-09-15T14:00:00Z",
"scheduled_timezone": "Asia/Jerusalem",
"hook": "pain_point",
"best_time_reason": "Weekday afternoons get the most engagement for this audience.",
"hashtags": ["buildinpublic", "crm"],
"image_url": "https://cdn.example.com/posts/crm-launch.png",
"image_prompt": "A freelancer closing a deal on a laptop, warm morning light"
}
headers = {
"api_key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_key: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
platform: 'linkedin',
title: 'Ship a CRM in an afternoon',
body: JSON.stringify('We replaced our lead spreadsheet with an app we built in an afternoon. Here\'s what changed.'),
scheduled_at: '2026-09-15T14:00:00Z',
scheduled_timezone: 'Asia/Jerusalem',
hook: 'pain_point',
best_time_reason: 'Weekday afternoons get the most engagement for this audience.',
hashtags: ['buildinpublic', 'crm'],
image_url: 'https://cdn.example.com/posts/crm-launch.png',
image_prompt: 'A freelancer closing a deal on a laptop, warm morning light'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/social-calendar/posts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/social-calendar/posts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'platform' => 'linkedin',
'title' => 'Ship a CRM in an afternoon',
'body' => 'We replaced our lead spreadsheet with an app we built in an afternoon. Here\'s what changed.',
'scheduled_at' => '2026-09-15T14:00:00Z',
'scheduled_timezone' => 'Asia/Jerusalem',
'hook' => 'pain_point',
'best_time_reason' => 'Weekday afternoons get the most engagement for this audience.',
'hashtags' => [
'buildinpublic',
'crm'
],
'image_url' => 'https://cdn.example.com/posts/crm-launch.png',
'image_prompt' => 'A freelancer closing a deal on a laptop, warm morning light'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"api_key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/social-calendar/posts"
payload := strings.NewReader("{\n \"platform\": \"linkedin\",\n \"title\": \"Ship a CRM in an afternoon\",\n \"body\": \"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.\",\n \"scheduled_at\": \"2026-09-15T14:00:00Z\",\n \"scheduled_timezone\": \"Asia/Jerusalem\",\n \"hook\": \"pain_point\",\n \"best_time_reason\": \"Weekday afternoons get the most engagement for this audience.\",\n \"hashtags\": [\n \"buildinpublic\",\n \"crm\"\n ],\n \"image_url\": \"https://cdn.example.com/posts/crm-launch.png\",\n \"image_prompt\": \"A freelancer closing a deal on a laptop, warm morning light\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.base44.com/api/apps/{app_id}/social-calendar/posts")
.header("api_key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"platform\": \"linkedin\",\n \"title\": \"Ship a CRM in an afternoon\",\n \"body\": \"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.\",\n \"scheduled_at\": \"2026-09-15T14:00:00Z\",\n \"scheduled_timezone\": \"Asia/Jerusalem\",\n \"hook\": \"pain_point\",\n \"best_time_reason\": \"Weekday afternoons get the most engagement for this audience.\",\n \"hashtags\": [\n \"buildinpublic\",\n \"crm\"\n ],\n \"image_url\": \"https://cdn.example.com/posts/crm-launch.png\",\n \"image_prompt\": \"A freelancer closing a deal on a laptop, warm morning light\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/social-calendar/posts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"platform\": \"linkedin\",\n \"title\": \"Ship a CRM in an afternoon\",\n \"body\": \"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.\",\n \"scheduled_at\": \"2026-09-15T14:00:00Z\",\n \"scheduled_timezone\": \"Asia/Jerusalem\",\n \"hook\": \"pain_point\",\n \"best_time_reason\": \"Weekday afternoons get the most engagement for this audience.\",\n \"hashtags\": [\n \"buildinpublic\",\n \"crm\"\n ],\n \"image_url\": \"https://cdn.example.com/posts/crm-launch.png\",\n \"image_prompt\": \"A freelancer closing a deal on a laptop, warm morning light\"\n}"
response = http.request(request)
puts response.read_body{
"id": "6886b8d390dc7e2f4a2c91b3",
"app_id": "6820f3a4e7b91d003c45a1f2",
"plan_id": "8c1f9a2e-3b7d-4c5e-9f01-2a3b4c5d6e7f",
"source_post_id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
"platform": "linkedin",
"title": "Ship a CRM in an afternoon",
"body": "We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed.",
"hook": "pain_point",
"cover_index": 0,
"scheduled_at": "2026-09-15T14:00:00",
"scheduled_local_at": "2026-09-15T17:00:00+03:00",
"scheduled_timezone": "Asia/Jerusalem",
"best_time_reason": "Weekday afternoons get the most engagement for this audience.",
"hashtags": [
"buildinpublic",
"crm"
],
"image_url": "https://cdn.example.com/posts/crm-launch.png",
"image_prompt": "A freelancer closing a deal on a laptop, warm morning light",
"status": "scheduled",
"workflow_id": "68a1c4f0d21b4e0a3c77e912"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
Personal API key.
Path Parameters
ID of the app whose social calendar you want.
Body
Content and schedule only. Ownership, lifecycle status, workflow binding, plan lineage and publish results are server-owned; sending them is an error rather than a silently ignored field.
Account to publish to. Only instagram and linkedin are accepted; the other values this enum carries are platforms Base44 plans for but can't publish, and sending one fails with a 422.
x, instagram, tiktok, linkedin, reddit, facebook "linkedin"
Title of the post, which labels it on the calendar. It isn't published as text, except on LinkedIn, where a post with an image sends it as the image's title.
1 - 300"Ship a CRM in an afternoon"
Body text of the post. Base44 publishes this followed by hashtags, so leave the tags out of it.
50000"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed."
When the post should publish, as an ISO 8601 timestamp between the years 2000 and 2100. Send an offset, or a naive timestamp that Base44 reads as UTC. It has to still be in the future when you schedule the post.
"2026-09-15T14:00:00Z"
IANA timezone name used to render scheduled_local_at in the response. It never moves the instant the post publishes. Defaults to UTC.
64"Asia/Jerusalem"
The angle the post leads with, for your own reference on the calendar. Empty by default.
500"pain_point"
Why you picked this time, shown alongside the post on the calendar. Empty by default.
1000"Weekday afternoons get the most engagement for this audience."
Up to 30 hashtags, published after body. Send them without the leading #; one you include is stripped before publishing.
30100["buildinpublic", "crm"]
HTTPS URL of the image to publish with the post. Required for an Instagram post, which is rejected at publish time without one, and optional on LinkedIn.
2000"https://cdn.example.com/posts/crm-launch.png"
Prompt the image came from, kept for reference. This endpoint doesn't generate an image from it.
2000"A freelancer closing a deal on a laptop, warm morning light"
Response
The created post.
ID of the post. Pass it as post_id to the other social calendar endpoints.
"6886b8d390dc7e2f4a2c91b3"
ID of the app the post belongs to.
"6820f3a4e7b91d003c45a1f2"
ID of the content plan the post was generated from, or null for a post created through Create scheduled post.
"8c1f9a2e-3b7d-4c5e-9f01-2a3b4c5d6e7f"
ID this post has inside the content plan it came from, or null for a post created through the API.
"3f2504e0-4f89-11d3-9a0c-0305e82c3301"
Account the post publishes to. Base44 publishes to instagram and linkedin. A post generated from a content plan can also name x, tiktok, reddit or facebook, which Base44 plans for but can't publish, and scheduling such a post fails it.
"linkedin"
Title of the post. It labels the post on the calendar and isn't published as text, except on LinkedIn, where a post with an image sends it as the image's title.
"Ship a CRM in an afternoon"
Body text of the post. Base44 publishes this followed by hashtags, so leave the tags out of it.
"We replaced our lead spreadsheet with an app we built in an afternoon. Here's what changed."
The angle the post leads with. A plan-generated post carries the angle the planner picked, such as pain_point or social_proof; a post you create carries whatever you sent, or an empty string.
"pain_point"
Zero-based position of the post in the series its content plan generated, which is how the calendar picks its cover image. Always 0 for a post created through the API.
0
When the post publishes, always in UTC. A post read back from the calendar carries no offset (2026-09-15T14:00:00), while the one Create scheduled post returns carries +00:00. Read both as UTC.
"2026-09-15T14:00:00"
The same instant as scheduled_at, rendered in scheduled_timezone as an ISO 8601 timestamp. Display only.
"2026-09-15T17:00:00+03:00"
IANA timezone scheduled_local_at is rendered in. It never moves the instant the post publishes.
"Asia/Jerusalem"
Why this time was picked, written by the planner for a plan-generated post. Empty unless something set it.
"Weekday afternoons get the most engagement for this audience."
Hashtags published after body, without the leading #. A leading # you send is stripped before publishing.
["buildinpublic", "crm"]
HTTPS URL of the image published with the post, or null if it has none. An Instagram post needs one to publish.
"https://cdn.example.com/posts/crm-launch.png"
Prompt the post's image was generated from, or null if there is none. Kept for reference; this endpoint doesn't generate images from it.
"A freelancer closing a deal on a laptop, warm morning light"
Where the post is in its lifecycle: proposal before you approve it, scheduled once approved, publishing while it's going out, then posted. needs_reconnect means the platform account has to be reconnected, not_materialized_plan_limit that the workspace plan doesn't cover publishing, publish_outcome_unknown that the platform may have accepted the post but Base44 couldn't confirm it, and failed that the post can't go out.
"scheduled"
ID of the automation that publishes this post, set once Start scheduling posts hands it over, and null before that. Its presence is what tells you the publish time is fixed.
"68a1c4f0d21b4e0a3c77e912"
Was this page helpful?