> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sorsa.io/llms.txt
> Use this file to discover all available pages before exploring further.

# X Articles

# X Articles

Retrieve the full content and metadata of any public X Article in a single request. An Article is a long-form post on X with a cover image, rich text body (up to \~100,000 characters), and engagement metrics separate from its announcement tweet.

> **Free to try:** `/article` works on your first 100 requests: one-time, no credit card, no expiry. An article fetch is a single request with no per-character charge, however long the body, so that is up to 100 full articles at no cost.

> **Note:** For a fuller guide on working with long-form X posts, see [X Articles API: Retrieve Long-Form X Posts](https://api.sorsa.io/blog/x-articles-api) on the blog.

***

## Quickstart

```bash theme={null}
curl -X POST https://api.sorsa.io/v3/article \
  -H "ApiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tweet_link": "https://x.com/SorsaApp/status/1234567890"}'
```

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"

def get_article(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/article",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()


article = get_article("https://x.com/SorsaApp/status/1234567890")
print(f"Author: @{article['author']['username']}")
print(f"Published: {article['published_at']}")
print(f"Views: {article['views_count']:,}")
print(f"Body length: {len(article['full_text'])} characters")
```

***

## Endpoint

```text theme={null}
POST /v3/article
```

### Request Body

| Parameter    | Type   | Required | Description                                                       |
| :----------- | :----- | :------- | :---------------------------------------------------------------- |
| `tweet_link` | string | Yes      | Full URL of the announcement tweet, or just the numeric tweet ID. |

### Response

```json theme={null}
{
  "full_text": "this isn't a cosmetic rebrand. it's a response to how crypto twitter actually works in 2026...",
  "preview_text": "this isn't a cosmetic rebrand. it's a response to how crypto twitter actually works in 2026.\nthe old model was simple...",
  "cover_image_url": "https://pbs.twimg.com/media/G-t2hYTaIAAstc8.jpg",
  "published_at": "2026-01-15T16:24:02Z",
  "views_count": 36538,
  "likes_count": 315,
  "bookmark_count": 38,
  "quote_count": 37,
  "reply_count": 80,
  "retweet_count": 41,
  "author": {
    "id": "1934538036466810880",
    "username": "SorsaApp",
    "display_name": "Sorsa",
    "description": "Crypto social analytics made simple...",
    "followers_count": 6050,
    "verified": false
  }
}
```

### Response Fields

| Field             | Type              | Description                                                                  |
| :---------------- | :---------------- | :--------------------------------------------------------------------------- |
| `full_text`       | string            | Complete article body. Can be tens of thousands of characters.               |
| `preview_text`    | string            | Truncated snippet shown in the timeline before "Read more."                  |
| `cover_image_url` | string \| null    | URL of the cover image. `null` if no cover was set.                          |
| `published_at`    | string (ISO 8601) | Publication timestamp (distinct from the announcement tweet's `created_at`). |
| `likes_count`     | integer           | Likes.                                                                       |
| `retweet_count`   | integer           | Retweets.                                                                    |
| `reply_count`     | integer           | Replies.                                                                     |
| `quote_count`     | integer           | Quote tweets.                                                                |
| `bookmark_count`  | integer           | Bookmarks.                                                                   |
| `views_count`     | integer           | Total impressions.                                                           |
| `author`          | object            | Full author profile (same fields as the standard User object).               |

> **Field naming.** The engagement fields on the article response (`likes_count`, `retweet_count`, `reply_count`, `quote_count`, `bookmark_count`) match the standard Tweet object, with one exception: impressions come back as `views_count` here, versus `view_count` (singular) on a tweet. If you run tweets and articles through the same pipeline, normalize that one key at ingestion. See [Response Format](https://docs.sorsa.io/response-format) for the full schema comparison.

***

## Detecting an Article vs a Regular Tweet

Not every tweet link points to an Article. Try `/article` first and fall back to `/tweet-info` if the response lacks a substantive body:

```python theme={null}
def get_content(tweet_link):
    """Fetch a tweet or article, returning the appropriate object."""
    try:
        article = get_article(tweet_link)
        if article.get("full_text") and len(article["full_text"]) > 500:
            return {"type": "article", "data": article}
    except Exception:
        pass

    resp = requests.post(
        "https://api.sorsa.io/v3/tweet-info",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return {"type": "tweet", "data": resp.json()}
```

***

## Next Steps

* [Search Tweets](https://docs.sorsa.io/search-tweets): find articles by keyword.
* [Tweet Engagement](https://docs.sorsa.io/tweet-engagement): get comments, quotes, and retweets on an article tweet.
* [Historical Data](https://docs.sorsa.io/historical-data): retrieve articles published months or years ago.
* [API Reference](https://docs.sorsa.io/api-reference-guide): full specification for `/article` and all Sorsa API endpoints.
