# Accounts a given account started or stopped following (follow/unfollow log, outgoing)

`GET https://twitterscore.io/api/v1/friendshipHistory/following`

Returns the outgoing follow activity of one account: every recorded event where the account followed (`action: "Following"`) or unfollowed (`action: "Unfollowing"`) another account, with the followed account's profile summary, Twitter Score, follower count, tags, categories and the event date. Identify the account by `username` or `twitter_id`. Only followed accounts that TwitterScore also tracks as full accounts are included (the query inner-joins the main accounts table), and the tags/categories shown are those of the followed account. Narrow the log to one day with `date` (YYYY-MM-DD), or to followed accounts carrying given tags / categories with comma-separated `tag_ids` / `category_ids` (ids from get_tags_list / get_categories_list). The whole history is loaded and then paginated in pages of at most 25. Rows are grouped and come back ordered by action name ("Following" before "Unfollowing") and then by twitter_id as a string, not newest-first; use `date` to look at a specific day.

**Required:** one of `username`, `twitter_id`.
**Nested fields**

- `data[].action` (string): "Following" when the account followed the target, "Unfollowing" when it unfollowed.
- `data[].twitter_id` (string): Followed account's numeric Twitter/X id as a string (CONVERT ... CHAR).
- `data[].username` (string): Followed account's handle.
- `data[].name` (string): Followed account's display name. Events whose followed account has no name are dropped by the grouping step (see notes), so this is never null in practice.
- `data[].twitter_score` (number): Followed account's Twitter Score (0-1000 scale) as a float; the main-account score is used, falling back to the graph-side score when the main one is 0.
- `data[].followers_count` (integer): Followed account's follower count at the time of serving (current, not historical).
- `data[].description` (string): Followed account's bio.
- `data[].profile_image_url` (string): Followed account's avatar URL on TwitterScore S3 (https://twitterscore.s3.amazonaws.com/<stored path>), or "https://twitterscore.io/media/profiles/NoImageFound.png" when none (both literals are in the SQL).
- `data[].created_at` (string): Date of the follow/unfollow event, YYYY-MM-DD.
- `data[].tags` (array): Tags of the followed account, de-duplicated; empty array when none.
- `data[].tags[].id` (number): Tag id. Integral, but may be serialised as e.g. 4.0 when the result set contains untagged rows (pandas NULL promotion; see notes).
- `data[].tags[].name` (string): Tag name.
- `data[].categories` (array): Account categories of the followed account, de-duplicated; empty array when none.
- `data[].categories[].id` (number): Category id (same float caveat as tags[].id).
- `data[].categories[].name` (string): Category name.

## Parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `username` | string | no |  | Handle of the account whose outgoing follows to list (surrounding whitespace and trailing slash tolerated). Resolved against current usernames/slugs first, then against previous usernames (renamed accounts). Required unless `twitter_id` is given. |
| `twitter_id` | integer | no |  | Numeric Twitter/X id of the account. Takes precedence over `username` when both are given. Required unless `username` is given. |
| `date` | string | no |  | Only events on this calendar day, format YYYY-MM-DD (DATE() of the recorded action timestamp). Any other format returns {"success": false, "message": "Invalid date format. Use YYYY-MM-DD."}. |
| `tag_ids` | string | no |  | Comma-separated tag ids (see /api/v1/get_tags_list); only events whose followed account carries at least one of these tags are returned (followed accounts with no tag are excluded while this filter is set). If any element is non-numeric the whole list is ignored (no filter); empty elements are skipped. |
| `category_ids` | string | no |  | Comma-separated account-category ids (see /api/v1/get_categories_list); only events whose followed account is in at least one of these categories are returned (uncategorised followed accounts are excluded while set). A list with a non-numeric element is ignored. |
| `page` | integer | no | `1` | 1-based page number. Non-numeric, 0 or negative values are treated as 1; a page past the last returns an empty `data` array. |
| `size` | integer | no | `10` | Rows per page, capped at 25. Values below 1 are treated as 1; a non-numeric value falls back to 10. |

At least one of `username`, `twitter_id` is required.

## Example request

```bash
curl -s "https://twitterscore.io/api/v1/friendshipHistory/following?username=VitalikButerin" \
  -H "X-API-Key: $TWITTERSCORE_API_KEY" \
  -H "User-Agent: my-app/1.0 (contact@example.com)"
```

```python
import os, requests

r = requests.get(
    "https://twitterscore.io/api/v1/friendshipHistory/following",
    params={"username": "VitalikButerin"},
    headers={"X-API-Key": os.environ["TWITTERSCORE_API_KEY"],
             "User-Agent": "my-app/1.0 (contact@example.com)"},
    timeout=15,
)
data = r.json()
if not data.get("success", True):      # errors arrive as success=false (see /developers/errors/)
    raise RuntimeError(data["message"])
print(data)
```

```javascript
const r = await fetch("https://twitterscore.io/api/v1/friendshipHistory/following?username=VitalikButerin", {
  headers: { "X-API-Key": process.env.TWITTERSCORE_API_KEY,
             "User-Agent": "my-app/1.0 (contact@example.com)" },
});
const data = await r.json();
if (data.success === false) throw new Error(data.message);
console.log(data);
```

## Example response

```json
{
  "success": true,
  "total": 143,
  "page": 1,
  "size": 2,
  "pages": 72,
  "data": [
    {
      "action": "Following",
      "twitter_id": "1138033434",
      "username": "paradigm",
      "name": "Paradigm",
      "twitter_score": 884.0,
      "followers_count": 251340,
      "description": "Research-driven crypto investment firm.",
      "profile_image_url": "https://twitterscore.s3.amazonaws.com/profiles/paradigm.jpg",
      "created_at": "2026-09-28",
      "tags": [
        {
          "id": 4,
          "name": "VC"
        }
      ],
      "categories": [
        {
          "id": 2,
          "name": "Venture Capitals"
        }
      ]
    },
    {
      "action": "Following",
      "twitter_id": "2312333412",
      "username": "ethereum",
      "name": "Ethereum",
      "twitter_score": 996.0,
      "followers_count": 3821004,
      "description": "Ethereum is a global, open-source platform for decentralized applications.",
      "profile_image_url": "https://twitterscore.io/media/profiles/NoImageFound.png",
      "created_at": "2026-09-12",
      "tags": [],
      "categories": [
        {
          "id": 1,
          "name": "Projects"
        }
      ]
    }
  ]
}
```

## Errors

Error codes this endpoint can return (see [Errors](/developers/errors/) for the body format): `api_key_missing`, `api_key_invalid`, `api_access_deactivated`, `api_key_revoked`, `invalid_params`, `account_not_found`, `method_not_allowed`, `rate_limited`, `quota_exceeded`, `server_error`.

---

Authentication: `X-API-Key` header (or `Authorization: Bearer`), see [Authentication](/developers/authentication/). Limits: per-minute rate and monthly quota by plan, see [Rate limits](/developers/rate-limits/). Machine-readable definition: [/openapi.json](/openapi.json).