Developers

Public publishing API

Upload media, create posts, and publish to Facebook, Instagram, TikTok, LinkedIn, Threads, and Pinterest, all scoped to a product via a workspace API key. The recommended way to integrate is the Connect API — a small, flat/api/connect/v1 surface that most scheduling tools can target as-is.

Need full control — explicit publish, job-run polling, signed webhooks, batch, per-channel settings? The advanced /api/public/v1 API further down exposes all of it. Both share the same auth, products, and publishing pipeline; use only these versioned public routes (internal app routes require Firebase user auth and are not part of the public contract).

Facebook, Instagram, and TikTok are manual-first over the API. Posts for those channels default to manual_reminder delivery: Markaestro never calls the platform's API for them. Publishing moves the post to the workspace's To Post queue, where the owner downloads the media, posts natively, and confirms — so posts appear exactly as if created by hand. Pass deliveryMode: "direct_publish" on create to opt a post into official-API publishing instead (on TikTok that means the inbox handoff, never public Direct Post). LinkedIn, Threads, and Pinterest publish programmatically by default.

Workspaces can have multiple products. Every API key is bound to one product when you create it, so calls target that product automatically and requests for any other product are rejected.

Building an AI agent?

Start with the AI agent guide instead. It has copy-paste tool schemas, a system-prompt brief, the retry and error-handling rules an agent needs, and a four-command quickstart. Your agent can also read /llms.txt directly.

Connect API
Recommended
The default way to integrate: a flat, snake_case surface at /api/connect/v1 that most scheduling tools can target as-is. It maps the common create-upload-url → PUT → post convention onto the same workspace, auth, products, and publishing pipeline as the full API below. Set the client base URL to /api/connect and authenticate with a product-scoped workspace API key (scopes posts.read, posts.write, media.write).
GET/api/connect/v1/social-accounts

Lists connected Facebook, Instagram, TikTok, LinkedIn, and Threads destinations as flat accounts, each labeled with its product so clients can group and disambiguate. Each channel is its own dedicated path — no cross-channel fan-out.

GET/api/connect/v1/products

Lists brands (wire name: products) with their connected accounts nested — a brand-first picker.

POST/api/connect/v1/media/create-upload-url

Returns a short-lived, single-use signed PUT url plus a media id.

PUT<upload_url>

Upload the raw image bytes to the signed url. No API key needed — the signature authorizes it.

POST/api/connect/v1/posts

Creates a draft per selected account. Set is_draft=false with scheduled_at to schedule delivery; TikTok uses the creator-inbox handoff.

GET/api/connect/v1/posts

Lists workspace posts with flat status, caption, and media urls.

# 1. List connected accounts
curl "$MARKAESTRO_URL/api/connect/v1/social-accounts" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY"

# 2. Request a signed upload url, then PUT the bytes
curl -X POST "$MARKAESTRO_URL/api/connect/v1/media/create-upload-url" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "mime_type": "image/png", "size_bytes": 184320, "name": "slide-1.png" }'
curl -X PUT "<upload_url>" -H "Content-Type: image/png" --data-binary @slide-1.png

# 3. Create a draft post for one or more accounts
curl -X POST "$MARKAESTRO_URL/api/connect/v1/posts" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "caption": "New drop",
    "media": ["ast_111", "ast_222"],
    "social_accounts": ["prod_123#instagram:instagram:ig_123"]
  }'

Each account from /social-accounts is labeled with its product — the wire-format name for a brand (the same account can appear under multiple brands) — and its id encodes productId#destinationId — pass it back verbatim in social_accounts, and the request fans out one post per account. Each key is bound to one brand, so it only sees and posts to that brand. Facebook, Instagram, and TikTok posts are manual-first — created as drafts and published natively by the workspace owner from the Markaestro To Post queue, never via the platform's API. LinkedIn, Threads, and Pinterest publish programmatically after an explicit publish action. Post status is one of draft, processing, posted, or failed. Facebook, Instagram, LinkedIn, TikTok, and Threads are each their own dedicated destination — publishing to one never fans out to another. Track publishing state through GET /api/connect/v1/posts.

Advanced: full Public API

The complete /api/public/v1 surface — explicit publish, async job runs, signed webhooks, batch create, and per-channel settings. Use it when the Connect API is not enough.

Meta & TikTok are manual-first
Facebook, Instagram, and TikTok posts default to the manual To Post queue — no platform API call, the workspace owner posts natively and confirms. Opt into API publishing per post with deliveryMode.
Instagram Login supported
Brands can expose standalone Instagram professional accounts even when no Facebook Page is linked.
TikTok opt-in uses inbox handoff
A TikTok post opted into API publishing is sent to the creator's TikTok inbox for final caption, privacy, and posting — never public Direct Post.
Async by design
Every publish returns a run id. Poll runs or subscribe to signed webhooks instead of assuming synchronous completion.
Brands and destinations
Discover the brands and publish destinations available to the API key. Brands are called products in the wire format — paths and payloads use products/productId for backwards compatibility, and POST bodies also accept brandId as an alias.
GET/api/public/v1/products

Lists the key's brands plus the channels currently available for each one.

GET/api/public/v1/products/:id/destinations

Lists the publish destinations for that brand, including standalone Instagram Login, Facebook Page, Threads, LinkedIn Profile/Page, and connected TikTok destinations.

Media
Upload images or videos to Markaestro-managed storage before creating posts.
POST/api/public/v1/media

