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

# Manage multiple X (Twitter) accounts for users

> Connect your users' X (Twitter) accounts from your own product, with a hosted link or the API. Your users need no Xquik signup, and connecting is free.

> For the complete documentation index, see [llms.txt](https://docs.xquik.com/llms.txt).

Your users connect their X (Twitter) accounts while staying in your product.
They need no Xquik signup, and each account belongs to your Xquik account.
Connecting is free.

| | Connect link | Direct API |
| - | - | - |
| Who collects the password | A page Xquik hosts | Your own form |
| What your backend receives | The result only | The X password & 2FA secret |
| Key you need | Full access | Full access, plus **Connect X accounts** |
| Best for | Most products | Products that must keep every step in their own UI |

Start with a connect link. Choose the direct API only if your product must own the form.

## Use a connect link

Create a link from your backend.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/bash.json","/languages/csharp.json","/languages/go.json","/languages/java.json","/languages/javascript.json","/languages/kotlin.json","/languages/php.json","/languages/python.json","/languages/ruby.json","/languages/typescript.json"]}}
curl -X POST https://xquik.com/api/v1/x/account-connection-links \
  -H "x-api-key: $XQUIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reference": "crm-user-7", "returnUrl": "https://app.example.com/connected" }'
```

Open the answer's `url` in a pop-up or a new tab. The page can't load in a frame.
The person enters their X username, email, password & Authenticator App 2FA secret there.
The page names your Xquik account, and asks for any code X emails them.




Then [read the link](https://docs.xquik.com/api-reference/x-accounts/get-connection-link.md) with its `id`.
Once `status` reads `connected`, you get `accountId`, `xUserId`, `xUsername`, `health` & your `reference`.

### What a link protects

* A link works for 30 minutes and connects 1 account. Only its hash is stored.
* 5 refused logins end a link, so it can't be used to guess passwords.
* The page takes the token out of the address bar, and sends no cookies.
* It offers your `returnUrl` as a button. It never redirects by itself.
* Send `accountId` to make a reconnect link. It refuses a sign-in for any other X account.

Treat `url` like a password until it's used. Keep it out of logs & analytics. [Revoke it](https://docs.xquik.com/api-reference/x-accounts/revoke-connection-link.md) if you send it to the wrong person.

## Use the direct API

> [!WARNING]
>
> With this path, your backend receives each user's X password and 2FA secret.
> [Your duties](#your-duties) lists what that makes you responsible for.

### Turn on the permission

Open [dashboard.xquik.com/api-keys](https://dashboard.xquik.com/api-keys) and edit a key.
Turn on **Connect X accounts**. It starts off on every key.
Full access doesn't include it, and only a signed-in dashboard session can change it.




A key without it gets `403 x_account_connect_permission_required`.
OAuth tokens and MCP tools always get `403 session_required`. X passwords never reach a model.

### Connect an account

Generate a `connection_attempt_id` first. You can then read the result even if the response never arrives.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/bash.json","/languages/csharp.json","/languages/go.json","/languages/java.json","/languages/javascript.json","/languages/kotlin.json","/languages/php.json","/languages/python.json","/languages/ruby.json","/languages/typescript.json"]}}
curl -X POST https://xquik.com/api/v1/x/accounts \
  -H "x-api-key: $XQUIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "username": "your_x_username",
  "email": "account@example.com",
  "password": "<ACCOUNT_PASSWORD>",
  "totp_secret": "<TOTP_SECRET>",
  "connection_attempt_id": "xatt_0123456789abcdef0123456789abcdef"
}
JSON
```

`totp_secret` is the long Authenticator App key, not a 6-digit code.
[Connect X account](https://docs.xquik.com/api-reference/x-accounts/connect.md) explains how a user finds it.

### Handle each answer

| Answer | What it means | What to do |
| - | - | - |
| `201` | The account connected. | Save `id`. Pass it or `xUsername` as `account` on later calls. |
| `202` with `pending` | The sign-in is still running. | Wait for `Retry-After`, then read [the attempt](https://docs.xquik.com/api-reference/x-accounts/connection-attempt.md). Don't start again. |
| `202` with `requires_email_code` | X sent the user an email code. | Ask for it, then send it to [submit](https://docs.xquik.com/api-reference/x-accounts/submit-challenge.md). |
| `422` | X refused the login. | Show `message` and ask the user to check their details. |
| `409` | Xquik already has this account. | Tell the user to disconnect it where they first connected it. |
| `429` | The login has to wait. | Wait for `Retry-After`, then try once. |

A successful attempt read gives `accountId` too.

### Reconnect, retry & disconnect

When a password changes or `health` reads `needsReauth`, call [reconnect](https://docs.xquik.com/api-reference/x-accounts/reauth.md) with the new password.
It answers like a connect. It refuses a sign-in that belongs to another X account.




[Bulk retry](https://docs.xquik.com/api-reference/x-accounts/bulk-retry.md) clears passing failures, so you never send a password for those.
[Disconnect](https://docs.xquik.com/api-reference/x-accounts/disconnect.md) removes an account and its stored session.




Account activity records each connect, reconnect & disconnect with the key's ID.

### Your duties

Your product collects X passwords, so these become your job.

* Tell users you collect their password and send it to Xquik.
* Send it only over HTTPS, and only from your backend.
* Keep request bodies out of your logs, traces, error reports & analytics.
* Never store the password or 2FA secret once Xquik answers.
* Keep this key in a secret store, and set its allowed IPs.
* Use a separate key for connecting, and pause it when you don't need it.

Xquik encrypts credentials at rest and never returns them.

## Act as each account

Send `account` on each write and DM call to pick which connected account acts.
[List X accounts](https://docs.xquik.com/api-reference/x-accounts/list.md) gives each account's `status` and `health`.

## Limits

These hold on both paths. Failed logins slow a caller down. Each account you connect lifts that limit, so onboarding many users isn't capped.
A caller with no connected accounts gets 10 failed logins per 15 minutes.
One X account gets 5 refused logins per 15 minutes, across all callers.
A `429` always says how long to wait.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.