B
Documentation

Bredgio API · v0

Programmatic control plane for Bredgio agents. Use it to create agents, dispatch posts and comments, schedule recurring runs, and observe execution in realtime.

Field Value
Base URL https://bredgio.letmesee.cc
WebSocket wss://bredgio.letmesee.cc/api/social-agents/ws
Format JSON (UTF-8)
Auth PAT — Authorization: Bearer bk_pat_...
Stability Pre-release — shapes may change

Architecture in 30 seconds

 ┌──────────────┐       HTTP        ┌──────────────┐    Mongo    ┌──────────┐
 │  Dashboard   │  ─────────────►   │  Bredgio API │ ──────────► │ MongoDB  │
 │ (Svelte UI)  │  ◄─────────────   │  (SvelteKit) │             └──────────┘
 └──────────────┘                   └──────┬───────┘
                                           │ enqueue task
                                           ▼
                                    ┌──────────────┐    wss     ┌──────────────┐
                                    │  WS Hub      │ ◄────────► │  Extension   │
                                    │ (Node + ws)  │  commands  │ (Chrome MV3) │
                                    └──────────────┘            └──────────────┘

The dashboard talks to the HTTP API. The HTTP API persists tasks to MongoDB. The WebSocket hub claims pending tasks, expands them into a sequence of atomic commands (navigate, click, type, …) and ships them to the agent's Chrome extension over a single long-lived socket. Results stream back the same way and are merged into the task log.

What you can do with the API

The API exposes every dashboard resource as a programmable endpoint — so you can drop Bredgio into any workflow, any scheduling system, any AI assistant. Common uses:

  • Manage agents programmatically — list, create, reconfigure, deactivate, rotate tokens.
  • Dispatch posts on demand — pass a string of content, the API drops a task to the named agent's browser and returns the live post URL when it lands.
  • Build recurring schedules — one-off, daily, weekly, cron. A built-in worker fires schedules at their nextRunAt so you don't run your own cron.
  • Track execution in realtime — poll GET /api/tasks/:id to see each step's log entry; on failure you get a structured errorCode telling you whether it was an FB login issue, a missing button, or a timeout.
  • Pull analyticsGET /api/logs returns the outreach event stream (sent / failed / skipped) with daily roll-ups, ready for BI tools.
  • Hand the wheel to AI — the official MCP server lets Claude, Cursor, or Cline dispatch tasks for you in natural language, no code required.

