EvenpostSign in

Docs · Tools

What your agent can do

Evenpost, an app for X (Twitter) that lets an AI agent draft posts you approve on your phone, gives your agent fifteen things it can do. Two it never can: approve a post, and post to X.

Evenpost / Docs / What your agent can do

Write and edit

  1. Draft a post or thread create_draftSaves a new draft, up to 25 tweets, for you to review. It is not posted and not queued.
  2. Edit a draft update_draftReplaces the tweets of a draft. If you edited it first, your version is kept and the agent is told.
  3. Check the length first quote_postCounts X's weighted length (a link counts 23, an emoji 2) and says which tweets carry a link. Nothing is saved.
  4. Ask you to look request_approvalSends you a "needs approval" notification. It only asks.
  5. Archive a draft archive_draftArchives a pending draft this key created. It does not post or delete.

Photos

  1. Attach a photo add_photoOne local JPEG, PNG or WEBP per call, up to 4 per tweet. EXIF and location data are removed.
  2. Remove a photo remove_photoTakes one photo off a tweet.
  3. Reorder photos reorder_photosSets the order. The first is the lead image.
  4. Attach a video add_videoOne local MP4 or MOV, up to 512 MB and 10 minutes. You approve it in the app.

add_video is only available on allow-listed accounts during the beta.

Read

  1. Account status account_statusPlan, tweet length limit, what is left this period, and drafts waiting for you.
  2. Who this key is for whoamiThe X account and the key name. It does not post.
  3. The queue list_queueWhat is scheduled and what needs attention, soonest first.
  4. Drafts by status list_draftsPending, failed, queued or posted, newest first.
  5. One post in full get_postIts tweets, photos, status and whether you edited it.
  6. Usage list_spendTweets and link posts used and left this period. Counts only.

What an agent cannot do

Approve, queue, post, change your posting hours, make or revoke keys, or delete anything. Those actions exist only in the app, on your phone, for you. An agent that tries gets a refusal, and nothing changes.

Can I tell my agent to post at 9 am?

Your agent cannot schedule a post for 9 am or any other time: it can draft the post and ask you to look. You pick the time when you queue it in the app, either an exact minute inside your hours (7 am to 6 pm by default) or the next slot with natural spacing.

Can the agent read what I already posted?

Yes, your agent can read what you already posted. It can list your posted drafts and open any one post in full, with its tweets, photos and status, which helps it avoid repeating itself. It cannot edit, delete or repost anything that is already live on X.

Want the approval queue on your phone? Join the waitlist. Already invited? Connect your agent.

Each tool

There is no post tool and no queue tool. Approving, queueing and posting stay in the app.

Account status account_status

