Properties
| Name | Type | Description |
|---|---|---|
| id | string | |
| sourceDraftId | string | Immutable original draft ID. New approvals preserve this as id; legacy audited approvals may resolve an older ID to a different canonical id. |
| snapshot | string | Computed full-state approval fence returned by GET. Includes media, options and metadata. |
| state | object | |
| createdAt | string | |
| clientId | string | Stable machine principal that created the post. Absent for human-created dashboard posts. |
| surface | string | Where the post was created, independent of the principal identity. |
| approval | object | Present for approval-gated agent work, including the owner's final decision when one has been made. |
| scheduledAt | object | |
| timezone | string | IANA timezone the caller scheduled in, when they named one. |
| scheduledAtLocal | string | Wall-clock time in timezone, computed on read. Not stored. |
| text | string | |
| campaign | string | |
| assetMetadata | object | |
| media | array | |
| warnings | array | Advisory notes from create or edit, for example PNG converted to JPEG for TikTok. |
| platformOptions | object | |
| targets | array |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/postlake-dev/json-schema/postlake-dev-post-schema.json",
"title": "Post",
"x-generated": "2026-10-31",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/postlake-dev-openapi.json#/components/schemas/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": "#/$defs/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": "#/$defs/PostTarget"
}
}
},
"required": [
"id",
"state",
"createdAt",
"scheduledAt",
"text",
"media",
"platformOptions",
"targets"
],
"$defs": {
"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": "#/$defs/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"
]
},
"Platform": {
"type": "string",
"enum": [
"bluesky",
"threads",
"x",
"linkedin",
"instagram",
"tiktok",
"facebook",
"youtube",
"pinterest"
]
},
"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": "#/$defs/Platform"
},
"state": {
"$ref": "#/$defs/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": "#/$defs/NormalisedError"
},
{
"type": "null"
}
]
}
},
"required": [
"account",
"platform",
"state",
"remoteId",
"url",
"publishedAt",
"error"
]
},
"TargetState": {
"type": "string",
"enum": [
"queued",
"scheduled",
"processing",
"published",
"failed"
]
}
}
}
Work with this as data
Every JSON Schema 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 schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.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.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/postlake-dev-post"
All schemas
curl "https://apis.io/api/v1/json-schemas?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.