Multipart upload. Returns an asset id and hosted URL.

Posts
Create, list, inspect, publish, and delete posts for Facebook, Instagram, LinkedIn, Threads, Pinterest, and TikTok.
POST/api/public/v1/posts

Creates a draft in the workspace. Facebook, Instagram, and TikTok default to manual posting (deliveryMode manual_reminder); pass deliveryMode direct_publish to opt a post into API publishing.

GET/api/public/v1/posts

Lists posts, newest first. Filter with ?status=scheduled to see what is queued, and ?productId= to scope to one brand. A brand-bound key is always limited to its own brand and may omit productId.

GET/api/public/v1/posts/:id

Returns current post status, delivery mode, and publish results.

POST/api/public/v1/posts/:id/publish

Queues an async publish run. Manual posts land in the workspace's To Post queue for native posting; LinkedIn, Threads, and Pinterest publish directly; opted-in Meta posts publish via the official API, and opted-in TikTok posts use the inbox handoff.

DELETE/api/public/v1/posts/:id

Deletes the post from Markaestro. Uses the existing posts.write scope. Returns 400 VALIDATION_POST_IS_PUBLISHING while a publish run is in flight. Deleting a published post does not retract the live platform copy.

Runs and Webhooks
Track async work with polling or signed webhook delivery.
GET/api/public/v1/job-runs/:id

Returns queued, running, succeeded, or failed.

POST/api/public/v1/webhook-endpoints

Registers a webhook destination using an API key.

GET/api/public/v1/webhook-endpoints

Lists registered webhook destinations for that API key scope.

DELETE/api/public/v1/webhook-endpoints/:id

Disables a webhook destination.

1. List products
Discover which products this API key can target.
curl "$MARKAESTRO_URL/api/public/v1/products" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY"
2. Inspect destinations
See the linked pages and accounts for a product before creating the post. Use the returned destinationId when a product has multiple destinations, such as a LinkedIn Profile plus Pages.
curl "$MARKAESTRO_URL/api/public/v1/products/prod_123/destinations" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY"
3. Upload media
Each post references previously uploaded media assets.
curl -X POST "$MARKAESTRO_URL/api/public/v1/media" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY" \
  -H "Idempotency-Key: upload-001" \
  -F "file=@launch-1.jpg"
4. Create a post
Create a draft using those asset ids. Instagram defaults to manual posting; add "deliveryMode": "direct_publish" to opt this post into official-API publishing.
curl -X POST "$MARKAESTRO_URL/api/public/v1/posts" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: post-001" \
  -d '{
    "channel": "instagram",
    "caption": "Launch day carousel",
    "mediaAssetIds": ["ast_123", "ast_124"],
    "productId": "prod_123",
    "destinationId": "instagram:instagram:ig_123"
  }'
TikTok example
TikTok posts land as Markaestro drafts and default to manual posting from the To Post queue. With deliveryMode: "platform_inbox" (or direct_publish), an explicit publish sends the draft to the creator's TikTok inbox instead.
curl -X POST "$MARKAESTRO_URL/api/public/v1/posts" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: post-tt-001" \
  -d '{
    "channel": "tiktok",
    "caption": "Spring drop teaser",
    "mediaAssetIds": ["ast_vid_123"],
    "productId": "prod_123",
    "destinationId": "tiktok:tiktok:tt_open_123"
  }'
5. Queue publish
Publishing creates an async run. Manual posts (the Facebook/Instagram/TikTok default) move to the To Post queue and fire post.action_required; LinkedIn, Threads, Pinterest, and opted-in Meta posts publish directly; opted-in TikTok posts queue the inbox handoff.
curl -X POST "$MARKAESTRO_URL/api/public/v1/posts/pst_123/publish" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY" \
  -H "Idempotency-Key: publish-001"
6. Review the schedule and cancel
List what is queued for a brand, then delete anything you no longer want to go out. Both use scopes existing keys already carry — posts.read and posts.write.
# What is scheduled for one brand
curl "$MARKAESTRO_URL/api/public/v1/posts?status=scheduled&productId=prod_123&limit=100" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY"

# Omit productId to see every brand the key can reach
curl "$MARKAESTRO_URL/api/public/v1/posts?status=scheduled" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY"

# Cancel one
curl -X DELETE "$MARKAESTRO_URL/api/public/v1/posts/pst_123" \
  -H "Authorization: Bearer $MARKAESTRO_API_KEY"
Webhook payload example
Deliveries are signed with HMAC using your webhook secret.
{
  "id": "evt_123",
  "type": "post.action_required",
  "createdAt": "2026-04-08T18:06:10.000Z",
  "workspaceId": "ws_123",
  "data": {
    "postId": "pst_123",
    "channel": "instagram",
    "status": "platform_action_required",
    "nextAction": "post_manually_from_reminder"
  }
}
Channel behavior
Validation and delivery rules enforced by the public API.

Facebook

Text-only, image, or video posts. Up to 10 images or 1 video per post. Manual posting by default; direct publish on opt-in.

Instagram

At least one image or video, up to 10 items. Single video publishes as a Reel. Manual posting by default; direct publish on opt-in.

TikTok

At least one image or video. Up to 10 images or 1 video. Manual posting by default; opted-in posts go to the creator's TikTok inbox, never public Direct Post.

LinkedIn

Text, single image, single video, or organic multi-image posts up to 20 images. Target either the connected Profile or a managed Page.