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

# Authenticate with CA Colombia API

> CA Colombia API uses cookie-based sessions issued after OAuth with Discord or Roblox. Learn to initiate OAuth, handle callbacks, and manage session expiry.

CA Colombia API authenticates requests using cookie-based sessions. After a player completes OAuth with Discord or Roblox, the API issues two cookies — an access token and a refresh token — which are sent automatically with every subsequent request. You never handle raw tokens directly: the cookies carry the session, and the API silently renews them before they expire.

## How Authentication Works

When a player completes the OAuth flow, the API sets two HTTP cookies on their browser or client:

| Cookie          | Lifetime | Purpose                                 |
| --------------- | -------- | --------------------------------------- |
| `access_token`  | 24 hours | Authenticates each request              |
| `refresh_token` | 8 days   | Used to silently renew the access token |

Every protected endpoint reads the `access_token` cookie on each request. If the token is within **5 minutes of expiry** — or has been marked inactive — the middleware automatically exchanges it for a fresh pair using the `refresh_token` cookie. The renewed cookies are written to the response transparently, so the player's session continues without any action required on your part.

<Note>
  Both cookies are scoped to the `cacolombia.co` domain. If you are running a companion application on a subdomain, ensure your client is configured to send cross-subdomain cookies or proxy requests through the same origin.
</Note>

## Starting the OAuth Flow

Initiate authentication by calling `POST /v1/oauth/:provider`. This endpoint returns a provider authorization URL that you redirect your user to.

**Supported providers**

| Provider | `:provider` value |
| -------- | ----------------- |
| Discord  | `discord`         |
| Roblox   | `roblox`          |

<Warning>
  You must complete Discord OAuth before you can link a Roblox account. The Roblox provider requires an existing user session with a linked Discord account. Attempting the Roblox flow without one will fail and redirect the user to the platform home page.
</Warning>

**Endpoint**

```text theme={null}
POST /v1/oauth/:provider
```

**Request body**

```json theme={null}
{
  "redirectUrl": "https://yourapp.com/auth/callback"
}
```

The `redirectUrl` must be a whitelisted URL. Contact the CA Colombia team to add your domain to the allowlist.

**Response**

```json theme={null}
{
  "targetUrl": "https://discord.com/oauth2/authorize?client_id=...&state=01J9XK2M4N7P3Q8R5T6W",
  "state": "01J9XK2M4N7P3Q8R5T6W"
}
```

Redirect your user to `targetUrl`. Store the `state` value so you can verify it matches when the callback arrives.

**Example**

```bash theme={null}
curl -X POST https://api.cacolombia.com/v1/oauth/discord \
  -H "Content-Type: application/json" \
  -d '{"redirectUrl": "https://yourapp.com/auth/callback"}'
```

## Handling the OAuth Callback

After the player authorizes with the provider, the API handles the callback at:

```text theme={null}
GET /v1/oauth/:provider?state=<state>&code=<code>
```

The API validates the `state` and `code`, retrieves the player's profile from the provider, creates or retrieves their platform account, and then:

1. Sets the `access_token` and `refresh_token` cookies on the response.
2. Redirects the player to your original `redirectUrl` with `?state=<state>` appended.

You do not call this endpoint directly — the provider redirects the player's browser to it automatically. Once the player lands back on your `redirectUrl`, their session cookies are already set and ready to use.

**Callback redirect example**

```text theme={null}
https://yourapp.com/auth/callback?state=01J9XK2M4N7P3Q8R5T6W
```

Use the returned `state` value to match against what you stored in Step 1 to confirm the flow completed for the right session.

## Using Your Session

Once cookies are set, all subsequent API requests are authenticated automatically — no `Authorization` header is required. Simply include cookies in your requests.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.cacolombia.com/v1/users/01J9XK2M4N7P3Q8R5T6W \
    --cookie "access_token=<cookie_value>"
  ```

  ```javascript JavaScript (browser) theme={null}
  // Cookies are sent automatically by the browser for same-origin or
  // credentialed cross-origin requests.
  const response = await fetch("https://api.cacolombia.com/v1/users/01J9XK2M4N7P3Q8R5T6W", {
    credentials: "include"
  });

  const user = await response.json();
  ```

  ```javascript JavaScript (Node.js / server-side) theme={null}
  import axios from "axios";

  const response = await axios.get(
    "https://api.cacolombia.com/v1/users/01J9XK2M4N7P3Q8R5T6W",
    {
      withCredentials: true,
      headers: {
        Cookie: "access_token=<cookie_value>"
      }
    }
  );
  ```
</CodeGroup>

## Token Refresh

Token renewal is fully automatic and transparent. You do not need to implement any refresh logic.

When the auth middleware processes a request and detects the access token is expiring within 5 minutes (or has already been marked inactive), it:

1. Reads the `refresh_token` cookie from the request.
2. Issues a new access token and refresh token pair.
3. Writes the updated cookies to the response.

The new cookies are written on the same response that returns your API data, so the player's next request is already using the fresh token without any round-trip delay.

If the refresh token itself is missing or invalid, the server returns `401 FAILED_TOKEN_RENEWAL` and the player must re-authenticate by starting the OAuth flow again.

## Error Codes

When authentication fails, the API returns a `401` or `403` response with a JSON body containing a `code` field. Use this code to determine what went wrong and how to recover.

| Code                          | HTTP Status | Description                                                                                                                                  |
| ----------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `UNAUTHENTICATED`             | 401         | No session cookie was provided and the endpoint requires authentication. Redirect the user to start the OAuth flow.                          |
| `INVALID_TOKEN_STRUCTURE`     | 401         | The `access_token` cookie is malformed and cannot be parsed. Clear the cookie and re-authenticate.                                           |
| `INVALID_TOKEN`               | 401         | The token was not found in the database — it has likely expired or been invalidated. The cookies are cleared automatically. Re-authenticate. |
| `FAILED_TOKEN_UID_MISSMATCH`  | 401         | The user ID encoded in the token does not match the token record in the database. Re-authenticate.                                           |
| `USER_NOT_FOUND`              | 401         | The token is valid but the associated user account no longer exists.                                                                         |
| `MISSING_FULL_PERMISSIONS`    | 403         | Your account does not have all of the permissions required by this endpoint.                                                                 |
| `MISSING_PARTIAL_PERMISSIONS` | 403         | Your account does not have any of the permissions required by this endpoint.                                                                 |
| `FAILED_TOKEN_RENEWAL`        | 401         | The automatic token refresh failed — either the refresh token is missing, expired, or invalid. Re-authenticate.                              |
| `FAILED_TOKEN_PARSING`        | 401         | An unexpected error occurred while parsing the session token. Re-authenticate.                                                               |

**Error response shape**

```json theme={null}
{
  "error": "Unauthorized",
  "code": "INVALID_TOKEN"
}
```

<Tip>
  Build a central response interceptor in your HTTP client that watches for `401` responses and automatically redirects the player to re-authenticate. This prevents stale sessions from surfacing as unexpected errors in your UI.
</Tip>
