# Pressbotics — full capability reference > The publish rail for AI agents. A hosted WordPress MCP server. Agents send markdown; Pressbotics creates correct Gutenberg posts and reports per-component outcomes. The site owner can require approval before anything goes live. This document describes only verified, shipped behaviour. ## Connecting - MCP server URL: https://mcp.pressbotics.com/mcp - Auth: OAuth. Add the URL as a custom MCP server, sign in, click Authorize. No API key required for Claude, ChatGPT, Cursor, n8n or any other MCP client. Menu names vary by client and version. - Static pb_live_ keys remain available for custom or self-hosted agents that cannot do OAuth. Keys can be scoped to specific sites and given a monthly publish cap. ## Tools (20 — this is the entire surface) - create_connect_link: Creates a one-time link the site owner opens to connect a WordPress site. - get_connect_status: Reports whether a connect link has been completed and which site it produced. - list_sites: Lists the connected sites the caller is allowed to publish to. - get_site_context: Returns a site's handle, capabilities, categories, tags, brand voice notes and approval policy. - site_health: Re-probes a site and reports WordPress version, plugin detection and SEO capability. - list_content: Lists and filters existing posts on a site so an agent can find something to update. - list_media: Lists attachments already in the site's media library, so an existing image can be reused. - create_media_upload: Creates an upload link the person opens to hand over a file the agent cannot forward itself. - get_media_upload: Polls an upload until it is ready and returns the media_ref to pass to a publish call. - publish_post: Creates a post from markdown and publishes it (or queues it for approval). - schedule_post: Same as publish_post, plus a future publish_at timestamp. - update_post: Updates an existing post by id with new content, taxonomy, media or SEO fields. - get_post_status: Returns the current state of a submitted action, including per-component outcomes. - list_scheduled: Lists scheduled posts across the caller's sites with their times and current state. - reschedule_post: Moves a scheduled post to a new time, on WordPress as well as in Pressbotics. - cancel_scheduled: Cancels a scheduled post before it runs, reverting it to a draft on WordPress. - schedule_batch: Schedules several posts in one call — a week of content at a time. - create_recurrence: Creates a standing cadence that generates empty scheduled slots. It does not write content. - list_recurrences: Lists the cadences on a site, with their pattern, timezone and next slots. - cancel_recurrence: Stops a cadence generating further slots. Slots already created remain. ## Publish parameters Shared by publish_post, schedule_post and update_post. publish_at applies to schedule_post only. post_id applies to update_post only and is required there. - site (string): Site handle or URL. Required. - title (string): Post title — the on-page headline. Required. - markdown (string): Post body in markdown. Converted to Gutenberg blocks. Required. - excerpt (string): WordPress excerpt. Does NOT set the meta description. - categories (string[]): Category names (not ids). Matched by name or created. - tags (string[]): Tag names (not ids). Matched by name or created. - featured_image_url (string (URL)): Public URL. Downloaded and sideloaded as the featured image. - featured_image_id (number): An attachment id already in the media library. Find one with list_media. - featured_media_ref (string): A file the person uploaded through the media handoff. From get_media_upload. - seo_title (string): The title tag. Max 70 characters. Needs the companion plugin + an SEO plugin (Yoast verified; Rank Math supported, untested). - meta_description (string): The search-result description. Max 200 characters. Same plugin requirement. - focus_keyword (string): Max 120 characters. Same plugin requirement. - canonical_url (string (URL)): Canonical link for the post. - request_review (boolean): Force the post into the approval queue regardless of site policy. - idempotency_key (string): Required. Repeat calls with the same key return the original action instead of duplicating. - publish_at (ISO 8601): schedule_post only. Future publish time. - post_id (number): update_post only. The WordPress post to update. Required there. ## Featured images — three inputs, MUTUALLY EXCLUSIVE Supplying more than one of these on the same call is REJECTED. Pressbotics never silently resolves the ambiguity. - featured_image_url — A publicly reachable URL: Pressbotics downloads it and sideloads it into the media library, then sets it as the featured image. - featured_image_id — An attachment already on the site: Reuse something in the media library. Find the id with list_media. - featured_media_ref — A file the person just uploaded: Produced by the media upload handoff: create_media_upload, the person uploads, get_media_upload returns the ref. An agent CANNOT accept a file from a person and forward it as a tool argument. A pasted image is an image block the model can see, not bytes it can re-serialise. When the person has a file (a phone photo, a screenshot), use the media upload handoff below. Do not substitute a stock image. ## Media upload handoff 1. create_media_upload({ site, purpose?, note? }) -> { upload_id, upload_url, expires_at } 2. Give the person upload_url. They must be signed in to Pressbotics; the page shows which site and what the file is for. 3. Poll get_media_upload({ upload_id }) until status is "ready" (statuses: pending, ready, expired, failed). 4. Pass the returned media_ref as featured_media_ref on the publish call. - Accepted types: JPEG, PNG, GIF, WebP, AVIF — Detected from the file's magic bytes, not its extension or declared type. - Maximum size: 20 MB — Larger files are rejected before anything is stored. - Link lifetime: 60 minutes — After that the page shows an expired state and the agent must create a new link. - Unused files: Deleted within 24 hours — An uploaded file that is never used is removed. - Used files: Deleted immediately — Once the file reaches WordPress, the buffered copy is deleted. - EXIF: Stripped — Camera and GPS metadata is removed from images before storage. An upload_id belonging to another workspace behaves as if it does not exist. ## Reusing existing media list_media lists attachments already in the site's media library with their ids, filenames, MIME types and URLs. Pass an id as featured_image_id rather than re-uploading the same image. ## Finding existing posts — list_content - search (string): Free-text search across post titles and content. - category (string): Category name. - tag (string): Tag name. - status (string): Accepted, but list_content only returns published posts today. Drafts and scheduled posts are not listed. - published_after (ISO 8601 or YYYY-MM-DD): Only posts published on or after this moment. - published_before (ISO 8601 or YYYY-MM-DD): Only posts published before this moment. - order_by (date | title | modified): Sort field. - order (asc | desc): Sort direction. - page (number): 1-based page number. - limit (number): Results per page. Every result carries date and modified, which is what makes "the post I published last Tuesday" resolvable. Use list_content to find a post_id, then update_post to change it. Agents should OFFER to edit an existing post rather than always publishing a new one. ## Markdown to Gutenberg — complete block list - Paragraphs - Headings H1–H6 - Bold, italic and links - Bulleted lists - Numbered lists - Blockquotes - Pullquotes (:::pullquote) - Fenced code blocks - Tables - Horizontal rules / separators - Images, with an optional caption - Galleries (:::gallery) - Cover blocks (:::cover) - Columns (:::columns) - Groups (:::group) - Embeds from supported providers - Self-hosted video files - Self-hosted audio files Inline images — including cover and gallery images — are downloaded and re-hosted in the site's media library. ### Composite blocks via ::: directives Written inside the `markdown` parameter. Each opens with `:::name` on its own line and closes with `:::` on its own line. - :::cover -> wp:cover: Full-bleed hero with the enclosed content overlaid. The hero image is uploaded to the media library like any other image. - :::pullquote -> wp:pullquote: A large decorative quote, distinct from a normal > blockquote. A second paragraph inside becomes the citation. - :::gallery -> wp:gallery: One image per line — markdown image syntax or a bare URL. Produces a gallery with nested images, all uploaded. - :::columns -> wp:columns: Columns separated by a line containing only ---. Markdown inside each column is compiled normally. - :::group -> wp:group: A grouped section. Worked example: ```markdown :::cover https://cdn.example.com/hero.jpg # Inside the launch of Orbit 2.0 A year of work, in one release. ::: Orbit 2.0 is the biggest release we have shipped. :::pullquote We stopped optimising the old thing and rebuilt the loop. Ana Reyes, Head of Product ::: ![The new dashboard](https://cdn.example.com/dash.png "The redesigned dashboard, shipped in 2.0") :::gallery ![Editor](https://cdn.example.com/g1.jpg) https://cdn.example.com/g2.jpg ![Timeline](https://cdn.example.com/g3.jpg) ::: :::columns ### Faster Builds are 3x quicker. --- ### Simpler One screen instead of four. ::: https://www.youtube.com/watch?v=dQw4w9WgXcQ https://cdn.example.com/walkthrough.mp4 ``` ### Image captions `![alt text](https://example.com/photo.jpg "This becomes the caption")` Markdown's title argument becomes a real WordPress figcaption. Without a title argument no caption is rendered. This is the ONLY way to caption an image. ### Self-hosted video and audio A bare link on its own line to a media FILE becomes a real player, not a link or an embed card. - Video: .mp4 .webm .ogv .mov .m4v -> wp:video - Audio: .mp3 .wav .m4a .ogg .oga .flac -> wp:audio ### Embeds A bare link on its own line to a supported provider becomes wp:embed. Supported providers: - YouTube - Vimeo - TikTok - Spotify - SoundCloud - Wistia Any other URL stays an ordinary paragraph/link. Embedding is not universal. Pressbotics creates the embed block; WordPress resolves it with the provider. Twitter/X and Instagram have retired their oEmbed endpoints, so those URLs do not render as cards. When resolution fails the post still publishes and embed_status is "partial" with the provider's error. Verified rendering on a live site: YouTube, Spotify, TikTok. list_content can see drafts and scheduled posts as well as published ones, via the rail's authenticated read. Post ids come back as wp_post_id. idempotency_key is REQUIRED on publish_post, schedule_post and update_post. ## Response contract — partial success Every executed publish, schedule or update reports per-component outcomes. A post can publish while a component fails; this is reported, not hidden. Read these fields before reporting success to your user — a post can go live without its featured image, and the response will say so. - state (queued | published | scheduled | failed | rejected | reverted): What happened to the post itself. Everything below describes its components. - partial (boolean): True when the post landed but at least one component did not. - image_status (none | ok | failed): Featured image outcome. - image_error (string): Why the featured image failed, when it did. - taxonomy_status (none | ok | partial | failed): Categories and tags outcome. - taxonomy_error (string): Which terms could not be applied. - seo_status (none | ok | unsupported): Whether SEO meta was actually written. - seo_error (string): Which piece is missing when seo_status is "unsupported". - embed_status (none | ok | partial | failed): Whether provider embeds resolved. A provider that will not embed stays a plain link and the post still publishes. - embeds (array): The embed URLs found and what each became. - inline_images ({ total, failed, errors }): Inline image re-hosting. An image that cannot be fetched is REMOVED from the post body and listed in errors; the post still publishes. - post_url (string (URL)): The live post URL, once it exists. - render_check (pass | fail | not_yet): pass: the live post was fetched and rendered correctly. fail: it did not, and the post was reverted to draft. not_yet: a scheduled post that is not public yet — the scheduler verifies it when it goes live and writes pass or fail then. render_check "pass" means the live post was fetched and rendered correctly. "fail" means it did not and the post was reverted to draft. "not_yet" means a scheduled post that is not public yet — the scheduler verifies it when it goes live and writes pass or fail onto the action then. A failed inline image is REMOVED from the post body and reported in inline_images.errors; the post still publishes. An embed provider that will not resolve stays a plain link; the post still publishes. get_post_status returns the same fields for a previously submitted action. ## SEO contract Every publish/schedule/update response returns seo_status: - none: No SEO fields were requested on the call. Nothing to write. - unsupported: SEO fields were requested but the site cannot write them. seo_error names the missing piece: the Pressbotics companion plugin, or a supported SEO plugin. - ok: The site is capable and the SEO meta was actually written. Requires the companion plugin AND an SEO plugin. Yoast is verified end to end on a live site; Rank Math is supported but has not been tested. Only the active plugin's meta keys are written. - Requirements for "ok": the free Pressbotics companion plugin AND an SEO plugin. Yoast is verified end to end on a live site; Rank Math is supported but has NOT been tested. Only the active plugin's meta keys are written. Other SEO plugins return "unsupported". - Field distinctions: post title is the headline (H1). seo_title is the title tag (max 70). excerpt is the on-site summary. meta_description is the search-result description (max 200). The excerpt does NOT set the meta description. focus_keyword is max 120 and follows the same plugin requirement. ## Taxonomy - categories and tags are passed as names, not ids. Existing terms are matched by name; missing ones are created. Call get_site_context first and reuse existing terms. ## Scheduling — the seven scheduler tools - list_scheduled - parameters: site (optional), from / to (ISO 8601, optional), status (optional), page, limit - returns: Scheduled posts with schedule_id, title, site, publish_at (absolute UTC), status (scheduled, published, cancelled, missed) and wp_post_id where known. - reschedule_post - parameters: schedule_id (required), publish_at (ISO 8601 with offset, required) - returns: The updated row. Pressbotics only records the move after WordPress confirms it; a failure returns a code such as wp_reschedule_unverified and changes nothing. - cancel_scheduled - parameters: schedule_id (required) - returns: The cancelled row. The WordPress post reverts to a draft. Cancelling an already-cancelled item returns already_cancelled rather than issuing a second call. - schedule_batch - parameters: site (required), posts[] — each an ordinary schedule_post payload with its own publish_at - returns: One result per item, each with its own action id and outcome. Items are independent: one can fail while the rest schedule. - create_recurrence - parameters: site, days_of_week, time_of_day, timezone, ends_on — see the table below - returns: The cadence, plus the slots generated for the horizon ahead. - list_recurrences - parameters: site (optional) - returns: Each cadence with its id, pattern, timezone, end date and whether it is active. - cancel_recurrence - parameters: recurrence_id (required) - returns: The cancelled cadence. Future slots stop being generated; slots already scheduled are untouched and must be cancelled individually. - Scheduling, batching and recurrence require a paid plan. On Free these tools return plan_upgrade_required with the plan name, price and upgrade link. Relay it; do not retry. - schedule_post creates a NATIVE WordPress scheduled post. It appears in wp-admin as Scheduled and WordPress publishes it. Pressbotics is not a second publishing engine. - publish_at must be a future ISO 8601 timestamp WITH timezone information (Z or an explicit offset). A naive timestamp with no timezone is REJECTED, not guessed. - The absolute instant is authoritative. Pressbotics also sends the matching site-local time when the site's WordPress timezone is known; when it is unknown it sends the absolute time only and lets WordPress derive the local value. - reschedule_post and cancel_scheduled only record the change after WordPress confirms it. An unverified change returns wp_reschedule_unverified / wp_cancel_unverified and nothing is changed locally. Cancelling twice returns already_cancelled. - On a site under review, a scheduled post waits in the approval queue first. Approval is what sends it to WordPress. An approval after publish_at cannot go back in time. - Missed schedules: WordPress cron depends on site traffic and can silently miss a scheduled post. Pressbotics checks each post around its due time, prompts the site to run its schedule, reads the post back to confirm publication, and marks it missed if it did not land. The owner recovers it with a one-tap publish-now in the dashboard schedule view. ## Recurrence — create_recurrence A recurrence schedules SLOTS, not content. It does NOT write posts and never invents any. The pattern is: create the cadence, then fill its slots with schedule_batch. create_recurrence takes FLAT fields: - site (string): Site handle or URL. Required. - days_of_week (number[]): 0 = Sunday through 6 = Saturday. Required. [1,3,5] is Monday, Wednesday, Friday. - time_of_day ("HH:MM"): 24-hour local time in the timezone below, e.g. "09:00". Required. - timezone (IANA timezone): REQUIRED — e.g. "America/New_York". There is no default and no guess. - ends_on (YYYY-MM-DD): Optional. Without it the cadence runs until you cancel it. - days_of_week uses 0 = Sunday through 6 = Saturday. Do NOT send a nested rule object. - timezone is REQUIRED and must be an IANA name. time_of_day is a wall-clock time and is meaningless without it; a cadence with no timezone is rejected, not guessed. - Slots are generated roughly three months ahead and topped up over time. Each slot is an ordinary scheduled post and can be moved or cancelled individually. - list_recurrences lists cadences; cancel_recurrence stops future slots. Slots already scheduled remain and must be cancelled with cancel_scheduled. - A cadence stops generating once the account is paused or the site is removed. ## Plans and limits Posts are a fair-use ceiling, not the value metric. What a plan buys is sites, agent keys and capability. - Free (free): 1 sites, 1 agent keys, 10 published posts per month. Includes: review-before-publish only. - Pro ($29/month): 3 sites, 5 agent keys, 150 published posts per month. Includes: Scheduling and recurrence, Media upload handoff. - Studio ($79/month): 10 sites, 20 agent keys, 600 published posts per month. Includes: Scheduling and recurrence, Media upload handoff. - Agency ($199/month): 30 sites, Unlimited agent keys, 2,000 published posts per month. Includes: Scheduling and recurrence, Media upload handoff. - Scale: custom volume and terms, contact us. Scheduling, recurrence and the media upload handoff require Pro or above. On a plan without them the internal endpoints return plan_upgrade_required with a message naming the plan, its price and the upgrade link — relay it to the person rather than retrying. ## Idempotency - Pass idempotency_key on publish calls. A repeat call with the same key returns the original action instead of publishing twice. ## Approval model - Each site has an approval policy: review everything, guardrails (first few publishes reviewed, blocked terms held), or full auto. - request_review forces review for a single call. - Action states: queued, published, published (partial), scheduled, failed (system error), rejected (declined by a person), reverted (published but failed its render check). ## Errors - plan_upgrade_required — cause: The workspace plan does not include the capability being called — scheduling, recurrence or the media upload handoff on the Free plan. Fix: Read the message out to the person: it names the plan that includes the capability, its price and the upgrade link. Do not retry; the same call is refused until the plan changes. - monthly_post_cap_reached — cause: The workspace has used every published post included in its plan this month. Fix: Relay the message, which states the cap, that the allowance resets on the 1st (UTC), and the upgrade link. Retrying is refused until then. - key_monthly_cap_reached — cause: The agent key itself has a monthly publish cap set by the site owner and has reached it. Fix: Ask the owner to raise or clear the cap on that key in Agents & Keys, or use a different key. - media_not_found — cause: featured_image_id points at an attachment that does not exist on that site, or a media_ref that was never produced. Fix: Call list_media and use an id from the result, or run the upload handoff again. - media_not_an_image — cause: The uploaded or referenced file is not one of the accepted image types once its bytes are inspected. Fix: Upload a real JPEG, PNG, GIF, WebP or AVIF. Renaming a file does not change what it is. - ambiguous image input — cause: More than one of featured_image_url, featured_image_id and featured_media_ref was supplied. Fix: Send exactly one. Pressbotics rejects the call rather than guessing which you meant. - upload expired — cause: get_media_upload returns status "expired": the 60-minute window elapsed, or the file was never uploaded. Fix: Call create_media_upload again and give the person the new link. - wp_auth_failed — cause: WordPress did not authenticate the stored credential at all — usually a revoked Application Password, or an email address used where the username was required. Fix: Reconnect the site in the dashboard and create a fresh Application Password. This is the only error that means reconnect. - wp_permission_denied — cause: WordPress found the post and authenticated the credential, but the connected user is not allowed to edit that post. A WordPress role or ownership problem. Fix: Give the connected WordPress user a role that can edit the post (Editor or above), or connect as a user who can. Do NOT reconnect the site — the credential is working. - wp_not_found — cause: The target does not exist on the site: an update_post post_id that was deleted or never existed, or a REST route the site does not serve. Fix: Confirm the post id with list_content. If the REST API is disabled, re-enable it. - wp_schedule_unverified — cause: WordPress did not hold the post as "future" at the exact requested instant, so the schedule was not trusted. The post was reverted to draft. Fix: Check the site's own clock and timezone, then schedule again. Nothing is left scheduled — the post is a draft on the site. - wp_publish_unverified — cause: WordPress did not report the post as "publish" after an immediate publish, so publication was not trusted. The post was reverted to draft. Fix: Run site_health, then publish again. The content is safe as a WordPress draft. - ambiguous_publish_at — cause: publish_at carried no timezone information, so the intended instant is unknowable. Fix: Send an ISO 8601 timestamp with an offset (2026-09-20T15:30:00-04:00), or a naive time plus an explicit IANA timezone. Nothing is guessed. - nonexistent_local_time — cause: The local time requested does not exist — it falls in the hour a clock-forward DST change skips. Fix: Pick a time outside the gap, or send an explicit UTC offset so the instant is unambiguous. - ambiguous_local_time — cause: The local time requested happens twice — it falls in the hour a clock-back DST change repeats. Fix: Send an explicit UTC offset to say which of the two you meant. - invalid_calendar_date — cause: The date does not exist: 31 November, 30 February, or a non-leap 29 February. Fix: Send a real calendar date. - invalid_utc_offset — cause: The offset in the timestamp is not a real UTC offset. Fix: Use an offset between -14:00 and +14:00, or an IANA timezone name. - site_timeout — cause: WordPress accepted the request but did not answer in time. Common on shared hosting with large image sideloads. Fix: Retry with the same idempotency_key. Use a smaller image if it recurs. - site_unreachable — cause: The site could not be contacted at all: DNS failure, TLS failure, firewall, or an address that is not publicly routable. Fix: Check the site is up over HTTPS from the public internet, then run site_health. - seo_status: unsupported — cause: SEO fields were requested on a site without both the companion plugin and an SEO plugin (Yoast, verified; Rank Math, supported but untested). Fix: Install both, then run site_health. The post itself still published. ## Site requirements - WordPress 6.0+, PHP 7.4+, REST API enabled, HTTPS (Application Passwords are disabled over plain HTTP), publicly reachable. - WordPress.com on lower plans cannot install plugins or use Application Passwords; a self-hosted site is required. ## Out of scope by design Pressbotics does not: - Managing WordPress users - Changing site settings - Installing, activating or configuring plugins - Changing or editing themes - Running WordPress core updates It is a publishing rail. A compromised agent can post something you can revert; it cannot take over the site. ## Documentation - https://pressbotics.com/docs/what-is-pressbotics — What is Pressbotics: What it is, what it is not, and how the approval model works. - https://pressbotics.com/docs/quickstart — Quickstart: Connect an agent in four clicks with OAuth, then publish. - https://pressbotics.com/docs/chatgpt — Connecting ChatGPT: Add the server URL as a custom MCP server and authorize. - https://pressbotics.com/docs/cursor — Connecting Cursor: Same OAuth server URL, added in Cursor's MCP settings. - https://pressbotics.com/docs/n8n — Connecting n8n: Wire the MCP server into a workflow for scheduled publishing. - https://pressbotics.com/docs/any-mcp-client — Any MCP client: One URL, OAuth, no key — the shape that works everywhere. - https://pressbotics.com/docs/agent-keys — Agent keys: The pb_live_ path for custom agents that cannot do OAuth. - https://pressbotics.com/docs/connect-your-site — Connect your site: The wizard, and both connection paths. - https://pressbotics.com/docs/application-passwords — Application Passwords: How to create one — and the username trap that catches everyone. - https://pressbotics.com/docs/wordpress-plugin — The WordPress plugin: What it adds, why SEO needs it, and how to install it. - https://pressbotics.com/docs/yoast-rankmath — Yoast and Rank Math: What each needs, and why only the active plugin's fields are written. - https://pressbotics.com/docs/supported-versions — Supported WordPress versions: WordPress 6.0+, PHP 7.4+, REST enabled, HTTPS, self-hosted. - https://pressbotics.com/docs/publishing — Publishing: Markdown to Gutenberg: blocks, ::: directives, captions, media, taxonomy and idempotency. - https://pressbotics.com/docs/seo-fields — SEO fields: The seo_status contract, and seo_title vs title vs excerpt vs meta_description. - https://pressbotics.com/docs/images — Images: Three ways in, mutually exclusive — and why an agent can't take your file. - https://pressbotics.com/docs/media-uploads — Media uploads: The handoff for a file only you can supply — phone photo to post. - https://pressbotics.com/docs/embeds — Embeds, video and audio: Bare URLs that become players and embed cards — and the ones that don't. - https://pressbotics.com/docs/scheduling — Scheduling: schedule_post, batches, moving and cancelling — and the timezone rule. - https://pressbotics.com/docs/schedule-calendar — The schedule calendar: One calendar across every site, and what happens when WordPress misses one. - https://pressbotics.com/docs/recurring-schedules — Recurring schedules: A cadence generates slots, not content. Fill them with schedule_batch. - https://pressbotics.com/docs/updating-a-post — Updating a post: Find it with list_content, change it with update_post. - https://pressbotics.com/docs/taking-a-post-back — Taking a post back: Unpublish keeps the draft. Restoring writes a new edit, it does not rewind history. - https://pressbotics.com/docs/site-context — Site context: The call an agent should make before its first publish. - https://pressbotics.com/docs/approval-policies — Approval policies: Review everything, guardrails, or full auto — per site. - https://pressbotics.com/docs/the-approval-queue — The approval queue: What you see, what approving does, and how you hear about it. - https://pressbotics.com/docs/brand-voice-notes — Brand voice notes: Write the rules once per site; every agent reads them. - https://pressbotics.com/docs/reverting — Reverting and the render check: The post-publish render check, and how to undo something. - https://pressbotics.com/docs/plans-and-limits — Plans and limits: Sites, keys, monthly posts and which policies each plan unlocks. - https://pressbotics.com/docs/usage-and-caps — Usage and caps: What counts, where to see it, and what happens at the ceiling. - https://pressbotics.com/docs/managing-sites-and-keys — Managing sites and keys: Connect, scope, name and prune — before you have thirty of each. - https://pressbotics.com/docs/revoking-access — Revoking access: How to cut something off, in the right order. - https://pressbotics.com/docs/deleting-your-account — Deleting your account: What is removed, what isn't, and how to do it. - https://pressbotics.com/docs/exporting-your-data — Exporting your data: One JSON file of everything we hold about your workspace. - https://pressbotics.com/docs/how-credentials-are-stored — How credentials are stored: AES-256-GCM, a key only the rail holds, and never in a response. - https://pressbotics.com/docs/workspace-isolation — Workspace isolation: The tenant boundary, key scoping, and the blast radius. - https://pressbotics.com/docs/two-factor-authentication — Two-factor authentication: TOTP on your account, and what it gates. - https://pressbotics.com/docs/responsible-disclosure — Responsible disclosure: Found something? Here is how to tell us. - https://pressbotics.com/docs/troubleshooting — Troubleshooting: Connection failures, plugin not detected, missing images, partial success. - https://pressbotics.com/docs/tool-reference — Tool reference: All 20 tools, their parameters and what they return. - https://pressbotics.com/docs/error-reference — Error reference: Every error you are likely to hit, with the cause and the fix. - https://pressbotics.com/docs/changelog — Changelog: What has shipped, newest first.