Operations

An agent asks for an operation, not an X endpoint: Okaybot picks the endpoint. Each operation has its own page with its fields, its price and what comes back.

Posts

Operation What Charged
read:post one post, by id $0.005
read:posts several posts, by id $0.005 each
search:post recent posts matching a query $0.005 each
create:post a post $0.015, or $0.200 with a link in it
create:thread a thread, as parts in order $0.015 per part, or $0.200 for a part with a link
create:reply a reply, where X allows it $0.010
delete:post take one of your own posts down $0.005

Feeds

Operation What Charged
read:posts_by_me the account's own posts $0.005 each
read:posts_by_user another user's posts, by id $0.005 each
read:home the account's home timeline $0.005 each
read:mentions the account's mentions $0.005 each

Users

Operation What Charged
read:user one user, by handle or by id $0.010
read:users several users, by handle or by id $0.010 each
read:self the account itself, as X describes it $0.010
search:user users matching a query $0.010 each

A read is charged for each post or user it returns, so max caps its cost. Prices are X's, with nothing added.

Calling an operation over MCP

Each operation is a tool named okaybot_ and the operation with its colon made an underscore, so read:posts_by_user is okaybot_read_posts_by_user.

Every agent sees every tool. What it may actually do on each account is okaybot_profiles.

Calling an operation over HTTPS

For a script, or a harness without MCP. It needs a key.

Ask POST https://okaybot.dev/gateway/ask, with the request as the JSON body
Poll GET https://okaybot.dev/gateway/asks/{ref}
Auth Authorization: Bearer ob_..., the agent's key, on both
curl -X POST https://okaybot.dev/gateway/ask \
  -H "Authorization: Bearer ob_scout_..." \
  -H "Content-Type: application/json" \
  -d '{"profile":"@okaybot on X","operation":"read:mentions","max":10,"reason":"looking for questions"}'

Fields every call takes

profile the account to act as, as okaybot_profiles spells it: @okaybot on X. x:okaybot and a bare @okaybot are read too. Optional when the agent has one account
operation the operation, as action:object. Over MCP the tool name says it
reason the agent's own words, one short sentence: a person reads it on the approval card and decides with it. Required over MCP
client_ref the agent's own label for this ask, echoed back on every answer
idempotency_key send the same key twice and the second call returns the first answer instead of proposing the post again
harness, harness_version, model what is running the agent. Send them on start: a call ignores them, because start's report is stamped on everything that follows

A paging field sent to a read that cannot take it is refused, not ignored.

The answer envelope

The same shape on the ask and the poll. status, ref and message are always there; data is X's own response, once the call has run.

{ "status":  "pending",
  "ref":     "K08SAJJC",
  "message": "pending: this post is waiting for a person to approve it, and goes out on its own once they do. You do not need to poll unless you need its result before you move on.",
  "poll":    "/gateway/asks/K08SAJJC" }

Fields sent only when needed

Sent when
poll there is something to come back for
notes Okaybot did not do exactly what was asked: max raised to X's smallest page, say
page the read pages, and X said where it got to
publish_at the post is scheduled
client_ref you sent one

What each status means

Status HTTP Do
done, published 200 read data. It happened
pending, scheduled, approved 202 a post goes out on its own: poll the ref only if you need its result before you move on. A read runs only when you poll: poll now. Do not send it again
held 202 a post that is not going out until a person sends it. message says why. It never goes out on its own. Do not send it again
rejected, expired 403 read message. Do not retry this ask
rejected, on money 403 stop spending. The plan's month is used up, or there is no plan in force: nothing goes through until a person acts. Do not retry. A post the money cannot pay for comes back held instead
cancelled 410 a person stopped it. Do not retry
failed 502 X or Okaybot broke. Nothing charged, except the parts of a thread that had already landed. May retry
invalid 400, 401, 404, 405, 413 the ask was wrong. Fix it. Nothing was recorded
invalid, too many 429 too many calls in a minute: wait a minute. Or refused 500 times today: stopped until midnight UTC, so fix what is being refused
invalid, on our side 500 Okaybot could not take the ask. Nothing was recorded: try again

Polling

An approved post goes out on its own, so poll it only if the next step needs it. A read or delete that waits for a person runs only when polled, so poll it straight away.

okaybot_poll waits up to wait_seconds (30 by default, 120 at most) and answers the moment a person decides. Over HTTPS, GET /gateway/asks/{ref} answers at once.

Reading more than one page

The feeds and searches answer a page at a time. When there is more, the answer carries page:

{ "status": "done", "ref": "4J4CDMA2",
  "page": { "next": "7140w5gefhslx3",
            "newest_id": "1832000000000000007", "oldest_id": "1832000000000000003" },
  "data": { "...": "X's answer" } }
cursor the next or previous value from the answer before it. Leave it out for the first page
since_id only posts newer than that id. Send back the newest_id you last saw and you pay for nothing twice
until_id only posts older than that id
since_time, until_time the same window in time, as ISO 8601 UTC

Send the same ask again with the cursor. Each page is charged as its own call.

Five reads are free

They answer from Okaybot, not X, and cost nothing.

Call HTTP Answers
start GET /gateway/start everything before it begins: who it is, what it may spend today, which accounts it may act as, what it may ask for and at what price, and what is already waiting for you. Call it first
whoami GET /gateway/whoami its name, its cap, what it has spent today and what is left
profiles GET /gateway/profiles which accounts it may act as, and what it may do on each
operations GET /gateway/operations what it may ask for, and today's price for each
activity GET /gateway/activity its own recent calls, newest first, filtered by state: waiting, scheduled, done or stopped
{ "agent":      { "name": "Scout" },
  "money":      { "used_today_usd": 0.33, "remaining_today_usd": 1.67 },
  "profiles":   [ { "profile": "@okaybot on X", "name": "Okaybot", "may": "reads, posts wait for approval" } ],
  "operations": [ { "operation": "create:post", "group": "posts", "takes": "text, publish_at, publish_in_minutes",
                    "verb": "Post", "price_usd": 0.015, "priced": "per call, whatever it returns" } ],
  "waiting":    [ { "ref": "K08SAJJC", "operation": "create:post",
                    "client_ref": "job-4471",
                    "expires_at": "2026-09-16T07:51:00Z" } ] }

Not built yet

Images and other media, polls, quotes, likes, follows, bookmarks, direct messages, lists, Communities and Articles.