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

# Authentication Guide

> Complete guide to authenticating with the Royalti.io API

The Royalti.io API supports multiple authentication methods to suit different integration needs. This guide covers all authentication flows, token management, and best practices.

## Authentication Methods

The API supports four authentication token types, each identified by prefix:

### 1. JWT Tokens (Standard Authentication)

The primary authentication method for user-facing applications.

**Token Prefixes:**

* No specific prefix for JWT tokens
* Detected by JWT structure (header.payload.signature)

**Token Lifecycle:**

* `access_token`: Valid for 6 hours
* `refresh_token`: Valid for 1 day

**Use Case:** Web applications, mobile apps, standard API integrations

### 2. Workspace API Keys (RWAK)

Programmatic access scoped to a specific workspace.

**Token Prefix:** `RWAK`

**Use Case:** Server-to-server integrations, automation scripts, CI/CD pipelines

### 3. User API Keys (RUAK)

Programmatic access scoped to a specific user within a workspace.

**Token Prefix:** `RUAK`

**Use Case:** User-specific automation, personal integrations

### 4. God Keys (GODK)

Super admin system access for platform operations.

**Token Prefix:** `GODK`

**Use Case:** Platform administration, system maintenance (restricted)

<Warning>
  God Keys (GODK) provide unrestricted system access and should only be used by authorized platform administrators. Never share or expose God Keys.
</Warning>

## JWT Authentication Flow

The standard authentication flow for most applications.

### Step 1: Login

Exchange credentials for a refresh token:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.royalti.io/auth/login" \
    -H "Content-Type: application/json" \
    -d '{
      "email": "user@example.com",
      "password": "your_password"
    }'
  ```

  ```javascript JavaScript theme={null}
  const loginResponse = await fetch('https://api.royalti.io/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      email: 'user@example.com',
      password: 'your_password'
    })
  });

  const { refresh_token, workspaces } = await loginResponse.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.royalti.io/auth/login',
      json={
          'email': 'user@example.com',
          'password': 'your_password'
      }
  )

  data = response.json()
  refresh_token = data['refresh_token']
  workspaces = data['workspaces']
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "message": "Successful",
  "workspaces": [
    {
      "workspaceId": "7bd60554-4f63-4c62-a5f6-c29c3f67cb2a",
      "name": "My Workspace",
      "status": "active",
      "userType": [["Artist"]],
      "role": "admin"
    }
  ],
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

<Note>
  The refresh token is stored in Redis cache for validation. Keep it secure and use it only to obtain access tokens.
</Note>

### Step 2: Get Access Token

