Quickstart
From zero to a published post: create an API key, a team, connect an account, upload media and publish, using plain HTTP.
The Free plan is enough for everything on this page: it includes 20 posts, 200 uploads and 3 teams a month. Examples use curl; every request is also available through the SDK.
1. Get an API key
Sign up, then open API Keys in the dashboard and create a key. It starts with sk_live_ and is shown once. Keep it on your server.
export SIAR_API_KEY=sk_live_... Check that it works:
curl "https://api.siaran.my/api/v1/team" -H "x-api-key: $SIAR_API_KEY" An empty list is a success: { "items": [], "total": 0 }.
2. Create a team
A team is a group of at most one connected account per network. Use one per customer, brand or location.
curl -X POST "https://api.siaran.my/api/v1/team" \
-H "x-api-key: $SIAR_API_KEY" \
-H "content-type: application/json" \
-d '{ "name": "Acme Bakery" }'
# → { "id": "TEAM_ID", "name": "Acme Bakery", ... } 3. Connect an account
Ask for an authorization URL, open it in a browser and sign in with the network. Afterwards the account belongs to the team.
curl -X POST "https://api.siaran.my/api/v1/social-account/connect" \
-H "x-api-key: $SIAR_API_KEY" \
-H "content-type: application/json" \
-d '{
"type": "LINKEDIN",
"teamId": "TEAM_ID",
"redirectUrl": "https://yourapp.example/connected"
}'
# → { "url": "https://www.linkedin.com/oauth/v2/authorization?..." }
# Send your user to that URL. After consent they land back on redirectUrl. To let your own users do this, send them a hosted connect link instead.
4. Upload media (optional)
# Small files: multipart form upload
curl -X POST "https://api.siaran.my/api/v1/upload" \
-H "x-api-key: $SIAR_API_KEY" \
-F "teamId=TEAM_ID" \
-F "file=@./launch.jpg"
# Or let Siar fetch it from a public URL
curl -X POST "https://api.siaran.my/api/v1/upload/from-url" \
-H "x-api-key: $SIAR_API_KEY" \
-H "content-type: application/json" \
-d '{ "teamId": "TEAM_ID", "url": "https://cdn.example.com/launch.mp4" }'
# → { "id": "UPLOAD_ID", "type": "video", "mime": "video/mp4", ... } The response contains the upload id. Reference it from any post in uploadIds.
5. Publish
curl -X POST "https://api.siaran.my/api/v1/post" \
-H "x-api-key: $SIAR_API_KEY" \
-H "content-type: application/json" \
-d '{
"teamId": "TEAM_ID",
"title": "Launch day",
"postDate": "2026-11-02T09:00:00.000Z",
"status": "SCHEDULED",
"socialAccountTypes": [
"INSTAGRAM",
"LINKEDIN",
"BLUESKY"
],
"data": {
"INSTAGRAM": {
"type": "POST",
"text": "We shipped. Details in the comments.",
"uploadIds": [
"UPLOAD_ID"
]
},
"LINKEDIN": {
"text": "We shipped today. Here is what changed and why.",
"uploadIds": [
"UPLOAD_ID"
]
},
"BLUESKY": {
"text": "We shipped today.",
"uploadIds": [
"UPLOAD_ID"
]
}
},
"firstComment": {
"INSTAGRAM": "Changelog: example.com/changelog"
}
}' const res = await fetch('https://api.siaran.my/api/v1/post', {
method: 'POST',
headers: { 'x-api-key': process.env.SIAR_API_KEY, 'content-type': 'application/json' },
body: JSON.stringify({
"teamId": "TEAM_ID",
"title": "Launch day",
"postDate": "2026-11-02T09:00:00.000Z",
"status": "SCHEDULED",
"socialAccountTypes": [
"INSTAGRAM",
"LINKEDIN",
"BLUESKY"
],
"data": {
"INSTAGRAM": {
"type": "POST",
"text": "We shipped. Details in the comments.",
"uploadIds": [
"UPLOAD_ID"
]
},
"LINKEDIN": {
"text": "We shipped today. Here is what changed and why.",
"uploadIds": [
"UPLOAD_ID"
]
},
"BLUESKY": {
"text": "We shipped today.",
"uploadIds": [
"UPLOAD_ID"
]
}
},
"firstComment": {
"INSTAGRAM": "Changelog: example.com/changelog"
}
}),
});
const post = await res.json();
console.log(post.id, post.status); // e.g. "SCHEDULED" import os, requests
res = requests.post(
"https://api.siaran.my/api/v1/post",
headers={"x-api-key": os.environ["SIAR_API_KEY"]},
json={
"teamId": "TEAM_ID",
"title": "Launch day",
"postDate": "2026-11-02T09:00:00.000Z",
"status": "SCHEDULED",
"socialAccountTypes": [
"INSTAGRAM",
"LINKEDIN",
"BLUESKY"
],
"data": {
"INSTAGRAM": {
"type": "POST",
"text": "We shipped. Details in the comments.",
"uploadIds": [
"UPLOAD_ID"
]
},
"LINKEDIN": {
"text": "We shipped today. Here is what changed and why.",
"uploadIds": [
"UPLOAD_ID"
]
},
"BLUESKY": {
"text": "We shipped today.",
"uploadIds": [
"UPLOAD_ID"
]
}
},
"firstComment": {
"INSTAGRAM": "Changelog: example.com/changelog"
}
},
)
post = res.json()
print(post["id"], post["status"]) With status: "SCHEDULED" and a future postDate the post publishes at that time. Use DRAFT to store it without publishing.
6. Check the result
curl "https://api.siaran.my/api/v1/post/POST_ID" -H "x-api-key: $SIAR_API_KEY" The status moves from SCHEDULED through PROCESSING to POSTED or ERROR. For production, listen for the post.published webhook instead of polling.
Next
- Posting and statuses for per-network payloads and retries.
- Platform pages for each network’s limits and fields.
- Rate limits and errors before you go to production.