Developer Docs

Authentication

Secure your API requests with JWT access tokens, refresh tokens, and OAuth integrations.

Authentication

TRCR uses JSON Web Tokens (JWT) for authentication. Every API request must include a valid access token in the Authorization header. Access tokens are short-lived (15 minutes) and can be refreshed using a long-lived refresh token (30 days).

Important: Never expose your refresh token in client-side code or public repositories. Store it securely (e.g., in an HTTP-only cookie or secure server-side storage).

Register a New Account

Create a new user account. The response includes both access and refresh tokens so the user is immediately authenticated.

curl -X POST https://api.trcr.pro/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securePassword123",
    "full_name": "Jane Doe"
  }'

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
  "token_type": "Bearer",
  "expires_in": 900,
  "user": {
    "id": "usr_abc123",
    "email": "user@example.com",
    "full_name": "Jane Doe",
    "avatar_url": null,
    "email_verified": false,
    "timezone": "UTC",
    "locale": null
  }
}

locale is the user's preferred language (BCP-47 code) and is null until set via a profile update — clients should fall back to browser language detection while it is unset.

Log In

Authenticate with email and password to receive tokens.

curl -X POST https://api.trcr.pro/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "securePassword123"}'

Token Refresh

Access tokens expire after 15 minutes. Use the refresh token to obtain a new access token without requiring the user to log in again. Refresh tokens are valid for 30 days and are rotated on each use -- the response includes a new refresh token and the old one is invalidated.

curl -X POST https://api.trcr.pro/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "dGhpcyBpcyBhIHJlZnJl..."}'

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "bmV3IHJlZnJlc2ggdG9r...",
  "token_type": "Bearer",
  "expires_in": 900
}

Logout

Invalidate the current refresh token. The access token will remain valid until it expires naturally (up to 15 minutes).

curl -X POST https://api.trcr.pro/api/v1/auth/logout \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "dGhpcyBpcyBhIHJlZnJl..."}'

Forgot Password

Initiate a password reset by sending a reset link to the user's email. Returns 200 OK regardless of whether the email exists (to prevent enumeration).

curl -X POST https://api.trcr.pro/api/v1/auth/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Reset Password

Complete the password reset using the token from the email link.

curl -X POST https://api.trcr.pro/api/v1/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{"token": "RESET_TOKEN", "password": "newSecurePass123"}'

Verify Email

Verify a user's email address using the token sent in the verification email. This marks the account as verified.

curl -X POST https://api.trcr.pro/api/v1/auth/verify-email \
  -H "Content-Type: application/json" \
  -d '{"token": "VERIFY_TOKEN"}'

OAuth Authentication

TRCR supports OAuth login via GitHub and Google using the standard OAuth 2.0 authorization code flow. The server holds the provider client secret and performs the code exchange, so your application never handles the provider code directly.

1. Start the Flow

Send the user to the authorize endpoint for the provider. The endpoint returns the provider authorization URL to redirect the browser to, along with an opaque state value the server uses to protect the callback.

# GitHub
GET https://api.trcr.pro/api/v1/auth/github/authorize

# Google
GET https://api.trcr.pro/api/v1/auth/google/authorize

Response:

{
  "url": "https://github.com/login/oauth/authorize?client_id=...&state=...",
  "state": "oas_a1b2c3..."
}

2. Provider Redirects to the Callback

After the user authorizes, the provider redirects back to the API's own callback (https://api.trcr.pro/api/v1/auth/{provider}/callback), where the server exchanges the code for tokens. For the web flow (no redirect_uri supplied at authorize time), the callback responds with the same JSON token payload as the login endpoint — you receive an access token and refresh token.

Native (Mobile) OAuth

Native apps pass an allow-listed custom-scheme redirect_uri when starting the flow. The value must begin with trcr://; any other scheme is ignored and the request falls back to the web flow.

# Begin the native flow with a custom-scheme redirect_uri
GET https://api.trcr.pro/api/v1/auth/github/authorize?redirect_uri=trcr://auth/callback

The provider redirect target is still the API's own callback ({PUBLIC_API_URL}/auth/{provider}/callback) — the server controls the final hop. After exchanging the code, the callback issues a 302 redirect to your custom scheme with the tokens in the URL fragment (the fragment is never sent to a server):

HTTP/1.1 302 Found
Location: trcr://auth/callback#access_token=eyJhbGci...&refresh_token=dGhpcyBp...&token_type=Bearer&expires_in=900

The app captures the full callback URL (for example from ASWebAuthenticationSession on iOS) and parses the tokens from the fragment.

Setup: Register {PUBLIC_API_URL}/auth/{provider}/callback (e.g. https://api.trcr.pro/api/v1/auth/github/callback) as an authorized redirect URI in your GitHub and Google OAuth applications. The same value is used for both the web and native flows.

WebSocket Authentication

WebSocket connections use a ticket-based authentication system to avoid sending tokens in query strings. The flow has two steps:

1. Obtain a WebSocket Ticket

Request a one-time ticket via REST. Tickets expire after 30 seconds.

curl -X POST https://api.trcr.pro/api/v1/auth/ws-ticket \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
  "ticket": "wst_a1b2c3d4e5f6..."
}

2. Connect with the Ticket

Open a WebSocket connection and send the ticket as the first message:

import WebSocket from "ws";

const ws = new WebSocket("wss://api.trcr.pro/ws");

ws.on("open", () => {
  ws.send(JSON.stringify({
    action: "authenticate",
    payload: { ticket: "wst_a1b2c3d4e5f6..." }
  }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data.toString());
  if (msg.status === "authenticated") {
    console.log("Connected and authenticated");
  }
});

Using Tokens in Requests

Include the access token in the Authorization header for every API request:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

If the token is expired or invalid, the API returns a 401 Unauthorized response. Your application should catch this, use the refresh token to get a new access token, and retry the request.

Token Payload

The JWT access token payload contains the following claims:

{
  "sub": "usr_abc123",         // user ID
  "org": "org_xyz789",         // active organization ID
  "role": "admin",             // role in the organization
  "iat": 1711612800,           // issued at
  "exp": 1711613700            // expires at (iat + 900s)
}

Security Best Practices

  • Store refresh tokens in HTTP-only cookies or secure server-side storage -- never in localStorage.
  • Always use HTTPS when communicating with the API.
  • Rotate refresh tokens on every use (the API does this automatically).
  • Implement token refresh logic that retries failed requests after obtaining a new access token.
  • Log out users by invalidating their refresh token when they sign out.