---
title: "X API: post and schedule from code"
url: "https://get1post.com/developers/x.md"
canonical_url: "https://get1post.com/developers/x"
last_updated: "2026-10-26"
type: "reference"
summary: "Post and schedule to X with the 1Post API and MCP server: the request, the reply, every rule it is checked against and a dry run."
related: ["https://get1post.com/platforms/x.md", "https://get1post.com/platforms/x/specs.md", "https://get1post.com/docs/api-posts.md", "https://get1post.com/docs/mcp.md"]
---

# X API: post and schedule from code

Post and schedule to X with the 1Post API and MCP server: the request, the reply, every rule it is checked against and a dry run.

Post to X from code with one request: POST /v1/posts with your account id, the text and a schedule_at time. X text is limited to 280 characters, counted with X's weights: links count 23 and emoji 2. 1Post allows up to 50 posts a day for each connected account, and a dry run checks a post against every rule first.

## Connect X first

1. Open Accounts in 1Post and choose Connect.
2. Pick X.
3. Sign in with X and approve access, or enter your own X developer keys.
4. Choose the account in 1Post. It is ready to pick in the composer.

Then GET /v1/accounts returns the id of the X account to use in the request.

## Send a post to X

**Schedule a post**

```bash
curl https://api.get1post.com/v1/posts \
  -H "Authorization: Bearer $ONEPOST_API_KEY" \
  -H "Idempotency-Key: x-first-post" \
  -d '{"accounts":["ACCOUNT_ID"],"text":"Doors open at nine. Bring a friend.","schedule_at":"2026-11-02T15:00:00Z"}'
```

The reply is 202 with the post (status scheduled) and one destination for X, which moves from queued to published or failed.

## What you can send to X

- Text
- Up to 4 images, or 1 GIF, or 1 video
- Threads
- Polls
- Reply settings
- Community posts
- Labels for paid partnerships and generated media

## What X publishes

- A post can contain up to 280 characters. Most characters count 1, emoji count 2, and every URL counts 23 however long it is.
- Creating posts through the API is limited to 100 per 15 minutes per user and 10,000 per 24 hours per app.
- Pay-per-use API pricing is $0.015 for a post and $0.200 for a post with a URL.

## X rules the request is checked against

| Rule | What 1Post checks |
| --- | --- |
| Text limit | 280 characters, counted with X's weights: links count 23 and emoji 2 |
| Media accepted | Images, GIFs, Video |
| Images per post | 4 |
| Videos per post | 1 |
| Images and video together | Not in one post |
| GIF | Must be the only media in the post |
| Threads | Yes, as a chain of replies |
| First comment | Yes |
| Polls | 2 to 4 options of up to 25 characters; not together with media |
| Posts per day, per connected account (1Post) | 50 |

The same table with sources is on the [X specs page](https://get1post.com/platforms/x/specs.md).

## X options in the request

- Thread: send parts instead of text. Each part is one post in the chain, up to 100 parts, and each is counted on its own.
- First comment: add first_comment with text to an account object, and delay_min if it should wait.
- Poll: 2 to 4 options of up to 25 characters, sent in the account's settings.

**A two-part thread in the next free slot**

```json
{
  "accounts": [
    "ACCOUNT_ID"
  ],
  "parts": [
    {
      "text": "1/ The short version."
    },
    {
      "text": "2/ The detail.",
      "delay_min": 1
    }
  ],
  "use_next_free_slot": true
}
```

## Check the post before it is queued

Add "dry_run": true to test a post: nothing is kept, a valid one answers 200 and a broken one answers 422 naming the rule.

**A refused request, abridged**

```json
{
  "error": {
    "code": "invalid_for_platform",
    "message": "x refuses this post: X counts 312 of 280 characters in part 1. (text_too_long).",
    "fix": "Fix the rule named in the message and send the post again.",
    "retryable": false,
    "request_id": "REQUEST_ID"
  }
}
```

An assistant connected to the [MCP server](https://get1post.com/docs/mcp.md) sends the same fields to create_post; [set one up](https://get1post.com/assistants.md).

## Questions

**Can I post to X with an API key?**

Yes. A key with write scope can create, change and cancel X posts for the workspace it belongs to, with the role of the member who made it. See [API authentication](https://get1post.com/docs/api-authentication.md).

**What happens if a X post breaks a rule?**

The request is refused with invalid_for_platform and the failing rule is named. Fix it and send the request again, or send it with dry_run to test the fix first.

**How many X posts can I send in a day?**

Up to 50 for each connected account. A request that would pass that answers daily_cap with the time the day frees up.

**Does a link cost more on X?**

Through the X API a post with a URL costs $0.200 against $0.015 for a plain post, as X publishes it. The [X API cost calculator](https://get1post.com/tools/x-api-cost-calculator.md) shows what that means for your month.

## Sources

- [X developer docs: counting characters](https://docs.x.com/fundamentals/counting-characters), read 2026-10-22
- [X API rate limits](https://docs.x.com/x-api/fundamentals/rate-limits), read 2026-10-22
- [X API pricing](https://docs.x.com/x-api/getting-started/pricing), read 2026-10-22

## Related

- [Schedule X posts: formats, limits, setup](https://get1post.com/platforms/x.md)
- [X specs and limits: text, media, daily cap](https://get1post.com/platforms/x/specs.md)
- [Creating and changing posts with the API: 1Post docs](https://get1post.com/docs/api-posts.md)
- [The MCP server: 1Post docs](https://get1post.com/docs/mcp.md)
