JuzPost Identity API
Who the calling token belongs to, and what its plan allows.
Who the calling token belongs to, and what its plan allows.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
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.curl "https://apis.io/api/v1/apis/juzpost:juzpost-identity-api"
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.
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 Identity 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: Identity
description: Who the calling token belongs to, and what its plan allows.
paths:
/me:
get:
operationId: getMe
summary: Show who the token belongs to and what its plan allows
description: 'Returns the calling user, the credential, the workspace and its scheduling defaults,
the plan, billing state, the entitlements that gate every other operation, quota usage,
the limits in force and a `blocked` list of plain-English reasons a write would fail.
This is the only authenticated operation that is not itself gated on the `api`
capability, so call it first to discover whether a schedule or upload would be
rejected with `402`. The same shape backs the MCP `get_context` tool.'
tags:
- Identity
responses:
'200':
description: Identity, credential, workspace, plan, billing, entitlements, quotas, limits and blockers.
content:
application/json:
schema:
$ref: '#/components/schemas/Me'
'401':
$ref: '#/components/responses/Unauthorized'
/workspace:
get:
operationId: getWorkspace
summary: Get the workspace timezone and preset posting times
description: 'Returns the workspace the token belongs to. The `timezone` and `defaultTimes` are the
inputs the bulk scheduler uses when you do not override them, so read this before
calling `POST /schedule` if you want to predict the slots it will pick.'
tags:
- Identity
responses:
'200':
description: The account this token belongs to.
content:
application/json:
schema:
$ref: '#/components/schemas/Workspace'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'404':
description: The account behind this token no longer exists.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
responses:
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'
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'
schemas:
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.
'
Billing:
type: object
description: Subscription state for the workspace.
required:
- status
- periodEnd
- cancelAtPeriodEnd
- graceUntil
- dunning
properties:
status:
type: string
description: The billing provider's subscription status, such as `active`, `trialing` or `past_due`.
periodEnd:
type: string
format: date-time
description: End of the current billing period.
cancelAtPeriodEnd:
type: boolean
description: Whether the subscription ends at `periodEnd`.
graceUntil:
type:
- integer
- 'null'
description: Unix milliseconds until which already-scheduled posts keep publishing after a failed payment. Null when not in dunning.
dunning:
type: boolean
description: True while payment has failed and the grace window is open. New schedules are refused; scheduled posts still fire until `graceUntil`.
Entitlement:
type: object
description: One capability and, when it is locked, the lowest plan that allows it.
required:
- allowed
- requiredPlan
properties:
allowed:
type: boolean
description: Whether the plan behind this token permits the action right now.
requiredPlan:
type:
- string
- 'null'
enum:
- none
- solo
- growth
- pro
- null
description: The lowest plan that allows the action, or null when `allowed` is true.
Workspace:
type: object
description: 'The account this token belongs to: the boundary around your accounts, posts and media,
plus the scheduling defaults the bulk scheduler reads.
'
required:
- id
- name
- timezone
- defaultTimes
properties:
id:
type: string
format: uuid
description: The account id. You never send it anywhere; quote it if you contact support.
name:
type: string
description: Display name of the account.
timezone:
type: string
description: 'IANA timezone name, such as `America/New_York`. Preset posting times are wall-clock
times in this zone, converted to UTC at scheduling time, so daylight saving is
handled for you.
'
examples:
- America/New_York
defaultTimes:
type: array
description: 'Preset posting times as 24-hour `HH:MM` wall-clock strings in your timezone.
`POST /schedule` uses these unless you override them, and fails with `422` if this
list is empty and you pass none.
'
items:
type: string
description: A posting time as `HH:MM` in your timezone.
pattern: ^\d{2}:\d{2}$
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
Me:
type: object
description: Everything an agent needs to know before acting, in one call.
required:
- user
- credential
- workspace
- plan
- billing
- entitlements
- quotas
- limits
- blocked
properties:
user:
type: object
description: The user the credential was minted for.
required:
- id
- email
properties:
id:
type: string
format: uuid
description: The user's id.
email:
type:
- string
- 'null'
description: The user's email address, or null if the account has none on record.
credential:
type: object
description: The credential used for this request. Never includes the secret.
required:
- type
- scopes
- expiresAt
properties:
type:
type: string
enum:
- api_key
- oauth
description: '`api_key` for a dashboard-issued key, `oauth` for an AI connector grant.'
scopes:
type: array
description: Scopes granted. API keys hold all four.
items:
type: string
enum:
- read
- create
- edit
- admin
expiresAt:
type:
- string
- 'null'
format: date-time
description: When an OAuth access token expires. Null for API keys.
workspace:
allOf:
- $ref: '#/components/schemas/Workspace'
- type: object
required:
- slug
- role
properties:
slug:
type: string
description: URL slug of the workspace.
role:
type: string
description: The calling user's role in the workspace, such as `owner`.
description: The workspace this credential is scoped to. Everything you can read or write lives inside it.
plan:
type: object
description: The plan in force. An unknown or lapsed subscription resolves to `none`.
required:
- id
- name
- trialActive
properties:
id:
type: string
enum:
- none
- solo
- growth
- pro
description: Plan id. `none` means no active paid plan, in which case most operations return `402`.
name:
type: string
description: Display name of the plan.
trialActive:
type: boolean
description: Whether the subscription is in its trial period.
billing:
oneOf:
- $ref: '#/components/schemas/Billing'
- type: 'null'
description: Subscription state, or null when the workspace has never subscribed.
entitlements:
$ref: '#/components/schemas/Entitlements'
quotas:
type: object
description: 'Usage against the caps. `subscription` is one pool shared by every workspace the
plan owner has; `workspace` is this workspace alone.
'
required:
- subscription
- workspace
properties:
subscription:
type: object
required:
- ownedBy
- accounts
- queuedPosts
properties:
ownedBy:
type: string
enum:
- you
- workspace owner
description: Whose subscription the plan and these counts belong to.
accounts:
type: object
required:
- used
- max
properties:
used:
type: integer
description: Social accounts connected across every workspace the owner has.
max:
type: integer
description: Account slots granted to the subscription.
queuedPosts:
type: object
required:
- used
- max
properties:
used:
type: integer
description: Posts scheduled and not yet published, across every workspace the owner has.
max:
type: integer
description: Maximum scheduled posts the plan allows at once.
workspace:
type: object
required:
- accounts
- storage
properties:
accounts:
type: integer
description: Social accounts connected in this workspace.
storage:
type: object
required:
- usedBytes
- quotaBytes
properties:
usedBytes:
type: integer
description: Bytes of media stored in this workspace.
quotaBytes:
type: integer
description: Storage quota in bytes for this workspace.
limits:
type: object
description: The fixed limits scheduling and uploads are validated against.
required:
- scheduleAheadDays
- minScheduleMinutes
- maxFilesPerPost
- blockedPlatforms
- presignPerMinute
properties:
scheduleAheadDays:
type: integer
description: How far into the future a post may be scheduled.
minScheduleMinutes:
type: integer
description: Minimum lead time for a scheduled post.
maxFilesPerPost:
type: integer
description: Maximum media files on one post.
blockedPlatforms:
type: array
description: Platforms the plan cannot post to.
items:
type: string
presignPerMinute:
type: integer
description: '`POST /storage/presign` calls allowed per minute.'
blocked:
type: array
description: 'Plain-English reasons a write would fail right now, such as a missing plan, a
past-due subscription or a full queue. Empty when nothing blocks you. Show these to
the user instead of attempting the doomed write.
'
items:
type: string
Entitlements:
type: object
description: 'The capability flags that gate this API. Check these before attempting a write rather
than discovering a `402` mid-workflow.
'
required:
- api
- schedule
- publish
- connectAccount
- createWorkspace
properties:
api:
allOf:
- $ref: '#/components/schemas/Entitlement'
description: 'Programmatic access at all. When not allowed, every operation except `GET /me`
returns `402`. Requires the Pro plan.
'
schedule:
allOf:
- $ref: '#/components/schemas/Entitlement'
description: 'Scheduling for a future time, and by extension media uploads. When not allowed,
`POST /schedule`, future-dated single-post scheduling and `POST /storage/presign`
return `402`.
'
publish:
allOf:
- $ref: '#/components/schemas/Entitlement'
description: Publishing immediately. When not allowed, scheduling with no `publishAt` returns `402`.
connectAccount:
allOf:
- $ref: '#/components/schemas/Entitlement'
description: Whether another social account can be connected. Reflects the account slots granted to this customer, not only the plan.
createWorkspace:
allOf:
- $ref: '#/components/schemas/Entitlement'
description: Whether another workspace can be created.
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`.
'