Guides
The paths behind the quickstart: connect an account, move a post through its statuses, upload media, and publish ads from the top down.
Connect an account
OAuth stays in the Athenous app. Open Connections, link the network, then list connections with the API key.
curl -sS "https://public-api.athenous.io/api/v1/connectors" \
-H "X-Api-Key: $ATHENOUS_API_KEY"
Use the returned id as connectorId. Facebook Pages are GET /api/v1/connectors/pages?platform=FACEBOOK. Ad accounts are GET /api/v1/connectors/ad-accounts?platform=META. A Snap public profile id can be updated with PATCH /api/v1/connectors/{id}.
Post lifecycle
Status is one of DRAFT, SCHEDULED, PUBLISHING, PUBLISHED, PARTIAL, FAILED, or CANCELLED. Each channel has its own publication status: PENDING, PUBLISHING, PUBLISHED, or FAILED.
| Status | What you can do |
|---|---|
DRAFT | Edit the post. Call approve before you schedule it. Publish sends it now. |
SCHEDULED | Athenous publishes at scheduledAt. A channel scheduledAt overrides that time for one network. |
PUBLISHING | Wait, then read the post again. |
PUBLISHED | Pull engagement with POST /api/v1/posts/{id}/sync. |
PARTIAL | At least one channel published and at least one failed. Read publications[].errorMessage, then retry-failed. |
FAILED | No channel published. Fix the channel options and retry. |
There is no webhook for these transitions. Poll GET /api/v1/posts/{id} or GET /api/v1/posts/{id}/publications.
Schedule a post
Create the draft, approve it, then set the time. The full request is on the quickstart. Scheduling before approve returns a 4xx whose detail is Approve this draft before it can be scheduled.
curl -sS -X POST "https://public-api.athenous.io/api/v1/posts/$POST_ID/approve" \
-H "X-Api-Key: $ATHENOUS_API_KEY"
curl -sS -X PUT "https://public-api.athenous.io/api/v1/posts/$POST_ID?status=SCHEDULED" \
-H "X-Api-Key: $ATHENOUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"scheduledAt":"2026-03-20T14:00:00Z"}'
Publish now, then retry one network
curl -sS -X POST "https://public-api.athenous.io/api/v1/posts/$POST_ID/publish" \
-H "X-Api-Key: $ATHENOUS_API_KEY"
curl -sS -X POST "https://public-api.athenous.io/api/v1/posts/$POST_ID/retry-failed" \
-H "X-Api-Key: $ATHENOUS_API_KEY"
retry-failed sends only the channels whose last publish failed.
Upload media
Networks fetch mediaUrl at publish time. Upload the file first and store the returned URL on the post. The multipart field name is file. The response field is mediaUrl. Files around 90 MiB and larger use POST /api/v1/posts/media/upload-session, then a PUT of the bytes to uploadUrl. The full sequence is on Posts.
MEDIA_URL=$(curl -sS -X POST "https://public-api.athenous.io/api/v1/posts/media" \
-H "X-Api-Key: $ATHENOUS_API_KEY" \
-F "file=@./hero.jpg" | jq -r '.mediaUrl')
Extra images for a carousel go in media_urls inside that channel’s settings. Limits are on the platform list.
Publish ads top down
Create the campaign, publish it, then the ad set, then the ad. A key limited to athenous_post receives 403 on these routes. platform values are on the advertising list.
CID=$(curl -sS -X POST "https://public-api.athenous.io/api/v1/campaigns" \
-H "X-Api-Key: $ATHENOUS_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"API campaign","platform":"META","objectiveType":"AWARENESS","budgetAllocation":{"META":5000}}' \
| jq -r '.id')
curl -sS -X POST "https://public-api.athenous.io/api/v1/campaigns/$CID/publish" \
-H "X-Api-Key: $ATHENOUS_API_KEY" -H "Content-Type: application/json" \
-d '{"platform":"META","connectorId":"CONNECTOR_UUID","adAccountId":"act_123","facebookPageId":"123456"}'
Create the ad set at POST /api/v1/campaigns/{campaignId}/ad-sets, publish it, then create the ad at POST …/ad-sets/{adSetId}/ads and publish that. Sync metrics with POST …/sync and the same platform and connectorId.
Pages
page starts at 0. size is 1 to 1000, default 20. Posts and campaigns both return content, totalElements, and totalPages. Repeat status to filter posts, for example status=DRAFT&status=SCHEDULED.
Errors and rate limits
Default rate limit is 100 requests per minute per key. batch raises that to 500. 429 includes Retry-After.
| Code | What to do |
|---|---|
401 | Send X-Api-Key on product routes, or a bearer token on account routes. |
403 | The plan or the key scope does not include this route. A Posts-only key names the Posts scope in detail. An Ads-only key names the Ads scope. |
409 | Quota, a duplicate publish, or a plan limit. Check GET /api/v1/posts/quota/monthly for posts. |
422 | Invalid body, channelSettings, or a missing connectorId. |
502 | The network rejected the publish. Read publications[].errorMessage. |
The full code list is in the API reference. Account routes, API keys, sessions, and MFA use a session or bearer token, not X-Api-Key. See Account.