What you do not need: the login endpoint. /api/auth/* exists for the dashboard web UI — external callers only need a Personal Access Token (PAT) and never have to touch cookies, sessions, or passwords.

Quick start

You'll need a PAT, an agent, and a browser with the extension installed. Five minutes, end to end.

1 · Mint a PAT in the dashboard (one-time setup)

Open the dashboardSettings → API Keys → + New PAT. Copy the generated bk_pat_... and stash it in a password manager. The full token is shown only once.

PAT issuance requires a Pro plan or above. See Plan gate.

2 · Create an agent

curl -X POST https://bredgio.letmesee.cc/api/agents \
  -H 'Authorization: Bearer bk_pat_...' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Marketing seat #1","platforms":["facebook"]}'

The response includes agent.token — a long hex string the extension uses to authenticate (different from your PAT). It's returned in full only on creation and on explicit reveal / regenerate. Save it now.

3 · Install the extension on the operator's machine

Open the Chrome Web Store listing and click Add to Chrome. After install, click the Bredgio toolbar icon, paste the agent token from step 2, and hit Save & Connect — the agent comes online within a few seconds.

Environments that can't reach the Chrome Web Store (intranets, blocked by enterprise policy) can sideload instead: download https://bredgio.letmesee.cc/bredgio-extension.zip?v=<version>, unzip, open chrome://extensions, enable Developer mode, and Load unpacked.

4 · Dispatch a post

curl -X POST \
  https://bredgio.letmesee.cc/api/agents/<agentId>/command \
  -H 'Authorization: Bearer bk_pat_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "action": "post",
    "platform": "facebook",
    "params": { "content": "Hello, world!\nFrom Bredgio." }
  }'

You'll get back task.taskId. Poll GET /api/tasks/<taskId> to watch status transition through pending → dispatched → running → completed, or open https://bredgio.letmesee.cc/dashboard/tasks/<taskId> in the dashboard to follow the live log.

Authentication

External callers always use PAT — one token, every endpoint, no login flow needed. Session cookies and agent tokens are used by Bredgio's own components (dashboard UI, Chrome extension) and don't come up in typical API usage.

Caller Scheme Where it goes
Your code / automation / MCP server / CI Personal Access Token (PAT) Authorization: Bearer bk_pat_…paid plans only
Dashboard web UI (internal) Session cookie Set by POST /api/auth/login. External callers should ignore this endpoint.
Chrome extension (internal) Agent token WebSocket ?token=… or heartbeat body.

Plan gate — PAT issuance is paid

Programmatic access via PAT is only available on the Pro plan and above. Free-plan accounts can use the dashboard normally but the Settings → API Keys → New PAT button is disabled, and the bredgio-mcp server will refuse to start without a PAT.

Plan Dashboard Extension (agent token) PAT issuance MCP server
Free
Pro
Team / Enterprise ✅ (multi-seat)

Attempting to mint a PAT on a Free plan returns:

{
  "success": false,
  "error": "Upgrade to Pro to enable API access",
  "errorCode": "plan_upgrade_required",
  "upgradeUrl": "https://bredgio.letmesee.cc/dashboard/billing"
}

Existing PATs continue working through the end of the current billing period if you downgrade — after that they auto-revoke and return 401 plan_downgraded on every call.

Personal Access Token (PAT) — primary for external use

PATs look like bk_pat_3dd2104b9144794e76ff437f655784bb. Every endpoint in this document accepts a PAT via the Authorization: Bearer … header — same authority as the user has in the dashboard.

  • Mint — Dashboard → Settings → API Keys → + New PAT. The full token is shown once, at creation.
  • Revoke — Same panel, Revoke button. Effective immediately; subsequent calls return 401 invalid_key.
  • Scope — Account-wide. Can do anything the user can do in the dashboard except mint or revoke other PATs (UI-only).
  • Plan gate — Requires Pro or higher (see table above).

Treat PATs like passwords: store them in a secrets manager, never commit to source control, rotate on suspected leak.

Agent token — Chrome extension only

Each agent has its own token (server-minted via randomBytes(32).toString('hex'), 64 hex chars) which the extension uses to authenticate against the WebSocket hub. This is not the token your code should send to the API — your code uses a PAT; agent tokens live inside the extension popup.

  • RevealReveal button on the dashboard agent page, or GET /api/agents/:id/token via the API.
  • RegenerateRegenerate button (requires the account password); also POST /api/agents/:id/token with the password. The previous token is invalidated immediately and any extension session using it disconnects.

The cookie is a signed JWT containing { userId, email, name, plan }. It is HttpOnly, Secure, SameSite=Lax, and set by POST /api/auth/login. It only exists to support the dashboard's own web UI — external code should use a PAT and never call /api/auth/*.


Endpoints

Endpoint groups, in the order you'd usually need them.

Auth

POST /api/auth/login

Exchange email + password for a session cookie.

Body

Field Type Required Notes
email string yes Case-insensitive.
password string yes

Response — 200 OK

{
  "success": true,
  "user": {
    "id": "65fc...",
    "email": "[email protected]",
    "name": "Lucien",
    "plan": "free"
  }
}

Sets Set-Cookie: bredgio_session=<jwt>; HttpOnly; Secure; SameSite=Lax.

Errors400 (missing fields), 401 (invalid credentials), 500.

POST /api/auth/logout

Clears the session cookie. Always returns { "success": true }.

PATCH /api/auth/profile

Update mutable fields on the currently logged-in user. Re-issues the session cookie so the new claims are reflected.

Body

Field Type Required Notes
name string no Trimmed.

Response — 200 OK — same shape as /login.


Agents

An agent is a (human operator, browser profile) pair on a partner's machine. Each agent has its own token, status (online / offline / paused), and per-day usage counters.

GET /api/agents

List every agent owned by the authenticated user, including a todayCount of tasks dispatched in the last 24h.

Response — 200 OK

{
  "success": true,
  "agents": [
    {
      "agentId": "65fc...",
      "name": "Marketing seat #1",
      "userId": "65f0...",
      "userEmail": "[email protected]",
      "status": "online",
      "platforms": ["facebook"],
      "config": { "dailyOutreachLimit": 5, "messageDelaySec": 30, "postDelaySec": 60 },
      "lastSeenAt": "2026-05-18T03:14:15.000Z",
      "extensionVersion": "0.2.1",
      "todayCount": 7
    }
  ]
}

POST /api/agents

Create a new agent and mint its token.

Body

Field Type Required Notes
name string yes Free-form label.
platforms string[] no Subset of facebook, twitter, instagram, linkedin, threads. Defaults to [].

Response — 200 OK

{
  "success": true,
  "agent": {
    "agentId": "65fc...",
    "name": "Marketing seat #1",
    "platforms": ["facebook"],
    "token": "7c4d9f8e3b21…",
    "...": "other fields as in /api/agents"
  }
}

token is only present on creation. Save it now.

GET /api/agents/:id

Detailed view, including the 20 most recent tasks and outreach log entries.

Response

{
  "success": true,
  "agent": { /* same as list */ },
  "recentTasks": [ /* Task objects, see below */ ],
  "recentLogs":  [ /* OutreachLog objects */ ],
  "todayCount": 7
}

