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/juzpost:juzpost-accounts-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
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: JuzPost REST Accounts API
version: 1.0.0
summary: Token-only API behind the `juzpost` command line client.
description: 'The machine-facing surface of JuzPost: connect-once device login, draft creation,
media upload to R2, and scheduling posts across connected social accounts.
**Base URL.** `https://www.juzpost.com/api/cli/v1`. Note the `cli` segment:
`/api/v1` is a different, older surface used by the dashboard and is not this API.
**Authentication.** Every operation requires `Authorization: Bearer `. There are no
unauthenticated operations.
## Get a token
1. Open **Settings, General** in the JuzPost
dashboard.
2. Find the **API keys** card and choose **Generate API key**.
3. Copy the key. It begins with `jp_live_` and is shown **once**, at creation. Store it in
your secret manager before leaving the page.
4. Check it works:
```bash
curl https://www.juzpost.com/api/cli/v1/me \
--header "Authorization: Bearer jp_live_YOUR_KEY"
```
A `200` comes back with your account, plan and capabilities. A `401` means the key is
wrong, revoked, or was pasted with a trailing newline.
Revoke a key from the same card. Nothing in this API can delete the credential it is
calling with, which is deliberate: an automated client should not be able to lock itself
out, and revocation should be a human action.
**One token, one account.** A token belongs to exactly one JuzPost account (a *workspace*).
Every operation acts on that one account, and no operation anywhere accepts an account id.
**Entitlements.** Every operation other than `GET /me` requires the
caller''s plan to include the `api` capability, and `POST /schedule`,
`POST /posts/{postId}/schedule` and `POST /storage/presign` additionally require `schedule`
(or `publish`, for immediate posting). A plan that lacks the capability produces `402`,
never `403`. Call `GET /me` first to check before attempting a write that is doomed.
**Errors.** Every non-2xx response uses the same envelope: a single `error` object carrying
a stable machine-readable `code`, a human `message`, and optional `details`. Never branch on
the message text; branch on `error.code` or the HTTP status.
**Unknown ids.** An id that is not yours is reported as `404`, never `403`, so no operation
can be used to discover whether someone else''s data exists.'
contact:
name: JuzPost Support
url: https://www.juzpost.com/support
license:
name: Proprietary
url: https://www.juzpost.com/terms
servers:
- url: https://www.juzpost.com/api/cli/v1
description: The only supported base URL.
security:
- bearerAuth: []
tags:
- name: Accounts
description: Connected social accounts and the named groups that bundle them.
paths:
/accounts:
get:
operationId: listAccounts
summary: List your connected social accounts
description: 'Returns connected social accounts, newest first by default. Use the returned `id` values
as `socialAccountIds` when scheduling. Access and refresh tokens are never included in
the response. Results are cursor-paginated: pass `pagination.nextCursor` back as
`cursor` to get the next page, and stop when `pagination.hasMore` is false.'
tags:
- Accounts
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Order'
- $ref: '#/components/parameters/AccountSort'
- $ref: '#/components/parameters/PlatformFilter'
- $ref: '#/components/parameters/GroupIdFilter'
responses:
'200':
description: One page of connected accounts.
content:
application/json:
schema:
$ref: '#/components/schemas/AccountPage'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
/groups:
get:
operationId: listGroups
summary: List the named account groups you can schedule to
description: 'Returns channel groups: saved bundles of social accounts, used so you can schedule to
"all-tiktok" instead of listing account ids. The group `name` is what
`POST /schedule` accepts in its `group` field. Cursor-paginated.'
tags:
- Accounts
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Order'
- $ref: '#/components/parameters/GroupSort'
- $ref: '#/components/parameters/NameFilter'
responses:
'200':
description: One page of channel groups.
content:
application/json:
schema:
$ref: '#/components/schemas/GroupPage'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
/groups/{groupId}:
get:
operationId: getGroup
summary: Get one account group and its members
description: 'Returns a single channel group with the full list of social account ids in it. A group
belonging to someone else is reported as `404`, never `403`.'
tags:
- Accounts
parameters:
- $ref: '#/components/parameters/GroupIdPath'
responses:
'200':
description: The group and its member account ids.
content:
application/json:
schema:
$ref: '#/components/schemas/Group'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'404':
$ref: '#/components/responses/NotFound'
components:
parameters:
GroupIdPath:
name: groupId
in: path
required: true
description: Id of the channel group, as returned by `GET /groups`.
schema:
type: string
format: uuid
AccountSort:
name: sort
in: query
required: false
description: 'Which field to sort connected accounts by. An unlisted value returns `400`.
'
schema:
type: string
enum:
- createdAt
- username
- platform
default: createdAt
Order:
name: order
in: query
required: false
description: 'Sort direction. Anything other than the literal `asc` is treated as `desc`.
'
schema:
type: string
enum:
- asc
- desc
default: desc
NameFilter:
name: name
in: query
required: false
description: Return only groups whose name contains this substring.
schema:
type: string
GroupIdFilter:
name: groupId
in: query
required: false
description: 'Return only accounts that are members of this channel group. An unknown or empty group
yields an empty page rather than an error.
'
schema:
type: string
format: uuid
PlatformFilter:
name: platform
in: query
required: false
description: 'Return only accounts on this platform, matched exactly, for example `tiktok`,
`youtube`, `instagram`, `x`, `bluesky`, `pinterest`.
'
schema:
type: string
Limit:
name: limit
in: query
required: false
description: 'How many items to return in this page. Values outside 1-100 are clamped rather than
rejected. Defaults to 20.
'
schema:
type: integer
minimum: 1
maximum: 100
default: 20
GroupSort:
name: sort
in: query
required: false
description: 'Which field to sort groups by. An unlisted value returns `400`.
'
schema:
type: string
enum:
- createdAt
- name
default: createdAt
Cursor:
name: cursor
in: query
required: false
description: 'Opaque continuation token. Omit it for the first page, then pass back the previous
response''s `pagination.nextCursor` verbatim. Never parse, construct or modify it, and
do not reuse a cursor after changing `sort`, `order` or any filter, which returns `400`
with `error.details.code` of `invalid_cursor`.
'
schema:
type: string
schemas:
GroupPage:
allOf:
- $ref: '#/components/schemas/PageEnvelope'
- type: object
description: A page of channel groups.
properties:
data:
type: array
description: The groups in this page.
items:
$ref: '#/components/schemas/Group'
PaginationMeta:
type: object
description: 'Page state returned by every list operation. Keyset-based, so it stays correct while
rows are being inserted, and it deliberately carries no total count.
'
required:
- limit
- nextCursor
- hasMore
properties:
limit:
type: integer
description: The page size actually applied, after clamping to 1-100.
nextCursor:
type:
- string
- 'null'
description: 'Pass this back as the `cursor` query parameter to fetch the next page. It is `null`
when there is no next page.
'
hasMore:
type: boolean
description: 'True when at least one more page exists. Stop paginating when this is false rather
than when the data array is short.
'
Account:
type: object
description: 'A connected social account. Access and refresh tokens are never serialized here.
'
required:
- id
- username
- platform
- avatarUrl
- isActive
- createdAt
properties:
id:
type: string
format: uuid
description: 'The account id. Pass these values in `socialAccountIds` when scheduling.
'
username:
type: string
description: The handle or channel name on the platform.
platform:
type: string
description: 'Which network this account is on, for example `tiktok`, `youtube`, `instagram`,
`x`, `bluesky` or `pinterest`.
'
avatarUrl:
type:
- string
- 'null'
description: Profile picture URL, or null if the platform gave none.
isActive:
type: boolean
description: 'Whether the connection is still usable. An inactive account normally needs
reconnecting in the dashboard before it can publish.
'
createdAt:
type: string
format: date-time
description: When the account was connected.
Error:
type: object
description: 'The envelope returned by every non-2xx response in this API. There is never a top-level
field other than `error`.
'
required:
- error
properties:
error:
type: object
description: The single error describing why the request did not succeed.
required:
- code
- message
properties:
code:
$ref: '#/components/schemas/ErrorCode'
message:
type: string
description: 'Human-readable explanation, safe to show to a user. Wording is not stable across
releases, so never parse or match on it.
'
details:
description: 'Optional structured context whose shape depends on the code, for example
`{ "requiredPlan": "pro" }` on a `payment_required`, `{ "code":
"invalid_cursor" }` on a bad cursor, or `{ "usedBytes": …, "quotaBytes": … }`
when a storage quota is full. Treat it as opaque unless a specific operation
documents its contents.
'
Group:
type: object
description: 'A channel group: a named bundle of social accounts you can schedule to by name.
'
required:
- id
- name
- accountIds
- accountCount
- createdAt
properties:
id:
type: string
format: uuid
description: The group id.
name:
type: string
description: 'The group''s name. This is the value `POST /schedule` accepts in its `group` field,
matched exactly.
'
accountIds:
type: array
description: Ids of the social accounts in this group, in no guaranteed order.
items:
type: string
format: uuid
description: A social account id belonging to this group.
accountCount:
type: integer
description: 'How many accounts are in the group. The bulk scheduler rejects groups of more than
10 with a `422`.
'
createdAt:
type: string
format: date-time
description: When the group was created.
PageEnvelope:
type: object
description: 'Shared shape of every paginated response: a `data` array plus `pagination` state.
'
required:
- data
- pagination
properties:
data:
type: array
description: The rows in this page, ordered by the requested sort and direction.
items: {}
pagination:
$ref: '#/components/schemas/PaginationMeta'
ErrorCode:
type: string
description: 'Stable machine-readable error identifier. Branch on this rather than on the message.
Each code maps to exactly one HTTP status.
'
enum:
- bad_request
- unauthorized
- payment_required
- forbidden
- not_found
- conflict
- unprocessable
- pending
- rate_limited
- internal
AccountPage:
allOf:
- $ref: '#/components/schemas/PageEnvelope'
- type: object
description: A page of connected social accounts.
properties:
data:
type: array
description: The accounts in this page.
items:
$ref: '#/components/schemas/Account'
responses:
NotFound:
description: 'No such resource. A resource that belongs to someone else is
also reported here, so this never confirms whether another tenant''s id exists.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
PaymentRequired:
description: 'The plan behind this token does not include the capability this operation needs.
`error.details.requiredPlan` names the tier that does. This is never a token problem, so
do not retry without changing the plan.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: 'The request body or query string failed validation. `error.message` names the first
problem found.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: 'No bearer token was sent, or the token is unknown, revoked or malformed. Run the device
login again to obtain a new token.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'An API key created in the dashboard under Settings, General, API keys, sent as
`Authorization: Bearer jp_live_...`. Required on every operation without exception.
Missing, malformed, revoked or unknown tokens all produce `401` with code
`unauthorized`.
'