Welcome to The Crimson Market Developers Portal

Build powerful integrations with The Crimson Market API. Create OAuth applications, manage your credentials, and access our comprehensive documentation to bring trading functionality to your platform.

Developers Documentation

TCM OAuth Integration Docs

SDK-backed guidance for @crimsoncorp/oauth-react, plus portal-specific setup details for apps, scopes, and redirect registration.

React Quickstart

Recommended browser integration using useTcmOAuth with automatic popup or redirect selection.

SDK snapshot 21344f2c

Use useTcmOAuth when your app already has a server route for exchange and you want the SDK to choose popup vs redirect automatically.

Basic Usage

import { useTcmOAuth } from "@crimsoncorp/oauth-react";

export function LoginActions() {
  const oauth = useTcmOAuth<{ userId: string }>({
    clientId: process.env.NEXT_PUBLIC_TCM_CLIENT_ID!,
    tcmWebUrl: process.env.NEXT_PUBLIC_TCM_OAUTH_WEB_URL!,
    exchangeEndpoint: "/api/auth/tcm/oauth-exchange",
    callbackPath: "/auth/tcm/callback",
    interactionMode: "auto",
    onSuccess: ({ userId }) => {
      console.log("Logged in", userId);
    },
    onError: (error) => {
      console.error(error.code, error.message);
    },
  });

  return (
    <>
      <button onClick={() => void oauth.startLogin()} disabled={oauth.authenticating}>
        {oauth.authenticating ? "Please wait..." : "Open provider chooser"}
      </button>
      <button onClick={() => void oauth.startLogin("discord")} disabled={oauth.authenticating}>
        Continue with Discord
      </button>
    </>
  );
}

startLogin() opens the TCM provider chooser with prompt=select_provider. startLogin("discord") or another provider value forces that provider with provider=<provider>&prompt=login.

If the app should always start Google immediately, set googleOnly: true and call startLogin() without a provider argument.

Migrating to 1.3.0

startLogin(provider) now carries provider intent through the OAuth authorize request. Use it only when the app must require that provider, for example startLogin("twitch") for a Twitch-gated admin tool.

If your app previously passed a provider only to influence the initial UI, switch to startLogin() so the user gets the provider chooser.

Scopes

Omit scope when the OAuth client has one allowed scope in the Developers portal. The SDK will resolve that client policy before starting login.

If the client is allowed to request multiple scope sets, pass an explicit value such as scope: "profile email" or the narrowest scope set your app needs. The requested scopes must already be allowed on the OAuth client, otherwise the OAuth server will reject the authorization request.

Return Shape

The hook returns:

  • authenticating
  • phase
  • error
  • resolvedInteractionMode
  • startLogin(provider)
  • clearError()

resolvedInteractionMode becomes "popup" or "redirect" once the SDK decides which path it is taking.

Interaction Modes

useTcmOAuth supports:

interactionMode: "auto" | "popup" | "redirect"

Recommended default:

interactionMode: "auto"

Behavior:

  • auto chooses popup on desktop-like environments
  • auto chooses redirect on mobile-like environments
  • if popup opening is blocked, the SDK falls back to redirect by default

You can disable popup fallback with:

fallbackToRedirect: false

If you want a specific post-login landing route for redirect flows:

returnTo: "/account"

Diagnostics

By default, route-backed exchange requests send x-tcm-flow-id and x-tcm-message-id in development and staging. Override with:

diagnostics: "always"
diagnostics: "never"

Callback Page

Render the SDK callback component on your app origin:

import { TcmOAuthCallbackPage } from "@crimsoncorp/oauth-react";

export default function Page() {
  return <TcmOAuthCallbackPage />;
}

Recommended path:

"/auth/tcm/callback"

Low-Level Alternative

If you need full control over the exchange request, use useTcmOAuthPopup and provide exchangeCode manually. If you specifically want the older popup-only route-backed behavior, useTcmOAuthPopupRoute remains available as a compatibility API.

Important Constraint

This hook does not make pure browser-only apps fully supported. Popup or redirect can run in the browser, but token exchange still belongs on your server because Portal.Service currently requires client_secret.