PATCH /api/agents/:id

Update mutable fields. Pass only the keys you want to change.

Body (all optional)

Field Type Notes
name string
platforms string[] Replaces the array.
status online · offline · paused Manual override; usually you let the heartbeat manage this.
config.dailyOutreachLimit number
config.messageDelaySec number
config.postDelaySec number

Response — 200 OK{ success: true, agent }.

DELETE /api/agents/:id

Soft-delete the agent. Returns { success: true }.

GET /api/agents/:id/token

Reveal the current agent token. Owner-only.

{ "success": true, "token": "7c4d9f8e3b21…" }

POST /api/agents/:id/token

Rotate the agent token. Requires the user's password in the body — this is a sensitive operation that invalidates every running extension session on that agent.

Body

Field Type Required Notes
password string yes The authenticated user's account password.

Response — 200 OK

{ "success": true, "token": "new-token-here…" }

Errors400 passwordRequired, 401 Incorrect password, 403 Forbidden.

POST /api/agents/:id/command

Dispatch a task to the agent. This is the main work-creating endpoint.

Body

Field Type Required Notes
action enum yes See Task actions.
platform enum yes One of facebook, twitter, instagram, linkedin, threads. facebook and twitter (covers x.com) are shipped end-to-end today; the rest are planned.
params object yes Action-specific. See per-action shapes below.
scheduledFor ISO 8601 no Future timestamp. If omitted, the task is claimed immediately. Past timestamps are rejected with 400.

Response — 200 OK

{
  "success": true,
  "task": {
    "taskId": "65fc...",
    "action": "post",
    "status": "pending",
    "dispatchedAt": "2026-05-18T03:14:15.000Z",
    "scheduledFor": null
  }
}
Task actions
Value Platform Status params shape
post facebook, twitter shipped { "content": "string (newlines preserved)", "media": [{ "url": "…", "type": "image/jpeg" }] }
post-to-groups facebook shipped { "topic": "…", "content": "…", "maxGroups": 5, "intervalSec": 300 }
comment planned { "postUrl": "…", "content": "…" }
comment-feed planned { "feedUrl": "…", "content": "…" }
fetch-posts planned { "feedUrl": "…", "limit": 10 }
search planned { "query": "…" }
smart-post planned { "topic": "…", "tone": "…" }
smart-comment planned { "postUrl": "…", "stance": "…" }
friend-msg planned { "userId": "…", "content": "…" }
send-msg planned { "threadId": "…", "content": "…" }
group-outreach planned { "groupUrl": "…", "template": "…" }
auto-outreach planned { "policyId": "…" }

