Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/postlake-dev:postlake-dev-account-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: PostLake Account API
version: 1.0.0
description: Unified social media API. One API key, 10 platforms, normalised responses. Built for agents and developers.
contact:
url: https://postlake.dev
servers:
- url: https://api.postlake.dev
security:
- bearerAuth: []
tags:
- name: Account
description: API key identity, permissions, usage and account info
paths:
/v1/me/limits:
get:
tags:
- Account
summary: What this key may do, and what it can spend
description: The authenticated key's machine identity, enforced publishing policy, connected channels, credit balance, and rate limits. rateLimits.apiPerMinute and postsPerMinute are the workspace ceiling. rateLimits.profile is the per-Channels-profile cap, so one end user cannot starve the others. Networks still apply their own caps (TikTok is about 6 requests a minute per account). MCP agents receive the same view through whoami. Read this before planning a batch rather than discovering a limit by being refused.
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
account:
type: string
email:
type: string
name:
type: string
credits:
type: object
properties:
total:
type: integer
monthly:
type: integer
pack:
type: integer
monthlyAllowance:
type: integer
plan:
type: string
blockedPlatforms:
type: array
items:
type: string
billing:
type: object
description: Billing state separate from the entitlement tier. `payg` means the Free plan with a positive balance of purchased, non-renewing credits, not a subscription.
properties:
mode:
type: string
enum:
- free
- payg
- subscription
isSubscriber:
type: boolean
hasPurchasedCredits:
type: boolean
required:
- mode
- isSubscriber
- hasPurchasedCredits
connected:
type: array
items:
type: object
properties:
account:
type: string
platform:
type: string
handle:
type: string
status:
type: string
rateLimits:
type: object
properties:
apiPerMinute:
type: integer
description: Authenticated /v1 and /mcp requests per 60-second window for this workspace. The abuse ceiling shared by every profile.
postsPerMinute:
type: integer
description: POST /v1/posts, /v1/posts/{id}/publish, and MCP create_post / publish_draft per 60-second window for this workspace.
profile:
type: object
description: Per Channels profile (one end user). Applied when the request names profile or the post's accounts resolve to one.
properties:
apiPerMinute:
type: integer
description: Authenticated requests per 60-second window for this profile.
postsPerMinute:
type: integer
description: Publishes per minute for this profile. A noisy customer cannot spend the workspace envelope alone.
required:
- apiPerMinute
- postsPerMinute
required:
- apiPerMinute
- postsPerMinute
- profile
operationId: getV1MeLimits
x-operation-id-source: derived
/v1/me/agent:
patch:
tags:
- Account
summary: Set this agent's own display name
description: Changes only the authenticated API key's display nickname. It does not rename the key, change its permissions, or affect another agent. The account owner can lock the display name in Agent Control. Pass null to return to the key's original name.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- nickname
additionalProperties: false
properties:
nickname:
type:
- string
- 'null'
maxLength: 60
responses:
'200':
description: Updated identity
content:
application/json:
schema:
type: object
required:
- id
- name
- clientName
- nickname
- nicknameLocked
properties:
id:
type: string
name:
type: string
clientName:
type: string
nickname:
type:
- string
- 'null'
nicknameLocked:
type: boolean
'403':
description: The account owner locked this display name
operationId: patchV1MeAgent
x-operation-id-source: derived
/v1/social-accounts/{id}/profile:
patch:
tags:
- Account
summary: Edit a connected account's own profile
description: Change the display name, bio, avatar or banner. Only the fields you send are changed. Images are given as public URLs and uploaded for you. A network that does not allow this refuses.
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
displayName:
type: string
bio:
type: string
avatarUrl:
type: string
bannerUrl:
type: string
responses:
'200':
description: Updated
content:
application/json:
schema:
type: object
properties:
account:
type: string
platform:
type: string
ok:
type: boolean
operationId: patchV1SocialAccountsByIdProfile
x-operation-id-source: derived
/v1/me:
get:
tags:
- Account
summary: Get current account
description: Validate API key and echo account info, including the optional default timezone.
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
id:
type: string
email:
type: string
platforms:
type: array
items:
$ref: '#/components/schemas/Platform'
timezone:
type: string
description: IANA default for naive scheduledAt values, when set.
required:
- id
- email
- platforms
'401':
$ref: '#/components/responses/Unauthorized'
operationId: getV1Me
x-operation-id-source: derived
patch:
tags:
- Account
summary: Update current account
description: Set or clear the account default timezone used for naive scheduledAt values.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
timezone:
type: string
description: IANA name such as Europe/London. Empty string or null clears the default.
nullable: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
id:
type: string
email:
type: string
platforms:
type: array
items:
$ref: '#/components/schemas/Platform'
timezone:
type: string
required:
- id
- email
- platforms
'400':
description: Invalid timezone
'401':
$ref: '#/components/responses/Unauthorized'
operationId: patchV1Me
x-operation-id-source: derived
/v1/account/export:
get:
tags:
- Account
summary: Export account data
description: GDPR data export. All data for the account (no secrets).
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
account:
type: object
properties:
id:
type: string
email:
type: string
required:
- id
- email
profiles:
type: array
items:
$ref: '#/components/schemas/Profile'
socialAccounts:
type: array
items:
$ref: '#/components/schemas/SocialAccount'
posts:
type: array
items:
$ref: '#/components/schemas/Post'
auditLog:
type: array
items:
$ref: '#/components/schemas/AuditEvent'
exportedAt:
type: string
format: date-time
required:
- account
- profiles
- socialAccounts
- posts
- auditLog
- exportedAt
'401':
$ref: '#/components/responses/Unauthorized'
operationId: getV1AccountExport
x-operation-id-source: derived
/v1/audit:
get:
tags:
- Account
summary: Get audit log
description: Security audit trail (logins, key creation, disconnects). Returns up to 100 events.
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
events:
type: array
items:
$ref: '#/components/schemas/AuditEvent'
required:
- events
'401':
$ref: '#/components/responses/Unauthorized'
operationId: getV1Audit
x-operation-id-source: derived
/v1/email-preferences:
get:
tags:
- Account
summary: Read email preferences
description: 'How often this account receives the attention summary: the one email PostLake sends on its own schedule, when a channel has stopped working or a scheduled post did not go out. Account and security email (verify, password reset, new sign-in, payment failed) always sends and is not covered here.'
responses:
'200':
description: Current preferences
content:
application/json:
schema:
$ref: '#/components/schemas/EmailPreferences'
'401':
$ref: '#/components/responses/Unauthorized'
operationId: getV1EmailPreferences
x-operation-id-source: derived
patch:
tags:
- Account
summary: Set email preferences
description: 'Set how often the attention summary may arrive and whether optional product emails may send. Send at least one field. `daily` sends at most once a day and only on days something is actually wrong; `weekly` gathers anything still unresolved into at most one email a week; `off` stops it entirely. `onboarding` controls optional product emails. There is deliberately no MCP tool for this: these emails are how a person learns a post did not go out, and an agent that could switch them off could hide a failure it caused.'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
digestFrequency:
type: string
enum:
- 'off'
- weekly
- daily
onboarding:
type: boolean
description: Whether to receive optional product emails.
responses:
'200':
description: Updated preferences
content:
application/json:
schema:
$ref: '#/components/schemas/EmailPreferences'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
operationId: patchV1EmailPreferences
x-operation-id-source: derived
components:
schemas:
SocialAccount:
type: object
properties:
id:
type: string
platform:
$ref: '#/components/schemas/Platform'
handle:
type: string
profileId:
oneOf:
- type: string
- type: 'null'
status:
type: string
avatarUrl:
oneOf:
- type: string
- type: 'null'
connectVariant:
type: string
description: 'Which door this account was connected through, for networks that have more than one. Instagram is the case: `instagram` means Instagram Login, `facebook` means it was connected through a Facebook Page. The two reach genuinely different feature sets, so this decides what the account can do. Absent on networks with a single way in.'
accountType:
oneOf:
- type: string
enum:
- BUSINESS
- MEDIA_CREATOR
- PERSONAL
- type: 'null'
description: Instagram account type when known. Stories support both login routes, subject to Meta account eligibility. Facebook Login Stories require a Business account. Null means the type is unknown; Meta enforces eligibility during publishing.
discovers:
type: object
description: What this ACCOUNT can search, as opposed to GET /v1/platforms/{platform}, which can only speak for the network as a whole. An Instagram connected by Instagram Login cannot search creators or hashtags however the platform-level flags read, so check here before calling a discovery endpoint rather than learning it from an error.
properties:
posts:
type: boolean
profiles:
type: boolean
profilePosts:
type: boolean
places:
type: boolean
creators:
type: boolean
description: 'True only when the connection can reach its creator-discovery product. A true still leaves the network''s own onboarding to be done: Meta refuses the search with `creator_marketplace_not_onboarded` until the brand has accepted the relevant terms.'
required:
- posts
- profiles
- profilePosts
- places
- creators
requires:
oneOf:
- type: string
- type: 'null'
description: 'What this network needs before it will publish, in one sentence (media requirements, title and caption limits). Read it before composing: TikTok, Instagram, YouTube and Pinterest all refuse text-only posts. Null when the network accepts anything.'
required:
- id
- platform
- handle
- profileId
- status
- discovers
ErrorResponse:
type: object
properties:
error:
$ref: '#/components/schemas/NormalisedError'
required:
- error
NormalisedError:
type: object
description: '`type` is the coarse category you route on and is deliberately small, so it cannot say WHICH input was wrong. `code`, `fix`, `docs` and `param` are what turn a rejection into something a caller can act on rather than guess at. They are optional only in the sense that not every error has all four.'
properties:
type:
type: string
description: Coarse category to route on, e.g. rate_limited, auth_expired, platform_rejected.
message:
type: string
platform:
oneOf:
- $ref: '#/components/schemas/Platform'
- type: 'null'
retryable:
type: boolean
code:
type: string
description: Stable, granular handle to branch on, e.g. text_too_long. Also the anchor in the error reference.
fix:
type: string
description: The next action, in plain words. Safe to show a person as-is.
docs:
type: string
format: uri
description: Where the rule is written down, so it is learned once rather than rediscovered.
param:
type: string
description: The request field at fault, so a form can mark the right input.
required:
- type
- message
- retryable
TargetState:
type: string
enum:
- queued
- scheduled
- processing
- published
- failed
PostState:
type: string
enum:
- draft
- awaiting_approval
- rejected
- queued
- scheduled
- processing
- partial
- published
- failed
PostTarget:
type: object
properties:
removal:
type: object
description: Present after accepted network removal on a partial result. Retry skips accepted destinations; verified separately confirms absence.
properties:
accepted:
type: boolean
enum:
- true
verified:
type: boolean
at:
type: string
format: date-time
required:
- accepted
- verified
- at
account:
type: string
platform:
$ref: '#/components/schemas/Platform'
state:
$ref: '#/components/schemas/TargetState'
profile:
type: string
description: Username of the profile this channel belongs to. Resolved when the post is read, so it follows the channel if it moves. Absent once the channel is disconnected.
channelName:
type: string
description: The channel's handle at the time of reading, not the one frozen at publish. Absent once the channel is disconnected.
connection:
type: object
description: The native account or destination identity captured when this target was scheduled. It is used only to repair a disconnected channel safely.
properties:
platformAccountId:
type: string
destinationId:
type: string
destinationName:
type: string
handle:
type: string
remoteId:
oneOf:
- type: string
- type: 'null'
url:
oneOf:
- type: string
- type: 'null'
publishedAt:
oneOf:
- type: string
format: date-time
- type: 'null'
permalinkPending:
type: boolean
description: True when publication succeeded but an exact public permalink is still being resolved.
error:
oneOf:
- $ref: '#/components/schemas/NormalisedError'
- type: 'null'
required:
- account
- platform
- state
- remoteId
- url
- publishedAt
- error
AuditEvent:
type: object
properties:
id:
type: string
action:
type: string
ip:
type: string
userAgent:
type: string
createdAt:
type: string
format: date-time
required:
- id
- action
- ip
- userAgent
- createdAt
Platform:
type: string
enum:
- bluesky
- threads
- x
- linkedin
- instagram
- tiktok
- facebook
- youtube
- pinterest
EmailPreferences:
type: object
properties:
digest:
type: boolean
description: False when digestFrequency is off. Kept so older clients still work.
digestFrequency:
type: string
enum:
- 'off'
- weekly
- daily
onboarding:
type: boolean
description: Whether optional product emails may send.
required:
- digest
- digestFrequency
- onboarding
Profile:
type: object
properties:
id:
type: string
username:
type: string
description: The identifier agents put in `profile:`. Slugified.
name:
type: string
description: What the person typed, for display. Absent on profiles created before this existed.
createdAt:
type: string
format: date-time
required:
- id
- username
- createdAt
Post:
type: object
properties:
id:
type: string
sourceDraftId:
type: string
description: Immutable original draft ID. New approvals preserve this as id; legacy audited approvals may resolve an older ID to a different canonical id.
snapshot:
type: string
description: Computed full-state approval fence returned by GET. Includes media, options and metadata.
state:
$ref: '#/components/schemas/PostState'
createdAt:
type: string
format: date-time
clientId:
type: string
description: Stable machine principal that created the post. Absent for human-created dashboard posts.
surface:
type: string
enum:
- dashboard
- api
- agent
description: Where the post was created, independent of the principal identity.
approval:
type: object
description: Present for approval-gated agent work, including the owner's final decision when one has been made.
properties:
requestedAt:
type: string
format: date-time
decision:
type: string
enum:
- approved
- rejected
decidedAt:
type: string
format: date-time
reason:
type: string
required:
- requestedAt
scheduledAt:
oneOf:
- type: string
format: date-time
- type: 'null'
timezone:
type: string
description: IANA timezone the caller scheduled in, when they named one.
scheduledAtLocal:
type: string
description: Wall-clock time in timezone, computed on read. Not stored.
text:
type: string
campaign:
type: string
assetMetadata:
type: object
additionalProperties:
type: string
media:
type: array
items:
type: string
warnings:
type: array
items:
type: string
description: Advisory notes from create or edit, for example PNG converted to JPEG for TikTok.
platformOptions:
oneOf:
- type: object
properties:
pinterest:
type: object
properties:
boardId:
type: string
link:
type: string
altText:
type: string
- type: 'null'
targets:
type: array
items:
$ref: '#/components/schemas/PostTarget'
required:
- id
- state
- createdAt
- scheduledAt
- text
- media
- platformOptions
- targets
responses:
BadRequest:
description: Referenced by this document but never defined in it. API Evangelist added this empty placeholder so the document resolves; the shape is unknown and is NOT a claim about the API.
x-ae-placeholder: true
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: unauthorized
message: missing or invalid api key
retryable: false