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

# Users and Identity Providers in CA Colombia

> A CA Colombia user account links a Discord identity and a Roblox account. Learn how providers work, what data is stored, and how accounts are created.

Every person who interacts with CA Colombia has a single **user account** that acts as the central identity record on the platform. Your account ties together two external identity sources — Discord and Roblox — and determines what characters you can create, what permissions you hold, and how the API identifies you across every request.

## What Is a User?

A user is a unique platform account identified by a **Snowflake ID** (`userId`). Snowflakes are 64-bit integers encoded as strings — they are time-sortable, globally unique, and safe to store as strings in any language that cannot represent 64-bit integers natively (such as JavaScript's `number` type).

Each user account contains:

| Field             | Type                 | Description                                         |
| ----------------- | -------------------- | --------------------------------------------------- |
| `userId`          | `string` (Snowflake) | Unique identifier for the account                   |
| `permissions`     | `string` (bitfield)  | Encoded permission flags as a decimal string        |
| `maxCharacters`   | `number`             | Maximum number of characters this user may own      |
| `activeCharacter` | `object \| null`     | The user's currently selected character, if any     |
| `characters`      | `array`              | Full list of characters belonging to this user      |
| `createdAt`       | `string` (ISO 8601)  | When the account was first created                  |
| `updatedAt`       | `string` (ISO 8601)  | When the account was last modified                  |
| `providers`       | `array`              | Linked identity providers (returned when requested) |

<Note>
  `userId` is always a string, even though it encodes a 64-bit integer. Never cast it to a JavaScript `number` — you will lose precision on large values. Store and compare it as a string at all times.
</Note>

***

## Identity Providers

CA Colombia uses **OAuth 2.0 identity providers** to authenticate users without managing passwords directly. Each provider stores an external identifier and a snapshot of your profile data from that service.

A provider record contains:

| Field              | Type                    | Description                                                 |
| ------------------ | ----------------------- | ----------------------------------------------------------- |
| `providerId`       | `string` (Snowflake)    | Internal ID for this provider link                          |
| `providerName`     | `"discord" \| "roblox"` | Which external service this record belongs to               |
| `externalId`       | `string`                | Your user ID on the external platform                       |
| `externalMetadata` | `object`                | Profile snapshot (username, avatar, etc.) from the provider |

<CardGroup cols={2}>
  <Card title="Discord" icon="discord">
    **Required for all accounts.** Discord is the primary identity provider. Your account is created the first time you complete Discord OAuth. Your Discord roles within the CA Colombia server also determine your `permissions` bitfield and your `maxCharacters` limit.
  </Card>

  <Card title="Roblox" icon="gamepad-2">
    **Required for character management.** Roblox is the secondary provider. You must link your Roblox account before you can create or manage any in-game characters. Without it, your account exists but cannot interact with the game world.
  </Card>
</CardGroup>

***

## Account Creation Flow

<Steps>
  <Step title="Initiate Discord OAuth">
    Call `POST /v1/oauth/discord` with a `redirectUrl` to receive a `targetUrl`. Redirect your user to that URL to begin the OAuth 2.0 authorization flow with Discord.
  </Step>

  <Step title="Discord callback creates your account">
    After you authorize the application in Discord, the API callback exchanges the authorization code for tokens, fetches your Discord profile and server roles, and either creates a new user account or updates your existing one. Your `permissions` and `maxCharacters` are derived from your Discord roles at this point. Session cookies are set automatically.
  </Step>

  <Step title="Session cookies are issued">
    The API issues a short-lived access token and a longer-lived refresh token, both stored as cookies on your client. These cookies are sent automatically with every subsequent request — no manual token handling is required.
  </Step>

  <Step title="Link your Roblox account">
    Call `POST /v1/oauth/roblox` with a `redirectUrl` to receive a Roblox authorization URL. After you authorize, your Roblox identity is stored as a second provider on your existing account. You can now create characters.
  </Step>
</Steps>

<Warning>
  If you attempt to create a character before linking your Roblox account, the API will return a `403 Unauthorized` response. Linking Roblox is a prerequisite, not optional.
</Warning>

***

## Character Limits

Your `maxCharacters` value is calculated when your Discord data is synced and is based on your roles in the CA Colombia Discord server:

* Every user starts with a base limit of **1 character**.
* Holding the **Membership** role grants **+1 character** slot.
* Holding the **Booster** role grants an additional **+1 character** slot.

The maximum possible `maxCharacters` value is therefore **3**. When the number of characters in the `characters` array equals `maxCharacters`, the API will refuse to create additional characters until you have an available slot.

***

## Example User Object

```json theme={null}
{
  "userId": "1234567890123456789",
  "permissions": "2",
  "maxCharacters": 2,
  "activeCharacter": { "...": "character object" },
  "characters": [],
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": "2024-06-01T08:00:00.000Z"
}
```

<Tip>
  Request the `providers` field explicitly in supported endpoints when you need to display a user's linked accounts or validate that a specific provider is connected.
</Tip>
