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

# Account Linking

> Let one player sign in with several credentials — device, email, or a social account.

export const Scope = ({children}) => <Info>
    <b>Scope:</b> {children}
  </Info>;

A Flock player is **one account that can hold several credentials**. The same player might start
on a device ID, add an email and password later, and attach Google after that — signing in with
any one of them lands on the same account, with the same progress.

This is what makes device-first onboarding safe. A player can start instantly with no sign-up
form, then attach a real credential once they're invested, and keep everything if they lose the
device.

<Scope>credentials belong to a **player**; a player belongs to a game.</Scope>

## The credential types

`device_id`, `email`, `google`, `apple`, `facebook`, `steam`, and `discord`. A player can hold at
most one of each — linking a second Google account to the same player is rejected rather than
silently replacing the first.

<Tabs>
  <Tab title="Unity">
    Linking lives on the authentication provider, beside the login calls, and every method needs
    a **signed-in player**.

    ```csharp theme={null}
    // What is this player currently able to sign in with?
    List<PlayerLinkedAccount> accounts =
        await FlockClient.Instance.Authentication.GetLinkedAccountsAsync();

    // Attach an email/password credential to the signed-in player.
    accounts = await FlockClient.Instance.Authentication.LinkEmailAsync("player@example.com", "hunter2");

    // Attach a social credential using the same token your login flow already obtains.
    accounts = await FlockClient.Instance.Authentication.LinkGoogleAsync(idToken);

    // Detach one.
    accounts = await FlockClient.Instance.Authentication.UnlinkAsync(FlockCredentialProvider.Google);
    ```

    There is one method per provider — `LinkEmailAsync`, `LinkDeviceAsync`, `LinkGoogleAsync`,
    `LinkAppleAsync`, `LinkFacebookAsync`, `LinkSteamAsync`, `LinkDiscordAsync` — each taking the
    same token your login path already gets from that platform. `UnlinkAsync` takes a
    `FlockCredentialProvider` instead.

    **Every one of these returns the full, updated credential list**, so link and unlink double as
    a refresh — you rarely need to call `GetLinkedAccountsAsync` again straight afterwards.

    Each `PlayerLinkedAccount` carries `Provider`, `ProviderUserId`, `Email`, and `EmailVerified`.

    <Warning>
      **A player cannot unlink their last credential.** Removing it would leave an account nobody
      can sign in to, so the server refuses with
      `FlockErrorCode.PlayerCannotUnlinkLastCredential`. Disable the unlink button when the list
      has one entry rather than letting the player discover this as an error.
    </Warning>

    **Errors worth handling by name:**

    | Code                               | Means                                                                        |
    | ---------------------------------- | ---------------------------------------------------------------------------- |
    | `PlayerAccountAlreadyLinked`       | That credential is already attached — to this player, or to a different one. |
    | `PlayerAccountNotLinked`           | Unlinking something the player doesn't have.                                 |
    | `PlayerCannotUnlinkLastCredential` | The last remaining sign-in method.                                           |
    | `PlayerInvalidLinkRequest`         | The token was rejected by the provider.                                      |

    <Note>
      **There is no account-merge flow.** If a credential already belongs to a *different* player,
      linking fails with `PlayerAccountAlreadyLinked` — Flock will not fold two players' progress
      together, because there is no safe general answer to which save wins. Decide in your game
      what to offer: keep the current account, or sign out and into the other one.
    </Note>

    Credential state is never cached and never queued offline — it is security state, and a stale
    answer is worse than no answer. Every call goes to the server.
  </Tab>
</Tabs>

## Password resets on a linked email

`ResetPasswordAsync` works for a player who signed in **with** an email, and also for one who
linked an email during this session.

The SDK learns what's linked from the credential list, and deliberately doesn't persist that
across restarts. So after a restored session, call `GetLinkedAccountsAsync()` once before
offering a password reset — otherwise the SDK doesn't yet know the player has an email to reset.

<Note>
  Account linking is available in the [Unity SDK](/sdk/unity). Unreal support is not yet
  available.
</Note>

See [Players & Auth](/authentication) for the sign-in calls themselves.
