Agents see the plan, speak the right voice, and attach images
GET /schedule now returns per-channel cadence and the coming 14 days of the plan instead of the retired calendar slots and knobs. Channels and content items carry their voice. A draft an agent creates gets a time on the calendar. Agents can attach images from a URL, an upload, or inline bytes, and list what they uploaded.
The agent API grew up with the v3 release. This entry collects every change to
the /api/v1 contract and the Borker MCP that shipped with it, including the
ones that break a v1 shape in place under the one-release exception described
in the reference.
What changed for agents
GET /schedule and get_schedule return the v3 shape. This is a breaking
change to a v1 payload. The slots array is gone (v3 writes no calendar slots)
and so are maxPostsPerDay, minHoursBetween, queueBufferDays,
reactiveMinRelevance and autoApproveTypes, which nothing has read since the
plan compiler replaced slot placement. In their place: cadence, one row per
connected channel with how often Borker writes for it, and planned, the plan
items for the coming 14 days with the content id once a post is written.
config.matchThreshold says what a source item has to clear. An agent that
sized its week from maxPostsPerDay should read cadence.
Channels and items say which voice they speak in. GET /channels and
every content item carry voice: "personal" | "brand", resolved the way
generation resolves it. The per-voice settings in GET /schedule apply by it.
A draft an agent creates gets a time. POST /content with body (and
create_content_draft) takes an optional scheduledAt; without one the draft
takes its channel's next open time, the same rule the composer uses. The draft
still waits for review, and it now sits on the calendar at that instant, which
the response reports as scheduledAt.
Agents can attach images. POST /content and PATCH /content/:id (and
the MCP tools create_content_draft and update_content) take
media: [{ url } | { id }]. A URL is fetched server-side, validated the way
an upload from the app is, and stored; a failing image fails the whole call
with a sentence naming it, and nothing is created. Per-platform image caps are
checked at attach. POST /media takes a multipart file and returns a ready id;
POST /media/uploads (MCP request_media_upload) returns a signed, single-use
upload URL good for 15 minutes, or takes the bytes inline as base64 up to 1MB;
GET /media (MCP list_media) lists uploads not yet attached. Unattached
uploads are removed after 24 hours.
Smaller fixes from the agent-surface audit. A v1 request with no
Authorization header and no session answers 401 missing_authorization in
the v1 envelope; an unexpected failure inside a v1 route answers
500 internal_error in the same envelope. GET /brand no longer returns
examples (nothing wrote them) and no longer repeats the tagline and mission
inside aboutYou. The campaign source filter is refused like any unknown
value. Items carry topic and title. A generation that stops partway reports
the cause in one plain sentence rather than the provider's error text. The
MCP initialize answers a supported protocol version, a body that is not JSON
answers -32700, and a tool call missing a required argument is refused by
name. rate_limited_key and rate_limited_ip are in the error catalogue.
Content writes are documented as needing the editor role, which they always
did.