The validator accepts every action above today. Three flows are registered server-side: facebook + post, facebook + post-to-groups, and twitter + post (covers x.com). Other combinations dispatch successfully but fail at execution time with code: action_not_implemented.

Attaching images: params.media

media is an optional array on the post action. Each entry is { url, type }:

  • url — a URL that's publicly fetchable. The simplest path is to call POST /api/media/upload first and pass the returned url back unchanged; it points at Bredgio's own /api/media-proxy/<key> route which the agent's Chrome extension can fetch directly (host_permissions already cover it). External URLs work too, but only if they require no auth and don't block the extension with CORS / referer restrictions.
  • type — MIME. Supported: image/jpeg, image/png, image/webp, image/gif.

Array order = Facebook attachment order. Empty or omitted = text-only post. Video and reels are not supported.

curl -X POST \
  https://bredgio.letmesee.cc/api/agents/<agentId>/command \
  -H 'Authorization: Bearer bk_pat_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "action": "post",
    "platform": "facebook",
    "params": {
      "content": "Today’s new menu 🍣",
      "media": [
        { "url": "/api/media-proxy/bredgio/usr_…/abc.jpg", "type": "image/jpeg" },
        { "url": "/api/media-proxy/bredgio/usr_…/def.jpg", "type": "image/jpeg" }
      ]
    }
  }'

POST /api/media/upload

Upload an image to Bredgio's R2 storage. Upload once, then re-use the returned url across as many params.media entries as you need.

Bodymultipart/form-data

Field Type Required Notes
file file yes JPG / PNG / WebP / GIF, 10 MB max per file.

Response — 200 OK

{
  "success": true,
  "url": "/api/media-proxy/bredgio/usr_…/1748000000000-a1b2.jpg",
  "directUrl": "https://img.casinoarticle.top/bredgio/usr_…/1748000000000-a1b2.jpg",
  "key": "bredgio/usr_…/1748000000000-a1b2.jpg",
  "type": "image/jpeg",
  "size": 482103
}
  • url — the proxy URL. This is what you pass back into params.media[].url. Relative path, served from Bredgio's own origin.
  • directUrl — the R2 CDN URL. Useful for frontends that want fast thumbnails; external API callers can ignore it.
  • key — internal R2 key, reserved for a future delete endpoint.

Errors

Status error
400 file is required / Empty file / Unsupported type: …
401 Not authenticated — missing or invalid token
413 File too large (max 10MB)
500 Storage not configured — server .env missing R2 variables
curl -X POST \
  https://bredgio.letmesee.cc/api/media/upload \
  -H 'Authorization: Bearer bk_pat_...' \
  -F file=@./post-image.jpg

Tasks

A task is one unit of work. It starts at pending, gets claimed by the hub (dispatched), executes step by step (running), and ends in completed, failed, or cancelled.

GET /api/tasks

List tasks owned by the caller.

Query

Param Type Default Notes
agentId string Filter to one agent.
status enum pending, dispatched, running, completed, failed, cancelled.
limit number 50 Max 200.

Response — 200 OK

{
  "success": true,
  "tasks": [
    {
      "taskId": "65fc...",
      "agentId": "65f0...",
      "action": "post",
      "platform": "facebook",
      "status": "completed",
      "dispatchedAt": "2026-05-18T03:14:15.000Z",
      "startedAt":    "2026-05-18T03:14:16.123Z",
      "completedAt":  "2026-05-18T03:14:32.001Z",
      "scheduledFor": null,
      "currentStep": null,
      "errorCode": null,
      "result": { "post": { "url": "https://www.facebook.com/.../posts/123" } }
    }
  ]
}

GET /api/tasks/:id

Single-task detail including the full step log.

Response — 200 OK

