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

# Authorize

> Send the user's browser here to log in and consent. Redirects to your callback with an authorization code.

export const AuthorizeUrlBuilder = ({showEnvSelect = true, defaultEnv = "sandbox"}) => {
  const [env, setEnv] = useState(defaultEnv);
  const [clientId, setClientId] = useState("");
  const [codeChallenge, setCodeChallenge] = useState("");
  const [copied, setCopied] = useState(false);
  const [state] = useState(() => "st_" + Math.random().toString(36).slice(2, 10));
  const domain = env === "production" ? "login.taxrock.com" : "login-demo.taxrock.com";
  const enc = encodeURIComponent;
  const url = "https://" + domain + "/authorize" + "?response_type=code" + "&client_id=" + enc(clientId || "YOUR_CLIENT_ID") + "&redirect_uri=" + enc("http://localhost:0000") + "&scope=" + enc("offline_access read:client-accounts") + "&audience=" + enc("https://delegate.api.taxrock.com") + "&code_challenge=" + enc(codeChallenge || "YOUR_CODE_CHALLENGE") + "&code_challenge_method=S256" + "&state=" + state;
  const copy = () => {
    navigator.clipboard.writeText(url).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    });
  };
  const label = {
    display: "block",
    fontSize: "13px",
    fontWeight: 600,
    marginBottom: "4px"
  };
  const field = {
    width: "100%",
    boxSizing: "border-box",
    padding: "8px 10px",
    border: "1px solid rgba(128,128,128,0.35)",
    borderRadius: "8px",
    background: "transparent",
    color: "inherit",
    fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
    fontSize: "13px"
  };
  return <div style={{
    border: "1px solid rgba(128,128,128,0.25)",
    borderRadius: "12px",
    padding: "16px",
    margin: "16px 0",
    display: "flex",
    flexDirection: "column",
    gap: "12px"
  }}>
      {showEnvSelect && <div>
          <label style={label}>environment</label>
          <select style={field} value={env} onChange={e => setEnv(e.target.value)}>
            <option value="sandbox">Sandbox</option>
            <option value="production">Production</option>
          </select>
        </div>}
      <div>
        <label style={label}>client_id</label>
        <input style={field} value={clientId} onChange={e => setClientId(e.target.value)} placeholder="YOUR_CLIENT_ID" spellCheck={false} />
      </div>
      <div>
        <label style={label}>
          code_challenge{" "}
          <span style={{
    fontWeight: 400,
    opacity: 0.7
  }}>(from step 1)</span>
        </label>
        <input style={field} value={codeChallenge} onChange={e => setCodeChallenge(e.target.value)} placeholder="YOUR_CODE_CHALLENGE" spellCheck={false} />
      </div>
      <div style={{
    fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
    fontSize: "12px",
    lineHeight: 1.5,
    wordBreak: "break-all",
    padding: "10px 12px",
    border: "1px solid rgba(128,128,128,0.2)",
    borderRadius: "8px",
    background: "rgba(128,128,128,0.06)",
    opacity: clientId && codeChallenge ? 1 : 0.7
  }}>
        {url}
      </div>
      <div>
        <button onClick={copy} style={{
    padding: "8px 16px",
    borderRadius: "8px",
    border: "none",
    background: "#0072e1",
    color: "#fff",
    fontWeight: 600,
    fontSize: "14px",
    cursor: "pointer"
  }}>
          {copied ? "Copied!" : "Copy authorize URL"}
        </button>
      </div>
    </div>;
};

Open this URL in the user's browser to start the connect flow. The user logs in to TaxRock
and consents. TaxRock redirects to your registered callback with `?code=...&state=...`.
This is an interactive browser redirect, not a JSON endpoint. Verify the `state` value does not change, and
exchange the returned `code` at [Get or refresh a token](/api-reference/authentication/token).

Pick your environment, paste your `client_id` and `code_challenge`, then copy the URL:

<AuthorizeUrlBuilder />

## Query parameters

<ParamField query="response_type" type="string" required>
  Must be `code`.
</ParamField>

<ParamField query="client_id" type="string" required>
  Your client ID for the environment.
</ParamField>

<ParamField query="redirect_uri" type="string" required>
  Your callback URL, registered with TaxRock.
</ParamField>

<ParamField query="scope" type="string" required>
  Space-delimited. Use `offline_access read:client-accounts`. The `offline_access` scope is
  what yields a refresh token.
</ParamField>

<ParamField query="audience" type="string" required>
  `https://delegate.api.taxrock.com` (the same in both environments).
</ParamField>

<ParamField query="code_challenge" type="string" required>
  The PKCE S256 challenge derived from your `code_verifier`.
</ParamField>

<ParamField query="code_challenge_method" type="string" required>
  Must be `S256`.
</ParamField>

<ParamField query="state" type="string">
  An opaque value echoed back to your callback. Verify it matches what you sent.
</ParamField>

See the [Authentication Details](/authentication-details) reference for more information.
