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
- 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. - Edit a draft
update_draftReplaces the tweets of a draft. If you edited it first, your version is kept and the agent is told. - 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. - Ask you to look
request_approvalSends you a "needs approval" notification. It only asks. - Archive a draft
archive_draftArchives a pending draft this key created. It does not post or delete.
Photos
- Attach a photo
add_photoOne local JPEG, PNG or WEBP per call, up to 4 per tweet. EXIF and location data are removed. - Remove a photo
remove_photoTakes one photo off a tweet. - Reorder photos
reorder_photosSets the order. The first is the lead image. - 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
- Account status
account_statusPlan, tweet length limit, what is left this period, and drafts waiting for you. - Who this key is for
whoamiThe X account and the key name. It does not post. - The queue
list_queueWhat is scheduled and what needs attention, soonest first. - Drafts by status
list_draftsPending, failed, queued or posted, newest first. - One post in full
get_postIts tweets, photos, status and whether you edited it. - 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
tweets | yes | array of string, at least 1, at most 25 | The tweets of the thread, in order. |
photos | no | array of integer | Optional: 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
tweets | yes | array of string or object, at least 1, at most 25 | The tweets of the thread, in order: strings, or {text, photos?} objects. |
idempotency_key | no | string, min length 1, max length 200 | Optional: 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The draft's id, as create_draft or list_queue returned it. |
tweets | yes | array of string or object, at least 1, at most 25 | The 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_id | no | integer, at least 0 | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The draft's id, as create_draft or list_queue returned it. |
index | yes | integer, 0 to 24 | Which tweet of the thread, counting from 0. |
path | yes | string, min length 1 | Path to the image file on this machine. |
base_version_id | no | integer, at least 0 | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The draft's id, as create_draft or list_queue returned it. |
index | yes | integer, 0 to 24 | Which tweet of the thread, counting from 0. |
path | yes | string, min length 1 | Path to the video file on this machine. |
base_version_id | no | integer, at least 0 | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The draft's id, as create_draft or list_queue returned it. |
index | yes | integer, 0 to 24 | Which tweet of the thread, counting from 0. |
photo_id | yes | string | The photo's id, from get_post. |
base_version_id | no | integer, at least 0 | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The draft's id, as create_draft or list_queue returned it. |
index | yes | integer, 0 to 24 | Which tweet of the thread, counting from 0. |
photos | yes | array of string, at least 1, at most 4 | Photo ids in the new order. |
base_version_id | no | integer, at least 0 | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
cursor | no | string | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
status | yes | pending | failed | needs_check | queued | posted | Which drafts: pending (waiting for the owner), failed, needs_check, queued or posted. |
cursor | no | string | The 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.
| Argument | Required | Type | What it is |
|---|---|---|---|
draft_id | yes | string | The 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