{
  "success": true,
  "task": {
    "taskId": "65fc...",
    "...": "all fields from the list endpoint",
    "params": { "content": "Hello, world!" },
    "log": [
      { "ts": "...", "step": "navigate",        "status": "ok"    },
      { "ts": "...", "step": "click_compose",   "status": "ok"    },
      { "ts": "...", "step": "type_content",    "status": "ok"    },
      { "ts": "...", "step": "submit",          "status": "ok"    },
      { "ts": "...", "step": "extract_post_url","status": "ok", "data": { "url": "..." } }
    ]
  }
}

Errors403 Forbidden if the caller does not own the task.

Task log entries
Field Type Notes
ts ISO 8601 When the entry was appended.
step string Slug of the current step (e.g. click_compose, submit).
status info · ok · warn · error
message string Free text — usually empty on ok.
data object Step-specific payload, e.g. the captured url for extract_post_url.
errorCode string Present when status === 'error'. See Error codes.

Schedules

A scheduled post materialises into one or more dispatched tasks according to a frequency rule. Schedules are stored separately from tasks; a background worker (running in the WS hub process) wakes every few seconds, finds due schedules, and calls the same dispatch path as /api/agents/:id/command.

GET /api/schedules

Query

Param Type Default Notes
agentId string
status enum active, paused, completed, cancelled.
limit number 100

Response

{
  "success": true,
  "schedules": [
    {
      "scheduleId": "65fc...",
      "agentId": "65f0...",
      "platform": "facebook",
      "content": "Good morning, world.",
      "frequency": "daily",
      "runAt": null,
      "timeMinutesUTC": 540,
      "dayOfWeek": null,
      "cronExpr": null,
      "timezone": "Asia/Taipei",
      "status": "active",
      "nextRunAt": "2026-05-19T09:00:00.000Z",
      "lastRunAt": "2026-05-18T09:00:00.000Z",
      "createdAt": "2026-05-10T12:00:00.000Z"
    }
  ]
}

POST /api/schedules

Create a schedule.

Body

Field Type Required Notes
agentId string yes Must be owned by the caller.
platform enum yes See platform enum.
content string yes The post body. Newlines preserved.
frequency oneoff · daily · weekly · cron yes See Schedule semantics.
runAt ISO 8601 conditional Required when frequency=oneoff.
timeMinutesUTC number 0–1439 conditional Required when frequency=daily or weekly.
dayOfWeek number 0–6 conditional Required when frequency=weekly. 0=Sunday.
cronExpr string conditional Required when frequency=cron. 5-field cron.
timezone IANA string no Informational; server normalises to UTC.

Response — 200 OK

{ "success": true, "schedule": { /* full doc */ } }

PATCH /api/schedules/:id

Edit any subset of content, status, or the frequency tuple (frequency + runAt/timeMinutesUTC/dayOfWeek/cronExpr). If you touch any timing field, the server re-validates the full frequency spec and recomputes nextRunAt — so always send a coherent timing group, not a half-update.

Setting status to anything other than active clears nextRunAt.

Response{ success: true, schedule }.

DELETE /api/schedules/:id

Hard delete. { success: true } on success.

Schedule semantics
Frequency When it fires Required fields
oneoff Once, at runAt. Auto-transitions to completed after firing. runAt (future)
daily Every day at timeMinutesUTC minutes past UTC midnight. timeMinutesUTC
weekly Every week on dayOfWeek at timeMinutesUTC. timeMinutesUTC, dayOfWeek
cron Whenever the 5-field cron matches (UTC). cronExpr

cron schedules are intentionally excluded from the dashboard's month calendar view because their cadence isn't naturally per-day.


Logs

OutreachLog is a denormalised, append-only event stream — separate from tasks — that captures every message-sending attempt with its outcome (sent / failed / skipped). It powers the /dashboard/logs page and is the right place to look for analytics, not the task log.

GET /api/logs

Query

Param Type Default Notes
agentId string
platform string
result sent · failed · skipped
days number 7 Lookback window.
limit number 100

Response

