API Reference
Posts
List what exists, and create posts as a draft, a scheduled post, or an immediate publish across up to ten platforms at once.
List posts
GET
/api/v1/postsRequires read. Newest first.
Query parameters
statusstringoptionalFilter to one status:
draft, scheduled, publishing, published, partial or failed.limitnumberoptionalHow many to return. Defaults to 20, clamped to 50.
curl
curl "https://app.echoia.io/api/v1/posts?status=scheduled&limit=5" \
-H "Authorization: Bearer $ECHOIA_API_KEY"200
{
"posts": [
{
"id": "cmq7f8k1c0003sl3k7b4xe9rt",
"content": "New drop is live.",
"platforms": ["instagram", "x"],
"status": "scheduled",
"scheduledAt": "2026-09-12T18:00:00.000Z",
"publishedAt": null,
"results": [],
"errorMessage": null,
"createdAt": "2026-09-05T10:14:02.117Z"
}
]
}Content is truncated in lists
Post bodies over 500 characters come back shortened with an ellipsis, so a listing stays cheap. Fetch the post in the app if you need the full text.
Create a post
POST
/api/v1/postsRequires write — plus publish if you set publishNow.
Parameters
contentstringrequiredThe post text. Up to 10,000 characters.
accountsstring[]requiredWhich connected accounts publish it. Each entry is a handle qualified by platform (
instagram:@acme), a bare handle when it is connected on one platform only (@acme), or an account id from /accounts. One result per account; duplicates are ignored. A reference matching nothing — or more than one account — is refused with the candidates listed.accountIdsstring[]optionalDeprecated synonym of
accounts.platformsstring[]optionalShorthand alternative to
accounts. Resolves only while the platform has exactly one connected account; with several it is refused with ambiguous_platform and the candidates are listed. Supply one field or the other.scheduledAtstringoptionalISO 8601 datetime in the future. Omit for a draft. Mutually exclusive with publishNow.
publishNowbooleanoptionalPublish immediately. Requires the
publish scope.mediaUrlsstring[]optionalUp to 10 absolute https:// URLs. Relative paths are rejected.
firstCommentsstring[]optionalUp to 5 comments posted under the post once it is live, in order. Max 2,200 characters each.
Three modes, one endpoint
| You send | You get | Goes public |
|---|---|---|
| Neither field | draft — sits in the Posts tab | No |
scheduledAt | scheduled — editable until then | At that time |
publishNow: true | published / partial / failed | Immediately |
Scheduling
curl
curl -X POST https://app.echoia.io/api/v1/posts \
-H "Authorization: Bearer $ECHOIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Doors open Friday.",
"accounts": ["instagram:@acme", "facebook:@acme"],
"scheduledAt": "2026-09-12T18:00:00Z",
"firstComments": ["Full details in the link in bio."]
}'Overdue scheduled posts are not published late
If a scheduled post is more than six hours overdue — an outage, a long pause — it is marked
failed rather than published. A promotion going out a day late is worse than not going out.Publishing immediately
curl
curl -X POST https://app.echoia.io/api/v1/posts \
-H "Authorization: Bearer $ECHOIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Live now.",
"accounts": ["x:@acme", "x:@acme.labs"],
"publishNow": true
}'201
{
"post": {
"id": "cmq7fb2p90007sl3kd8y1qw3v",
"status": "published",
"scheduledAt": null,
"platforms": ["x"]
},
"accounts": [
{ "accountId": "cmr7ffil3", "platform": "x", "account": "@acme" },
{ "accountId": "cmrd5lx2uizc", "platform": "x", "account": "@acme.labs" }
],
"results": [
{ "platform": "x", "accountId": "cmr7ffil3", "accountLabel": "@acme", "success": true, "postId": "1834…", "url": "https://x.com/i/web/status/1834…" },
{ "platform": "x", "accountId": "cmrd5lx2uizc", "accountLabel": "@acme.labs", "success": true, "postId": "1835…", "url": "https://x.com/i/web/status/1835…" }
],
"note": "Published on every targeted account."
}results is keyed by account, not by platform
Two accounts on the same platform produce two entries with the same
platform. Match on accountId. The accounts array echoes what the request resolved to, which is what you read back when you used the platforms shorthand.Publishing is not all-or-nothing. One account can succeed while another fails — always read results, and see Errors for the partial case.
What gets rejected
- Neither
accountsnorplatforms. - An account reference that names nothing this key can reach, or an account that is disconnected.
- A
platformsentry matching several connected accounts —ambiguous_platform, with the candidates listed. Sendaccountsinstead. - Neither
contentnormediaUrls. - Both
scheduledAtandpublishNow. - A
scheduledAtin the past, or not a valid ISO datetime. publishNowwithout thepublishscope — and nothing is created.
Was this page helpful?