Where the account stands: handle (the X account this key acts for), key_name (this key's name), plan, the tweet length limit, what is left of this period's tweets and link posts, storage (bytes stored, the cap, and when the next posted file frees space), drafts waiting for the owner's approval (pending_approvals), drafts that failed (failed: X said no, or nothing was sent) and video_enabled (whether add_video works for this account; the owner turns it on), and drafts that need a check on X (needs_check, with check_reason: part of the thread may be live, so only the owner can settle it). Each list is its first 50: `more` says which have another page, and list_drafts pages through them. Read-only.

No arguments.

No refusal of its own.

Whoami whoami

Who this key acts for: handle (the X account), key_name (this key's name) and account_id. Read-only. It does not post.

No arguments.

No refusal of its own.

Quote post quote_post

Length-check a thread before drafting it. Counts X's weighted length (a link counts 23, an emoji 2), flags empty tweets and more than one cashtag, and says which tweets carry a link (and so use a link post). Runs locally; the limit follows the account when an API key is set. The result includes warnings for hidden characters, a tweet that is too long, a link to a post on X, an empty tweet, and more than one cashtag. Read-only.

ArgumentRequiredTypeWhat it is
tweetsyesarray of string, at least 1, at most 25The tweets of the thread, in order.
photosnoarray of integerOptional: how many photos each tweet carries, in the same order (a tweet with only a photo is not empty).

No refusal of its own.

Create draft create_draft

Save a new draft thread for the owner to review. It is not posted and not queued: the owner approves it in the Evenpost app. Returns draft_id, version_id and warnings (hidden characters removed, too long, a link to a post on X, an empty tweet, or more than one cashtag). Each tweet is a string or {text, photos?}, where photos are ids from add_photo; a new draft has none yet, so attach photos with add_photo.

ArgumentRequiredTypeWhat it is
tweetsyesarray of string or object, at least 1, at most 25The tweets of the thread, in order: strings, or {text, photos?} objects.
idempotency_keynostring, min length 1, max length 200Optional: send the same key again to get the same draft back instead of a duplicate.

No refusal of its own.

Update draft update_draft

Replace the tweets of an existing draft (send all of them) and return warnings for hidden characters, length, a link to a post on X, an empty tweet, or cashtags. Each tweet is a string or {text, photos?}. Photos you leave out stay with the tweet at the same position. If the draft has photos and you change the tweet count or the order of the tweets, every tweet must carry `photos` (a list of photo ids from get_post, or [] for none), or the call is refused with 422 photos_required and nothing is saved; photos you leave out of a restructure are only detached from this draft. Rewording a tweet in place is fine without photos. A tweet the owner has edited is protected: if the draft changed since you read it the call is refused until you re-read it with get_post and send its version_id. Cannot touch a draft that is posting or posted.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.
tweetsyesarray of string or object, at least 1, at most 25The full thread as it should read now: strings, or {text, photos?} objects (photos required on every tweet when you change the count or order of a draft that has photos).
base_version_idnointeger, at least 0The version you built on (version_id from get_post). Required once the owner has edited the draft: re-read it with get_post, build on that text, and send its version_id.

It can refuse with:

  • If the draft has photos and you change the tweet count or the order of the tweets, every tweet must carry `photos` (a list of photo ids from get_post, or [] for none), or the call is refused with 422 photos_required and nothing is saved; photos you leave out of a restructure are only detached from this draft.
  • A tweet the owner has edited is protected: if the draft changed since you read it the call is refused until you re-read it with get_post and send its version_id.
  • Cannot touch a draft that is posting or posted.

Add photo add_photo

Attach one local image file (PNG, JPEG or WEBP, up to 5 MB) to one tweet of a draft; call it once per photo. The server checks the file's bytes, not its name. Refused: animated images, transparent or lossless WEBP, JPEGs over 12,000 px a side or 100 megapixels, PNGs over 8192 px a side, and interlaced or low-bit-grey PNGs with transparency. A JPEG up to 4096 px keeps its pixels; a larger one is resized. Location and camera data are removed (the rotation stays), and other PNG transparency is flattened onto white. A tweet carries up to 4 photos, and an account can upload 50 photos or 100 MB a day.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.
indexyesinteger, 0 to 24Which tweet of the thread, counting from 0.
pathyesstring, min length 1Path to the image file on this machine.
base_version_idnointeger, at least 0The version you built on (version_id from get_post). Required once the owner has edited the draft: re-read it with get_post, build on that text, and send its version_id.

It can refuse with:

  • Refused: animated images, transparent or lossless WEBP, JPEGs over 12,000 px a side or 100 megapixels, PNGs over 8192 px a side, and interlaced or low-bit-grey PNGs with transparency.
  • Paths must be under the current directory or your home folder.
  • add_photo takes images up to 5 MB.

Add video add_video

Attach one local video to one tweet of a draft. MP4 or MOV. H.264 and AAC-LC. Up to 512 MB and 10 minutes. One video per tweet. No photos on that tweet. 10 videos or 1 GB a day. The owner approves it in the app. A file that already fits is uploaded unchanged; anything else is converted on this Mac with ffmpeg at high quality when ffmpeg is installed. A conversion can take minutes.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.
indexyesinteger, 0 to 24Which tweet of the thread, counting from 0.
pathyesstring, min length 1Path to the video file on this machine.
base_version_idnointeger, at least 0The version you built on (version_id from get_post). Required once the owner has edited the draft: re-read it with get_post, build on that text, and send its version_id.

It can refuse with:

  • Video is not turned on for this account yet.
  • add_video takes videos up to 512 MB.
  • Use another tweet, or remove the photos on this one.
  • Paths must be under the current directory or your home folder.

Remove photo remove_photo

Remove one photo or video from a tweet of a draft.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.
indexyesinteger, 0 to 24Which tweet of the thread, counting from 0.
photo_idyesstringThe photo's id, from get_post.
base_version_idnointeger, at least 0The version you built on (version_id from get_post). Required once the owner has edited the draft: re-read it with get_post, build on that text, and send its version_id.

No refusal of its own.

Reorder photos reorder_photos

Set the order of a tweet's photos. List every photo id the tweet has, in the order you want; the first is the lead image.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.
indexyesinteger, 0 to 24Which tweet of the thread, counting from 0.
photosyesarray of string, at least 1, at most 4Photo ids in the new order.
base_version_idnointeger, at least 0The version you built on (version_id from get_post). Required once the owner has edited the draft: re-read it with get_post, build on that text, and send its version_id.

No refusal of its own.

Request approval request_approval

Nudge the owner: sends a "needs approval" notification for this draft. It only asks. It does not approve, queue or post anything; the owner decides in the Evenpost app.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.

No refusal of its own.

Archive draft archive_draft

Archive a pending draft that this key created and that was never queued or posted. It cannot archive another key's draft, or one that was queued or posted: the owner does that in the app. It does not post or delete.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.

It can refuse with:

  • It cannot archive another key's draft, or one that was queued or posted: the owner does that in the app.

List queue list_queue

The owner's posting queue, soonest first, 50 at a time: what is scheduled, and what needs attention. Returns { items, next_cursor }; send next_cursor back as `cursor` for the next page (null means that was the last). A page can hold fewer than 50 when the drafts are long. Walking pages is not a snapshot: for failed or needs_check drafts use list_drafts with that status. Read-only.

ArgumentRequiredTypeWhat it is
cursornostringThe next_cursor of the previous page. Leave it out for the first page.

No refusal of its own.

List drafts list_drafts

Drafts in one status, newest first, 50 at a time. Returns { items, next_cursor }; send next_cursor back as `cursor` for the next page (null means that was the last). Read-only.

ArgumentRequiredTypeWhat it is
statusyespending | failed | needs_check | queued | postedWhich drafts: pending (waiting for the owner), failed, needs_check, queued or posted.
cursornostringThe next_cursor of the previous page. Leave it out for the first page.

No refusal of its own.

Get post get_post

One draft in full: its tweets (each with text, the ids of its photos, media_kinds, receipts, and owner_edited_at), status, version_id, warnings, and whether the owner has edited it. Echo a tweet's photos back to update_draft to keep them. receipts is read-only. Read-only.

ArgumentRequiredTypeWhat it is
draft_idyesstringThe draft's id, as create_draft or list_queue returned it.

No refusal of its own.

List spend list_spend

The plan, tweets and link posts used and left this period, and the account's tweet length limit. Read-only.

No arguments.

No refusal of its own.

Updated 6 Nov 2026