{
  "success": true,
  "logs": [
    {
      "logId": "65fc...",
      "agentId": "65f0...",
      "platform": "facebook",
      "result": "sent",
      "targetUrl": "https://facebook.com/...",
      "targetName": "Casino Royale Group",
      "messageSent": "...",
      "errorMessage": null,
      "timestamp": "2026-05-18T03:14:15.000Z"
    }
  ],
  "summary": {
    "total": 42,
    "sent": 38,
    "failed": 3,
    "skipped": 1,
    "byDay": [ { "day": "2026-05-18", "sent": 5, "failed": 0, "skipped": 0 } ]
  }
}

Extension endpoints

These are called by the Chrome extension running on operator machines, not by your code.

POST /api/extension/heartbeat

Used during the install handshake (the popup pings this once with the pasted token to mark the agent online before the WS connection establishes). Steady-state heartbeating happens over WebSocket pings.

Body

Field Type Required Notes
token string yes Agent token.
version string no Extension version (e.g. "0.2.1").

Response — 200 OK

{
  "success": true,
  "agent": {
    "agentId": "65fc...",
    "name": "Marketing seat #1",
    "userEmail": "[email protected]",
    "status": "online",
    "platforms": ["facebook"]
  }
}

Errors400 (no token), 401 Invalid token.


Locale

POST /api/locale

Persist a UI-language preference for the dashboard. Pure UI concern; you shouldn't need it from automation.

Body

Field Type Required Notes
locale en · zh-TW yes

Response{ success: true, locale }. Sets the locale cookie.


WebSocket hub protocol

The hub is the realtime backbone between Bredgio and every extension instance. One connection per agent, multiplexed for every command issued to that agent.

Connect

wss://bredgio.letmesee.cc/api/social-agents/ws?token=<agent_token>&version=<ext_ver>
  • token (required) — the agent token from POST /api/agents or GET /api/agents/:id/token. Missing or invalid token → HTTP/1.1 401 before the upgrade.
  • version (optional) — extension version, stored on the agent doc as extensionVersion.

The upgrade itself runs over Caddy on the public hostname and is routed internally to a Node process on port 3032.

Frame format

Every frame is a JSON object with a type discriminator.

Server → client

type Shape Meaning
command { type: 'command', id: uuid, cmd: string, args: object } Execute the named atomic command.
ping { type: 'ping' } Keepalive every 30 s. Reply with pong.

Client → server

type Shape Meaning
hello { type: 'hello', version?: string } Optional. Sent right after connect.
pong { type: 'pong' } Reply to a server ping. Sockets idle > 90 s are closed.
result { type: 'result', id: uuid, ok: boolean, data?: any, error?: string } Reply to a command, correlated by id.

Atomic commands

The server-side flow planner expands a task (e.g. facebook + post) into a sequence of these. The extension MUST NOT invent its own flows — new product behaviour ships server-side.

cmd args Returns (data)
navigate { url: string, waitForLoad?: boolean } {}
click { selectors: string[], timeoutMs?: number } { matched: string } (the selector that hit)
type { selector: string, text: string } {}
wait { seconds?: number, selector?: string, timeoutMs?: number } {}
evaluate { expression: string, awaitPromise?: boolean } { result: any }
screenshot { format?: 'png' | 'jpeg', quality?: number } { dataUri: string }
cookies { urls?: string[] } { cookies: Cookie[] }

selectors for click is an ordered fallback list — the extension tries each until one matches. This is how flows survive Facebook's locale-dependent DOM (English "Post" vs Traditional Chinese "貼文").

Per-command timeout defaults: click/type 10 s, navigate 30 s, the hub also enforces a 60 s end-to-end timeout per command and rejects the correlated promise on disconnect.

Lifecycle

extension      hub                            db
    │           │                              │
    ├─── connect ──►                           │
    │       (auth via ?token=)                 │
    │      ◄────── upgrade 101                 │
    │      ◄────── ping (every 30s)            │
    ├─── pong ────►                            │
    │                                          │
    │                ◄── claimNextPendingTask ─┤
    │      ◄────── command#1 (navigate)        │
    ├─── result#1 ─►                           │
    │                ──── appendTaskLog ──────►│
    │      ◄────── command#2 (click)           │
    ├─── result#2 ─►                           │
    │                                          │
    │                ─── finishTask / failTask ►
    │      ◄────── disconnect 1008 if token revoked