Exchange the refresh token and workspace selection for an access token:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.royalti.io/auth/authtoken?currentWorkspace=WORKSPACE_ID" \
    -H "Authorization: Bearer YOUR_REFRESH_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const tokenResponse = await fetch(
    'https://api.royalti.io/auth/authtoken?currentWorkspace=WORKSPACE_ID',
    {
      headers: {
        'Authorization': `Bearer ${refresh_token}`
      }
    }
  );

  const { data } = await tokenResponse.json();
  const access_token = data.access_token;
  ```

  ```python Python theme={null}
  response = requests.get(
      'https://api.royalti.io/auth/authtoken',
      params={'currentWorkspace': workspace_id},
      headers={'Authorization': f'Bearer {refresh_token}'}
  )

  access_token = response.json()['data']['access_token']
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "status": "success",
  "message": "Access token generated for My Workspace",
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}
```

### Step 3: Use Access Token

Include the access token in the Authorization header for all API requests:

```bash theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.royalti.io/user" \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.royalti.io/user', {
    headers: {
      'Authorization': `Bearer ${access_token}`
    }
  });
  ```

  ```python Python theme={null}
  response = requests.get(
      'https://api.royalti.io/user',
      headers={'Authorization': f'Bearer {access_token}'}
  )
  ```
</CodeGroup>

## OAuth Social Authentication

The API supports OAuth login via Google, LinkedIn, and Facebook using Passport.js.

### Supported Providers

* **Google OAuth** - `/auth/google`
* **LinkedIn OAuth** - `/auth/linkedin`
* **Facebook OAuth** - `/auth/facebook`

### OAuth Flow

<Steps>
  <Step title="Initiate OAuth">
    Redirect users to the provider's OAuth endpoint:

    ```
    GET /auth/google
    GET /auth/linkedin
    GET /auth/facebook
    ```

    Users will be redirected to the provider's login page.
  </Step>

  <Step title="OAuth Callback">
    After authentication, the provider redirects to our callback URL:

    ```
    GET /auth/google/callback
    GET /auth/linkedin/callback
    GET /auth/facebook/callback
    ```

    The callback exchanges the OAuth code for a session.
  </Step>

  <Step title="Session Cookie">
    OAuth flows use cookie-based refresh token storage for session management.
  </Step>
</Steps>

### Provider Account Linking

Users can link or unlink social providers to their existing account:

**Get Connected Providers:**

```bash theme={null}
GET /auth/social/providers
Authorization: Bearer YOUR_ACCESS_TOKEN
```

**Link a Provider:**

```bash theme={null}
POST /auth/social/{provider}/link
Authorization: Bearer YOUR_ACCESS_TOKEN
```

**Unlink a Provider:**

```bash theme={null}
DELETE /auth/social/{provider}/unlink
Authorization: Bearer YOUR_ACCESS_TOKEN
```

Where `{provider}` is one of: `google`, `facebook`, `linkedin`

### Provider Storage

Social provider IDs are stored in the Users table:

* `googleId` - Google account identifier
* `linkedinId` - LinkedIn account identifier
* `facebookId` - Facebook account identifier

## API Key Authentication

For programmatic access without user interaction.

### Workspace API Keys (RWAK)

Provide access to all resources within a specific workspace.

**Token Format:** `RWAK_xxxxxxxxxxxxxxxx`

**Usage:**

```bash theme={null}
curl -X GET "https://api.royalti.io/artist" \
  -H "Authorization: Bearer RWAK_xxxxxxxxxxxxxxxx"
```

### User API Keys (RUAK)

Provide access scoped to a specific user's permissions within a workspace.

**Token Format:** `RUAK_xxxxxxxxxxxxxxxx`

**Usage:**

```bash theme={null}
curl -X GET "https://api.royalti.io/user" \
  -H "Authorization: Bearer RUAK_xxxxxxxxxxxxxxxx"
```

<Note>
  API keys don't expire but can be revoked. Store them securely like passwords. Contact support to generate API keys for your account.
</Note>

## Token Management

### Token Validation

The authentication middleware validates tokens in this order:

1. Check for `Authorization: Bearer <token>` header
2. Detect token type by prefix (RWAK, RUAK, GODK) or structure (JWT)
3. Validate against Redis cache (for JWT) or database (for API keys)
4. Decode token and lookup associated TenantUser
5. Populate `req.user` with user context

### Workspace Switching

Users can switch between workspaces without re-authenticating:

```bash theme={null}
GET /auth/authtoken?currentWorkspace=NEW_WORKSPACE_ID
Authorization: Bearer YOUR_REFRESH_TOKEN
```

This returns a new access token scoped to the selected workspace.

### Token Refresh

When an access token expires (after 6 hours):

```json theme={null}
{
  "error": {
    "status": 401,
    "message": "JWT token expired"
  }
}
```

Request a new access token using your refresh token:

```bash theme={null}
GET /auth/authtoken?currentWorkspace=YOUR_WORKSPACE_ID
Authorization: Bearer YOUR_REFRESH_TOKEN
```

### Logout

Invalidate your tokens and end the session:

```bash theme={null}
POST /auth/logout
Authorization: Bearer YOUR_ACCESS_TOKEN
```

This removes the refresh token from Redis cache and invalidates the session.

## Multi-Tenant Architecture

All data in Royalti.io is isolated by tenant (workspace).

### Tenant Context

* Every resource has a `TenantId` foreign key
* JWT tokens carry `activeWorkspace` for context
* All queries are automatically scoped to the active tenant
* Users can belong to multiple tenants with different roles

### Custom Domains

Workspaces can use custom domains via Cloudflare SaaS integration:

* Custom domain detected in request
* Authentication middleware maps domain to workspace
* Automatic tenant context without explicit workspace parameter

## Password Management

### Forgot Password

Request a password reset:

```bash theme={null}
POST /auth/forgotpassword
Content-Type: application/json

