Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Breakreach Posts API
version: 1.1.0
description: 'Publish and schedule social media posts across Instagram, TikTok, X (Twitter), Reddit, LinkedIn, YouTube, Facebook, Threads, Bluesky, Pinterest, Telegram, Discord, Slack, Mastodon, WordPress, Ghost, Dev.to, Hashnode, Tumblr and Google Business Profile with one request shape.
Authenticate with an API key (create one in the Breakreach dashboard under Settings → API & MCP) sent as a Bearer token. Errors answer with an HTTP status and a JSON body { "error": "" }.
Every POST accepts an Idempotency-Key header: any unique string up to 255 characters, a UUID for instance. Retrying with the same key and the same body within 24 hours returns the first response, marked Idempotent-Replayed: true, instead of creating a second post. The same key with a different body answers 422, and 409 while the first request is still running. Errors are not kept, so a fixed request can reuse its key. Keys belong to the API key that sent them.
AI agents can use the same capabilities through the hosted MCP server at https://api.breakreach.com/mcp (OAuth 2.1).'
servers:
- url: https://api.breakreach.com
security:
- bearerAuth: []
tags:
- name: Posts
paths:
/v1/posts:
get:
summary: List posts
operationId: listPosts
parameters:
- name: workspace
in: query
schema:
type: string
- name: status
in: query
schema:
type: string
enum:
- draft
- scheduled
- published
- failed
- all
- name: limit
in: query
schema:
type: integer
default: 25
maximum: 100
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- posts
properties:
posts:
type: array
items:
$ref: '#/components/schemas/Post'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Workspace not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Posts
post:
summary: Create a post (schedule, publish now or save a draft)
description: 'Creates a post targeting one or several connected accounts. Provide scheduledAt (interpreted in the workspace timezone), or set useNextSlot to schedule at the next free slot of the workspace posting schedule, or publishNow to publish immediately. Set draft to save it for review in Breakreach without scheduling it: a draft needs no publish time (scheduledAt, if given, places it on the calendar), skips the media checks, and goes out only once it is scheduled, in the app or with PATCH /v1/posts/{id}. Media must be public URLs — use POST /v1/media first for reliable hosting. Media is required for Instagram, TikTok, YouTube and Pinterest. On Instagram one photo is a feed post, one video a Reel, and 2 to 10 files (photos and videos, in order) a carousel whose photos are all cropped to the first photo''s shape. Facebook Pages take up to 10 photos in one post, or one video. LinkedIn posts one MP4 video alone, or turns 2 to 20 photos into a carousel (a PDF document, one page per photo, all cropped to the first photo''s shape, titled with the first line), and posts a PDF URL as a document. Pinterest takes one image or one MP4/MOV video; an image sent with the video becomes its cover. YouTube publishes one video; an image sent with it becomes its custom thumbnail (JPG or PNG, 1280x720 works best; YouTube only takes custom thumbnails from verified channels, and the video is published without one otherwise).'
operationId: createPost
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- content
- accountIds
properties:
content:
type: string
description: The post text. For Reddit, the first line becomes the title.
accountIds:
type: array
items:
type: string
description: Target account ids from GET /v1/accounts
scheduledAt:
type: string
description: ISO datetime in the workspace timezone, e.g. 2026-09-20T11:00:00
publishNow:
type: boolean
useNextSlot:
type: boolean
draft:
type: boolean
description: Save as a draft for review instead of scheduling it. Can't be combined with publishNow
media:
type: array
items:
type: string
format: uri
workspace:
type: string
description: Workspace slug (optional)
pinterestBoardId:
type: string
description: Required when targeting Pinterest — see GET /v1/pinterest-boards
pinterestLink:
type: string
format: uri
description: Destination URL of the pin (optional, http(s), up to 2,048 characters). The pin title is the first line of content
redditSubreddit:
type: string
description: Subreddit without r/ — defaults to the user profile
redditFlairText:
type: string
description: Post flair name when the subreddit requires one
articleSettings:
$ref: '#/components/schemas/ArticleSettings'
googleBusinessSettings:
$ref: '#/components/schemas/GoogleBusinessSettings'
tiktokSettings:
type: object
properties:
privacyLevel:
type: string
enum:
- PUBLIC_TO_EVERYONE
- MUTUAL_FOLLOW_FRIENDS
- FOLLOWER_OF_CREATOR
- SELF_ONLY
disableComment:
type: boolean
disableDuet:
type: boolean
disableStitch:
type: boolean
responses:
'200':
description: Created
content:
application/json:
schema:
type: object
required:
- post
properties:
post:
$ref: '#/components/schemas/CreatedPost'
'400':
description: 'Validation error: missing content, accountIds or publish time, an account outside the workspace, missing media or pinterestBoardId, invalid scheduledAt, pinterestLink or googleBusinessSettings, a Google Business Profile update over 1,500 characters or with a video'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Workspace not found, or useNextSlot found no free slot
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
$ref: '#/components/responses/IdempotencyRunning'
'422':
$ref: '#/components/responses/IdempotencyMismatch'
tags:
- Posts
/v1/posts/{id}:
patch:
summary: Edit, schedule or move back to drafts
description: 'Edits a draft, scheduled or failed post. Only the fields you send change. Sending scheduledAt, useNextSlot or publishNow schedules the post: a draft goes out at that time, a failed post is retried. draft: true moves a scheduled post back to drafts so it won''t publish. Published posts can''t be edited.'
operationId: updatePost
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
content:
type: string
accountIds:
type: array
items:
type: string
description: Replaces the target accounts
media:
type: array
items:
type: string
format: uri
description: Replaces the media
scheduledAt:
type: string
description: ISO datetime in the workspace timezone, e.g. 2026-09-20T11:00:00
publishNow:
type: boolean
useNextSlot:
type: boolean
draft:
type: boolean
description: true moves the post back to drafts
workspace:
type: string
description: Workspace slug (optional)
pinterestBoardId:
type: string
pinterestLink:
type: string
format: uri
redditSubreddit:
type: string
redditFlairText:
type: string
articleSettings:
$ref: '#/components/schemas/ArticleSettings'
googleBusinessSettings:
$ref: '#/components/schemas/GoogleBusinessSettings'
responses:
'200':
description: Updated
content:
application/json:
schema:
type: object
required:
- post
properties:
post:
$ref: '#/components/schemas/CreatedPost'
'400':
description: Post already published, empty content or accountIds, draft combined with publishNow, missing media or pinterestBoardId once scheduled, invalid scheduledAt
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Post or workspace not found, or useNextSlot found no free slot
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Posts
delete:
summary: Delete a post (cancels scheduling)
operationId: deletePost
parameters:
- name: id
in: path
required: true
schema:
type: string
- name: workspace
in: query
schema:
type: string
responses:
'200':
description: Deleted
content:
application/json:
schema:
type: object
required:
- ok
properties:
ok:
type: boolean
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Post or workspace not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Posts
/v1/posts/{id}/metrics:
get:
summary: Per-post metrics
description: Views, likes, comments and shares for one post, plus the platform post ids it published to.
operationId: getPostMetrics
parameters:
- name: id
in: path
required: true
schema:
type: string
- name: refresh
in: query
schema:
type: boolean
description: Fetch fresh metrics from the platforms before answering, instead of the last stored ones
- name: workspace
in: query
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- id
- status
- publishedAt
- metrics
- perPlatform
- error
properties:
id:
type: string
status:
type: string
publishedAt:
type:
- string
- 'null'
format: date-time
metrics:
type:
- object
- 'null'
properties:
views:
type: number
likes:
type: number
comments:
type: number
shares:
type: number
perPlatform:
type: array
items:
type: object
required:
- accountId
- platform
- platformPostId
properties:
accountId:
type: string
platform:
type: string
platformPostId:
type: string
error:
type:
- string
- 'null'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Post or workspace not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Posts
/v1/posts/{id}/comments:
get:
summary: Read comments on a published post
description: 'Live comments/replies from the platforms. Supported: Instagram, Facebook, Threads, X. Each comment carries the accountId and platform needed to reply; accounts that couldn''t be read are listed in errors with the reason. YouTube is not listed yet: its comments need a restricted Google permission (youtube.force-ssl) that is not available to every account.'
operationId: getPostComments
parameters:
- name: id
in: path
required: true
schema:
type: string
- name: workspace
in: query
schema:
type: string
responses:
'200':
description: OK
'400':
description: The post has no published platform ids yet
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Post or workspace not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Posts
components:
schemas:
CreatedPost:
type: object
required:
- id
- status
- scheduledAt
- accounts
properties:
id:
type: string
status:
type: string
enum:
- draft
- scheduled
- publishing
description: publishing when publishNow was set, draft when draft was set
scheduledAt:
type: string
format: date-time
description: Publish time, in UTC
accounts:
type: array
items:
type: string
description: Target accounts as "platform (display name)", e.g. "instagram (Acme)"
Error:
type: object
required:
- error
properties:
error:
type: string
description: Human-readable reason
ArticleSettings:
type: object
description: Options for the blog networks (Dev.to, Hashnode, Ghost, Tumblr). On Dev.to, Hashnode and Ghost the first line of content is the title and the rest the body, in Markdown; the first photo is the cover
properties:
tags:
type: array
items:
type: string
description: Dev.to keeps the first 4 (letters and digits), Hashnode 15, Ghost and Tumblr up to 30
canonicalUrl:
type: string
format: uri
description: Where the article was first published, when this is a copy (Dev.to, Hashnode, Ghost)
asDraft:
type: boolean
description: Create it as an unpublished draft on the blog instead of publishing it
newsletter:
type: string
description: 'Ghost: also email the post with this newsletter (its slug, or "default" for the site''s first active one)'
emailSegment:
type: string
enum:
- all
- status:free
- status:-free
description: 'Ghost newsletter: who gets the email (default all members)'
aiDisclosure:
type: string
enum:
- no_ai
- some_ai
- fully_autonomous
description: 'Dev.to: how much AI wrote the article (Dev.to asks API clients to say so accurately)'
GoogleBusinessSettings:
type: object
description: 'Google Business Profile only: the button under the update. The update itself is the content (up to 1,500 characters) and one photo; videos aren''t accepted'
properties:
button:
type: string
enum:
- BOOK
- ORDER
- SHOP
- LEARN_MORE
- SIGN_UP
- CALL
description: BOOK, ORDER (order online), SHOP (buy), LEARN_MORE, SIGN_UP, or CALL (calls the profile's phone number). Omit for no button
buttonUrl:
type: string
format: uri
description: Where the button leads (http/https), required for every button except CALL
Post:
type: object
required:
- id
- content
- status
- scheduledAt
- accountIds
- media
- metrics
- error
properties:
id:
type: string
content:
type: string
status:
type: string
enum:
- draft
- scheduled
- publishing
- published
- failed
scheduledAt:
type: string
format: date-time
accountIds:
type: array
items:
type: string
media:
type: array
items:
type: string
format: uri
metrics:
type:
- object
- 'null'
properties:
views:
type: number
likes:
type: number
comments:
type: number
shares:
type: number
error:
type:
- string
- 'null'
description: Human-readable failure reason when status is failed
responses:
Unauthorized:
description: Missing, invalid or expired API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
IdempotencyRunning:
description: 'A request with this Idempotency-Key is still running: retry after Retry-After seconds to get its response'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
PaymentRequired:
description: No active Breakreach subscription or trial
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
IdempotencyMismatch:
description: This Idempotency-Key was already used with a different request in the last 24 hours
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: Not a member of the requested workspace
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
schema:
type: string
minLength: 1
maxLength: 255
description: 'A unique string for this request, e.g. a UUID. A retry with the same key and body within 24 hours returns the first response (with the header Idempotent-Replayed: true) instead of running again. Printable ASCII, no spaces.'
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: API key from the Breakreach dashboard (br_...) or an OAuth access token (bro_...)