Stale agent sweep

Every 60 s the hub runs a sweep that flips agents to offline if their lastSeenAt is older than 120 s. This is the safety net for extensions that crash, get uninstalled, or have their machine put to sleep without a clean close frame.


Error envelope

Every error response is:

{
  "success": false,
  "error": "human-readable message"
}

with a meaningful HTTP status code. Some responses include extra hints (e.g. passwordRequired: true from the token regenerate endpoint when the password was omitted).

Error codes

These appear as errorCode on failed tasks and inside task log entries.

Code Meaning Typical fix
fb_login_required The operator is not logged in to Facebook in the browser the extension controls. Have the operator log in, then redispatch.
fb_compose_not_found Couldn't find the "Create post" entry point. Usually Facebook A/B/C-testing the home page — wait or report it.
fb_textbox_not_found Compose dialog opened but no editable region appeared. Same as above.
fb_post_button_not_found Composed the post but couldn't locate the submit control. Same as above.
fb_unknown Catch-all for unmapped Facebook errors. Inspect log for the underlying step + message.
action_not_implemented The dispatched action has no server-side flow yet. See Task actions.
agent_offline No extension was connected when the task was claimed. Bring the agent online and redispatch.
command_timeout A single atomic command exceeded its timeout. Network or page slowness — retry.
disconnected The extension dropped during execution. Retry.
plan_upgrade_required The caller is on Free and tried to mint a PAT or hit a Pro-only endpoint. Upgrade at upgradeUrl returned in the error body.
plan_downgraded A previously valid PAT was auto-revoked when the account downgraded. Resubscribe or re-mint after upgrading.
invalid_key The Authorization: Bearer token is unknown, revoked, or malformed. Mint a new PAT and rotate.

HTTP status reference

Status When
400 Validation failed — missing field, bad enum, malformed JSON, past scheduledFor.
401 Missing or invalid session cookie / agent token / PAT / user password.
403 Authenticated but unauthorised — e.g. accessing another user's agent.
404 The agent / task / schedule does not exist.
500 Unhandled server error. Safe to retry idempotent reads.

Code examples

Every example uses a PAT. Set BREDGIO_API_KEY to your bk_pat_....

Node.js — dispatch and poll

const base = 'https://bredgio.letmesee.cc';
const headers = {
  authorization: `Bearer ${process.env.BREDGIO_API_KEY}`,
  'content-type': 'application/json'
};

const dispatch = await fetch(`${base}/api/agents/${agentId}/command`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    action: 'post',
    platform: 'facebook',
    params: { content: 'Hello from Node\nLine two.' }
  })
}).then((r) => r.json());

const { taskId } = dispatch.task;

for (;;) {
  const task = await fetch(`${base}/api/tasks/${taskId}`, { headers })
    .then((r) => r.json())
    .then((r) => r.task);
  if (['completed', 'failed', 'cancelled'].includes(task.status)) {
    console.log(task.status, task.result ?? task.errorCode);
    break;
  }
  await new Promise((res) => setTimeout(res, 2000));
}

Python — schedule a daily post

import os, requests

headers = {'Authorization': f"Bearer {os.environ['BREDGIO_API_KEY']}"}

r = requests.post(
    'https://bredgio.letmesee.cc/api/schedules',
    headers=headers,
    json={
        'agentId':       'YOUR_AGENT_ID',
        'platform':      'facebook',
        'content':       'Good morning ☀️',
        'frequency':     'daily',
        'timeMinutesUTC': 0,    # 00:00 UTC
        'timezone':      'Asia/Taipei'
    }
)
r.raise_for_status()
print('Scheduled:', r.json()['schedule']['scheduleId'])

cURL — list today's tasks

curl -H "Authorization: Bearer $BREDGIO_API_KEY" \
  'https://bredgio.letmesee.cc/api/tasks?limit=100&status=completed' \
  | jq '.tasks | length'

Support

Open an issue at the project repository or message the maintainer directly if you need API help, a new action type, or a bug investigated.