> ## 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.

# Connect X account

> Connect an X account to Xquik and prepare the saved TOTP secret key when Authenticator App 2FA is enabled

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

<Callout icon="circle-check" color="#16a34a">
  **Free** - does not consume credits
</Callout>

<Warning>
  Credentials are encrypted at rest and used only for maintaining the connection. Xquik never stores plaintext passwords.
</Warning>

<Info>
  If this X account uses 2FA, prepare `totp_secret` before sending the request. If 2FA is already enabled and you did not save the long secret key, turn Authentication App off and on again in X to reveal a new text secret. Copy it, add it to your authenticator app, finish the 6-digit confirmation on X, then send the saved long key as `totp_secret`.
</Info>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://xquik.com/api/v1/x/accounts \
    -H "x-api-key: xq_YOUR_KEY_HERE" \
    -H "Content-Type: application/json" \
    -d '{
      "username": "elonmusk",
      "email": "elon@example.com",
      "password": "s3cureP@ss",
      "totp_secret": "JBSWY3DPEHPK3PXP"
    }' | jq
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://xquik.com/api/v1/x/accounts", {
    method: "POST",
    headers: {
      "x-api-key": "xq_YOUR_KEY_HERE",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      username: "elonmusk",
      email: "elon@example.com",
      password: "s3cureP@ss",
      totp_secret: "JBSWY3DPEHPK3PXP",
    }),
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://xquik.com/api/v1/x/accounts",
      headers={"x-api-key": "xq_YOUR_KEY_HERE"},
      json={
          "username": "elonmusk",
          "email": "elon@example.com",
          "password": "s3cureP@ss",
          "totp_secret": "JBSWY3DPEHPK3PXP",
      },
  )
  data = response.json()
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
  )

  func main() {
      body, _ := json.Marshal(map[string]interface{}{
          "username":    "elonmusk",
          "email":       "elon@example.com",
          "password":    "s3cureP@ss",
          "totp_secret": "JBSWY3DPEHPK3PXP",
      })

      req, err := http.NewRequest("POST", "https://xquik.com/api/v1/x/accounts", bytes.NewReader(body))
      if err != nil {
          panic(err)
      }
      req.Header.Set("x-api-key", "xq_YOUR_KEY_HERE")
      req.Header.Set("Content-Type", "application/json")

      resp, err := http.DefaultClient.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      var data map[string]interface{}
      if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
          panic(err)
      }
      fmt.Println(data)
  }
  ```
</CodeGroup>

## Headers

<ParamField header="x-api-key" type="string" required>
  Your API key. Session cookie authentication is also supported. Generate a key from the [dashboard](https://xquik.com/dashboard).
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

## Body

<ParamField body="username" type="string" required>
  X username to connect. The `@` prefix is automatically stripped if included.
</ParamField>

<ParamField body="email" type="string" required>
  Email address associated with the X account.
</ParamField>

<ParamField body="password" type="string" required>
  Password for the X account. Encrypted at rest immediately upon receipt.
</ParamField>

<ParamField body="totp_secret" type="string">
  TOTP secret key for accounts with 2FA enabled. This is the base32-encoded secret, not the 6-digit code.
</ParamField>

## 2FA secret key setup

Xquik needs the authenticator app secret key, not a live 6-digit code. The key is the long base32 string X shows while you set up **Authentication App** 2FA, for example `JBSWY3DPEHPK3PXP`.

<CardGroup cols={2}>
  <Card title="Use the secret key" icon="key-round">
    Paste the long base32 key into `totp_secret`. Xquik uses it to generate fresh 2FA codes during login challenges.
  </Card>

  <Card title="Do not use backup codes" icon="ban">
    Do not paste the 6-digit authenticator code, the 12-character backup code, a passkey, or a security key prompt.
  </Card>
</CardGroup>

If you already saved the secret key, send it as `totp_secret`. If you did not save it, create a fresh authenticator app secret on X:

<CardGroup cols={1}>
  <Card title="You saved the key" icon="clipboard-check">
    Paste that saved base32 secret into `totp_secret`. Do not paste the current 6-digit authenticator code.
  </Card>

  <Card title="2FA is on, key is missing" icon="rotate-ccw">
    X shows the text secret only during Authentication App setup. Turn Authentication App off, turn it on again, copy the new key, then finish setup on X.
  </Card>

  <Card title="2FA is not enabled" icon="shield-check">
    Start Authentication App setup on X, reveal the text secret, copy it, add it to your authenticator app, confirm the 6-digit code on X, then connect.
  </Card>
</CardGroup>

1. Open X **Settings and Privacy > Security and Account Access > Security**.
2. Open **Two-Step Verification > Authentication App**.
3. Turn Authentication App off.
4. Turn Authentication App on again.
5. When the QR code appears, choose **Can't scan the QR code?** to reveal the text secret.
6. Copy the long secret key and store it safely before leaving the setup screen.
7. Add that key to your authenticator app if you are setting it up fresh.
8. Finish enabling 2FA on X by entering the current 6-digit code from your authenticator app.
9. Send the saved long key in `totp_secret` when you call Xquik.

<Warning>
  Do not stop after copying the secret key. Complete the X-side 2FA confirmation before starting the Xquik connection, or the key will not work.
</Warning>

<Note>
  Passkeys and security keys cannot satisfy this flow. Use Authenticator App 2FA.
</Note>

## Response

<Tabs>
  <Tab title="201 Created">
    <ResponseField name="id" type="string">Unique account ID.</ResponseField>
    <ResponseField name="xUsername" type="string">Connected X username.</ResponseField>
    <ResponseField name="xUserId" type="string">X user ID.</ResponseField>
    <ResponseField name="status" type="string">Account connection status (e.g. `"active"`).</ResponseField>
    <ResponseField name="health" type="string">Derived login/cookie health. One of `healthy`, `locked`, `needsReauth`, `recovering`, `suspended`, `temporaryIssue`. See [Account health](/api-reference/x-accounts/list#account-health) for meanings.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 timestamp of when the account was connected.</ResponseField>

    ```json theme={null}
    {
      "id": "3",
      "xUsername": "elonmusk",
      "xUserId": "44196397",
      "status": "active",
      "health": "healthy",
      "createdAt": "2026-02-20T08:15:00.000Z"
    }
    ```
  </Tab>

  <Tab title="202 Email Code Required">
    <ResponseField name="object" type="string">Always `x_account_connection_challenge`.</ResponseField>
    <ResponseField name="id" type="string">Challenge ID to submit with the email verification code.</ResponseField>
    <ResponseField name="status" type="string">Always `requires_email_code`.</ResponseField>
    <ResponseField name="expiresAt" type="string">ISO 8601 expiration time for the challenge.</ResponseField>
    <ResponseField name="message" type="string">Human-readable next step.</ResponseField>
    <ResponseField name="username" type="string">X username being connected.</ResponseField>

    ```json theme={null}
    {
      "object": "x_account_connection_challenge",
      "id": "xch_8vGd8Y9JvH6dV0xA",
      "status": "requires_email_code",
      "expiresAt": "2026-05-08T12:10:00Z",
      "message": "Enter the email verification code to continue.",
      "username": "elonmusk"
    }
    ```

    Submit the code to [Submit X Account Email Code](/api-reference/x-accounts/submit-challenge).
  </Tab>

  <Tab title="400 Invalid Input">
    ```json theme={null}
    { "error": "invalid_input", "message": "Invalid input. Check the request body." }
    ```

    Missing `username`, `email`, or `password`, or invalid field format.
  </Tab>

  <Tab title="401 Unauthenticated">
    ```json theme={null}
    { "error": "unauthenticated", "message": "Missing or invalid API key" }
    ```

    Missing or invalid API key.
  </Tab>

  <Tab title="409 Duplicate">
    ```json theme={null}
    { "error": "account_already_connected", "message": "This X account is already connected." }
    ```

    The specified X account is already connected to your Xquik account.
  </Tab>

  <Tab title="429 Rate Limit Exceeded">
    ```json theme={null}
    { "error": "rate_limit_exceeded", "message": "Connection safety limit reached. Try again later.", "retryAfter": 900 }
    ```

    The connection safety limit was reached. The response includes a `Retry-After: 900` header indicating how many seconds to wait before retrying. See the [rate limits guide](/guides/rate-limits) for details.
  </Tab>

  <Tab title="429 Login Cooldown">
    ```json theme={null}
    { "error": "login_cooldown", "message": "Login is temporarily paused", "reason": "automated", "retryAfterMs": 3600000 }
    ```

    A prior login attempt triggered a cooldown (for example, X flagged the session). Wait for `retryAfterMs` before retrying. The response includes a `Retry-After` header in seconds.
  </Tab>

  <Tab title="422 Login Failed">
    ```json theme={null}
    { "error": "login_failed", "message": "Login failed. Check credentials and try again." }
    ```

    X rejected the submitted username, email, password, or TOTP secret. Retry with the current password and the saved Authenticator App secret key, not a 6-digit code.

    ```json theme={null}
    {
      "error": "passkey_required",
      "message": "Passkey verification is not supported. Use Authenticator app 2FA for this X account, then try again."
    }
    ```

    X asked for passkey verification. Switch the account to Authenticator App 2FA, save the long TOTP secret key, finish setup on X, then connect with `totp_secret`.
  </Tab>

  <Tab title="502 X User Lookup Failed">
    ```json theme={null}
    { "error": "x_user_lookup_failed", "message": "X user not found. Check the username." }
    ```

    The X username could not be resolved. Verify the handle is correct and that the account exists.
  </Tab>

  <Tab title="503 Service Unavailable">
    ```json theme={null}
    { "error": "service_unavailable", "message": "Service temporarily unavailable. Try again." }
    ```

    The X connection service is temporarily unavailable. Retry after a short delay.
  </Tab>
</Tabs>

<Note>
  **Related:** [List X Accounts](/api-reference/x-accounts/list) to see all connected accounts, or [Re-authenticate](/api-reference/x-accounts/reauth) if a session expires later.
</Note>