{
  "email": "user@example.com",
  "redirect_url": "https://app.royalti.io/reset-password"
}
```

Returns a verification token to use with `/auth/resetpassword`.

### Reset Password

Reset password with verification code:

```bash theme={null}
PATCH /auth/resetpassword?code=VERIFICATION_CODE
Authorization: Bearer RESET_TOKEN
Content-Type: application/json

{
  "email": "user@example.com",
  "new_password": "new_secure_password"
}
```

### Set Password

For new users who verified their email:

```bash theme={null}
POST /auth/setpassword
Authorization: Bearer VERIFICATION_TOKEN
Content-Type: application/json

{
  "password": "secure_password_123"
}
```

## Magic Link Authentication

Request a passwordless login link:

```bash theme={null}
POST /auth/loginlink
Content-Type: application/json

{
  "email": "user@example.com"
}
```

A login link will be sent to the user's email. Clicking the link authenticates the user without a password.

## Best Practices

### Security

1. **Use HTTPS Only**
   * All API requests must use HTTPS
   * Verify SSL certificates in production
   * Never transmit tokens over HTTP

2. **Secure Token Storage**
   * Store tokens securely (environment variables, secure vaults)
   * Never commit tokens to version control
   * Use separate tokens for development and production

3. **Token Rotation**
   * Implement token refresh logic before expiration
   * Handle 401 errors by refreshing tokens
   * Re-authenticate if refresh token expires

4. **API Key Management**
   * Treat API keys like passwords
   * Rotate API keys periodically
   * Revoke unused or compromised keys immediately

### Error Handling

Handle authentication errors gracefully:

```javascript theme={null}
async function makeAuthenticatedRequest(url, accessToken, refreshToken) {
  let response = await fetch(url, {
    headers: { 'Authorization': `Bearer ${accessToken}` }
  });

  if (response.status === 401) {
    // Token expired, refresh it
    const newToken = await refreshAccessToken(refreshToken);
    response = await fetch(url, {
      headers: { 'Authorization': `Bearer ${newToken}` }
    });
  }

  return response.json();
}
```

### Rate Limiting

The login endpoint is rate limited:

* **20 requests per 3 minutes per IP address**

Implement exponential backoff for rate limit errors.

## Authentication Middleware

Protected routes use two middleware layers:

1. **basicAuth** - JWT validation, populates `req.user`
2. **auditMiddleware** - Captures user context (userId, role, IP, user agent)

Some endpoints use enhanced authentication:

* **enhancedGodminAuth** - Supports both GODK and JWT with isAdmin=true
* **subscriptionMiddleware** - Validates plan features and limits

## Troubleshooting

### Common Issues

**401 Unauthorized**

* Token expired - refresh your access token
* Invalid token - verify token is correct and not corrupted
* Token not in Redis - re-authenticate to get new tokens

**403 Forbidden**

* Insufficient permissions - check user role and workspace access
* Subscription limitation - verify plan includes requested feature

**Invalid Workspace**

* Workspace ID doesn't exist
* User not member of workspace
* Workspace is inactive

### Debug Tips

1. Verify token format and structure
2. Check token expiration timestamps
3. Confirm workspace ID is correct
4. Validate user has required permissions
5. Check Redis connection for JWT validation

## Support

For authentication issues or API key requests:

* Email: [api@royalti.io](mailto:api@royalti.io)
* Support Center: [support.royalti.io](https://support.royalti.io)
* API Status: [status.royalti.io](https://status.royalti.io)
