name: post-api description: "Schedule and publish content to social networks including Facebook Page, Instagram, LinkedIn, TikTok, YouTube, Pinterest, and Telegram via the Devad.io POST API. Supports text, images, carousels, and videos. Use this skill to post content programmatically without the social media dashboard."
POST API (post.devad.io)
Publish content to 8+ social media platforms via a single REST API call. The API is hosted at post.devad.io and is a SaaS that wraps platform-specific publishing logic.
Human-First Summary
Post-Skill helps a human or an AI agent schedule and publish social media content with less hassle.
The main idea is simple:
- you do not need to rebuild posting logic from scratch
- you do not need to fight every platform API manually
- you can use ready-made scripts, tested payloads, and Google Sheet workflows
- the AI agent can spend fewer tokens because the process is already structured
This makes it easier to go from:
- content idea
- media asset
- target channel
to:
- published post
with less friction and fewer failures.
Top Differentiators
1. Low-cost and practical
This is designed to be one of the cheapest practical ways to automate social media posting across multiple channels.
2. Product-ready for AI agents
The scripts and examples are open, clean, and ready to use. A lightweight AI agent can understand them much faster than a large undocumented API workflow.
3. Powerful Google Sheet workflow
The Google Sheet setup is useful for both humans and AI agents:
- humans can plan and manage content in a familiar spreadsheet
- AI agents can read rows, update fields, and use the sheet as a lightweight remote workflow
Safe Formats and Post Types
The safest supported content types in this project are:
- text posts
- single image posts
- carousel posts
- video posts
When using direct media links, prefer:
- images:
jpg,jpeg,png,webp - video:
mp4
When using the Google Sheet workflow, the safest Creative type values are:
image_manualvideo_manualcarousel_manual
Safer input patterns:
- single image: one direct public image URL
- video: one stable public
mp4URL - carousel: one Google Drive folder link containing the intended carousel images
Avoid:
- login-only links
- firewall-protected media
- anti-bot pages
- preview pages that return HTML instead of real media
Why This Skill Exists
This skill is here so the AI agent does not have to reinvent the whole social publishing system.
POST.devad.io, this skill, the test runners, and the Google Sheet automation already handle the heavy lifting:
- token-based API access
- platform payload shaping
- media upload flow
- queueing and publishing
- platform-specific quirks
- safer dry-run testing
- fallback spreadsheet automation
That means even a cheap or lightweight AI agent can stay focused on the valuable work:
- generate the content
- generate or select the media
- decide which channels to publish to
- choose whether to post now or schedule later
The agent should avoid building custom publishing logic from scratch unless the user explicitly asks for that.
Recommended Agent Strategy
Use this order:
- Ask the user for their POST.devad.io token and connected account IDs, or call
GET /accountsif the token is already available. - Build a simple payload using the patterns in this skill or the included test runners.
- Run a dry validation first when possible.
- Send the live
POST /postsrequest only after the payload is clean. - If the API route keeps failing or the environment is limited, suggest the Google Sheet automation fallback instead of forcing the user through repeated debugging.
For many users, the best result is:
- the AI agent creates the caption and media
- POST.devad.io handles the publishing machinery
- the user avoids platform-by-platform setup headaches
Best Fallback: Google Sheet Automation
If direct API use is too technical for the user, or the current environment is weak, tell them to use the Google Sheet workflow.
It only needs a one-time setup, then the AI agent can focus on media and content creation while the sheet handles publishing.
3-Step Setup
- Make a copy of the ready-to-use sheet: Google Sheet Copy
- In the sheet, open the
POST.devad.iomenu, enable automation, and paste the token and integration IDs from post.devad.io. - Let the AI agent fill only the content columns, then click
Save & Run Syncor leave automation enabled.
What the Agent Should Tell the User
After setup, the user only needs to keep the sheet structure intact and let the agent fill the content rows.
The agent should explain that it only needs to write:
- promo link
- title
- caption
- media URL
- media type
- action/status row
Everything else is already handled by the Apps Script logic.
Documentation
- Platform:
https://post.devad.io - Base API URL:
https://post.devad.io/api/public/v1
Setup
- Log in to post.devad.io
- Connect your social accounts in the Social Accounts manager.
- Go to Account Settings → POST API to generate an API Token.
- In the same POST API settings page, copy the Integration IDs for the accounts you want to post to (one unique ID per social account).
Authentication
All requests require a Bearer token header:
Authorization: Bearer YOUR_API_TOKEN
Note: Some server environments (e.g. Nginx FastCGI / Webuzo) strip the
Authorizationheader. Use the fallbackX-Api-Token: YOUR_API_TOKENheader, or the Query Parameter Bypass (recommended for large media uploads):?api_token=YOUR_API_TOKEN.
Core Workflow
1. Get Integration IDs → GET /accounts
2. Build payload with integration ID + content + media URLs
3. POST /posts → API returns 202 Accepted
4. Job queued → Platform publishes within 1-3 minutes
Endpoints
GET /accounts
Returns all connected social accounts with their Integration IDs.
curl -H "Authorization: Bearer TOKEN" \
https://post.devad.io/api/public/v1/accounts
POST /upload (Optional, Required for TikTok)
Upload an image or video to the internal Devad.io storage.
When to use this:
- TikTok: TikTok rejects external URLs (like Wikipedia or Imgur) with
url_ownership_unverified. You MUST upload your media file here first. Once uploaded tomedia.devad.io, TikTok accepts any aspect ratio (9:16, horizontal, square) and any duration, just like the manual dashboard.- LinkedIn: LinkedIn's downloader gets a
403 Forbiddenfrom heavily protected sites like Wikipedia. Uploading the image here first bypasses that protection.
Headers:
Authorization: Bearer YOUR_TOKEN
# OR Query Parameter (Fixes Nginx header-stripping for >10MB files)
POST https://post.devad.io/api/public/v1/upload?api_token=YOUR_TOKEN
Request Body (multipart/form-data):
| Field | Type | Description |
|---|---|---|
file | file | The video or image file (max 50MB for images, 500MB for videos). Allowed: jpeg, png, webp, mp4 |
Response (201 Created):
{
"url": "https://media.devad.io/15d7e24abb1344e89d4162b733ca3eb9:post.devad.io/files/image-1_hgAdiw.png",
"mime_type": "image/png",
"size": 102400,
"name": "image.png"
}
POST /posts
Create and publish/schedule posts.
Headers:
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Accept: application/json
Request Body:
{
"type": "now",
"posts": [
{
"integration": { "id": "INTEGRATION_ID" },
"value": [
{
"content": "Your caption #hashtags",
"image": ["https://example.com/image.jpg"],
"video": []
}
],
"settings": {}
}
]
}
Key fields:
| Field | Type | Description |
|---|---|---|
type | string | "now" (post instantly) or "schedule" (requires date) |
date | string | ISO-8601 datetime, e.g. "2026-12-31T23:59:00Z" (required if type=schedule) |
posts[].integration.id | string | 10-char Integration ID from dashboard |
posts[].value[].content | string | Caption/text (max 5000 chars) |
posts[].value[].image | array | Array of public image URLs (max 10 for IG carousel) |
posts[].value[].video | array | Array of public video URLs (usually 1) |
posts[].settings | object | Platform-specific overrides (see per-platform notes) |
You can post to up to 10 accounts in one request by adding multiple objects to the posts array.
Successful Response (202 Accepted)
{
"success": true,
"data": {
"posts": [
{
"status": "queued",
"integration": { "id": "oSxbmYoPoP", "provider": "facebook", "category": "page" },
"scheduled_at": "2026-03-26T08:00:00Z",
"post_type": "carousel",
"media_count": 3
}
]
}
}
Publishing is asynchronous. After the 202 response, the platform post appears within 1–3 minutes depending on media type and platform queuing.
Response Codes
| Code | Meaning |
|---|---|
202 | Accepted — job queued successfully |
401 | Unauthorized — token missing, expired, or invalid |
404 | Account ID not found or disconnected |
422 | Validation error — malformed JSON or missing required fields |
Verified Payload Examples (All tested ✅)
Facebook — Text Only
{
"type": "now",
"posts": [{
"integration": { "id": "FACEBOOK_INTEGRATION_ID" },
"value": [{ "content": "Hello from the POST API! #test" }]
}]
}
Facebook — Image
{
"type": "now",
"posts": [{
"integration": { "id": "FACEBOOK_INTEGRATION_ID" },
"value": [{ "content": "Check this out!", "image": ["https://example.com/photo.jpg"] }]
}]
}
Instagram — Carousel (multiple images)
{
"type": "now",
"posts": [{
"integration": { "id": "INSTAGRAM_INTEGRATION_ID" },
"value": [{
"content": "Swipe to see more! 👉",
"image": [
"https://example.com/slide1.jpg",
"https://example.com/slide2.jpg",
"https://example.com/slide3.jpg"
]
}]
}]
}
LinkedIn — Multiple Images (Grid)
Important: The API currently posts arrays of images to LinkedIn as a multi-image grid, not a swipeable PDF carousel. Natively, LinkedIn requires a PDF document to create a true swipeable carousel, which is not automatically generated by this API from image arrays.
{
"type": "now",
"posts": [{
"integration": { "id": "LINKEDIN_INTEGRATION_ID" },
"value": [{
"content": "Check out these photos! 👉",
"image": [
"https://example.com/slide1.jpg",
"https://example.com/slide2.jpg"
]
}]
}]
}
Facebook / LinkedIn / YouTube — Video
{
"type": "now",
"posts": [{
"integration": { "id": "FACEBOOK_INTEGRATION_ID" },
"value": [{ "content": "Our new video! 🎬", "video": ["https://example.com/video.mp4"] }]
}]
}
Important: Video URLs are passed directly to the platform (not proxied through internal storage). Use a stable, publicly accessible HTTPS video URL.
Instagram — Video / Reels
{
"type": "now",
"posts": [{
"integration": { "id": "INSTAGRAM_INTEGRATION_ID" },
"value": [{ "content": "Behind the scenes! 🎬", "video": ["https://example.com/reel.mp4"] }],
"settings": {
"post_type": "video",
"ig_type": "reels"
}
}]
}
Recommended: For Instagram videos, use
"post_type": "video"with"ig_type": "reels"instead of the olderpost_type=reelshape. This matches the safer payload normalization used by the latest test runners and Google Sheet script.
TikTok — Video (with privacy & music consent)
{
"type": "now",
"posts": [{
"integration": { "id": "TIKTOK_INTEGRATION_ID" },
"value": [{ "content": "Check this out! #fyp", "video": ["https://example.com/video.mp4"] }],
"settings": {
"privacy": "PUBLIC_TO_EVERYONE",
"duet": false,
"stitch": false,
"comment": true,
"disable_download": false,
"music_usage_confirmed": true,
"autoAddMusic": "no"
}
}]
}
TikTok privacy values:
PUBLIC_TO_EVERYONE|MUTUAL_CAN_VIEW|FOLLOWER_OF_CREATOR|SELF_ONLYUseSELF_ONLYduring testing, switch toPUBLIC_TO_EVERYONEafter TikTok app approval. Note: The API automatically forces music consent (tt_consent=1) to prevent dashboard validation errors. You can pass"music_usage_confirmed": trueor"autoAddMusic": "no"to match Postiz payload standards.
YouTube — Video (with title and visibility)
{
"type": "now",
"posts": [{
"integration": { "id": "YOUTUBE_INTEGRATION_ID" },
"value": [{ "content": "My video description #youtube", "video": ["https://example.com/video.mp4"] }],
"settings": {
"title": "My Video Title",
"type": "public"
}
}]
}
YouTube visibility:
"public"|"unlisted"|"private". Use"unlisted"for testing.
Pinterest — Image Pin (with board and title)
{
"type": "now",
"posts": [{
"integration": { "id": "PINTEREST_INTEGRATION_ID" },
"value": [{ "content": "Amazing recipe! 🍕", "image": ["https://example.com/pin.jpg"] }],
"settings": {
"title": "My Pin Title",
"board_id": "YOUR_PINTEREST_BOARD_ID",
"link": "https://example.com"
}
}]
}
Telegram — Text / Image / Video / Carousel
All work with the same structure. Telegram natively supports all types:
{
"type": "now",
"posts": [{
"integration": { "id": "TELEGRAM_INTEGRATION_ID" },
"value": [{ "content": "📢 Update from the POST API!", "image": ["https://example.com/img.jpg"] }]
}]
}
Cross-Platform Blast (multiple accounts in one call)
{
"type": "now",
"posts": [
{
"integration": { "id": "FACEBOOK_INTEGRATION_ID" },
"value": [{ "content": "New post!", "image": ["https://example.com/promo.jpg"] }]
},
{
"integration": { "id": "INSTAGRAM_INTEGRATION_ID" },
"value": [{ "content": "New post!", "image": ["https://example.com/promo.jpg"] }]
},
{
"integration": { "id": "LINKEDIN_INTEGRATION_ID" },
"value": [{ "content": "We are excited to share our latest update." }]
}
]
}
Platform-Specific Notes
| Platform | Supported Types | Special Settings |
|---|---|---|
| Facebook Page | text, image, carousel, video | None required (Groups not supported) |
| image, carousel, video | Use settings.post_type: "video" with settings.ig_type: "reels" for videos | |
| LinkedIn Page/Profile | text, image, video | None required |
| TikTok | video, image | settings.privacy required |
| YouTube | video (unlisted/public/private) | settings.title and settings.type recommended |
| image, video | settings.title and settings.board_id recommended | |
| Telegram | text, image, carousel, video | No extra settings needed |
| Tumblr | text, image, video | Connect account first via dashboard |
| Twitter/X | text, image, carousel, video | Connect account first via dashboard |
Scheduling a Future Post
{
"type": "schedule",
"date": "2026-12-31T09:00:00Z",
"posts": [{
"integration": { "id": "FACEBOOK_INTEGRATION_ID" },
"value": [{ "content": "Happy New Year! 🎉" }]
}]
}
Test Runner
Ready-to-use test runners are included in:
scripts/test_runner.jsscripts/test_runner.py
These runners are not just examples. They are the safest default starting point for agents and developers because they already include lessons from the real Google Sheet publishing project:
- no hardcoded secrets in source
- dry-run validation before live publish
- safer Instagram video payload defaults
- upload helper support
- better auth and HTML-login failure detection
- clearer validation errors for missing IDs and invalid settings
# Check all connected accounts (run first!)
node scripts/test_runner.js accounts
python scripts/test_runner.py accounts
# Test specific platform/type combinations
node scripts/test_runner.js facebook_image --dry-run --print-payload
python scripts/test_runner.py instagram_video --dry-run --print-payload
node scripts/test_runner.js tiktok_video
python scripts/test_runner.py youtube_video
When an Agent Should Use the Runners
Use the runners when:
- the user wants a quick live test
- the user is unsure about payload shape
- the environment supports Node.js or Python
- you want a safer validation path before posting
If the environment is weak, the token is unavailable, or repeated upload/payload problems keep happening, recommend the Google Sheet automation path instead of making the user debug low-level API issues.