Browser
Evaluate flags from client-side code with a public token and the OFREP HTTP API.
Browser and mobile code must never hold a secret key. Use the environment's public token instead. A public token is non-secret: it can evaluate flags, but it cannot read your rules or change anything.
Toggld does not ship a browser SDK package. Call the OFREP evaluation endpoints with fetch, or use an OpenFeature OFREP provider.
Find your public token
Open Settings → API Keys. Each environment section has one Public token, marked Non-secret. Select Copy. Public tokens start with ffp_.
Secret keys are shown only once, when you create them. Create a key
Needed for the Management API. Use a key with the management role.
Pasted keys stay in this browser tab and clear when you close it. The docs never send them anywhere. Only requests you run from the API playground use them.
Each environment has exactly one public token. Use the token of the environment that your build targets.
Evaluate one flag
Send a POST request to /ofrep/v1/evaluate/flags/{key}. Put the user's attributes under context, and include a stable targetingKey so that percentage rollouts stay consistent.
const API_URL = "https://api.toggld.io";
const PUBLIC_TOKEN = "ffp_YOUR_PUBLIC_TOKEN";
export async function getBooleanFlag(
key: string,
fallback: boolean,
context: Record<string, unknown>,
): Promise<boolean> {
try {
const response = await fetch(`${API_URL}/ofrep/v1/evaluate/flags/${encodeURIComponent(key)}`, {
method: "POST",
headers: {
Authorization: `Bearer ${PUBLIC_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ context }),
signal: AbortSignal.timeout(3000),
});
if (!response.ok) return fallback;
const result = await response.json();
return typeof result.value === "boolean" ? result.value : fallback;
} catch {
return fallback; // network error or timeout
}
}
const showNewCheckout = await getBooleanFlag("new-checkout", false, {
targetingKey: "user-123",
plan: "pro",
});A successful response is HTTP 200:
{ "key": "new-checkout", "value": true, "reason": "TARGETING_MATCH", "variant": "on" }The response has metadata when the flag has metadata.
Evaluate every flag
Send a POST request to /ofrep/v1/evaluate/flags to evaluate every flag of the environment in one request. Use it on page load, then read values from the result.
const response = await fetch("https://api.toggld.io/ofrep/v1/evaluate/flags", {
method: "POST",
headers: {
Authorization: "Bearer ffp_YOUR_PUBLIC_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ context: { targetingKey: "user-123" } }),
});
const { flags } = await response.json();
const values = new Map(
flags.filter((flag) => !("errorCode" in flag)).map((flag) => [flag.key, flag.value]),
);
const showNewCheckout = values.get("new-checkout") ?? false;The bulk response mixes successes and per-flag failures:
{
"flags": [
{ "key": "new-checkout", "value": true, "reason": "STATIC", "variant": "on" },
{ "key": "pricing-test", "errorCode": "TARGETING_KEY_MISSING", "errorDetails": "…" }
]
}A bulk response returns HTTP 200 even when some flags fail. Check each entry for errorCode.
Handle errors
Always keep a safe fallback value in code. Use it when any of these happen:
| Response | Cause | Body |
|---|---|---|
| Network error or timeout | The request did not complete. | None |
| 400 | Evaluation failed, for example a rollout without a targeting key. | { "key", "errorCode", "errorDetails" } |
| 400 | The request body is not valid JSON (PARSE_ERROR) or has the wrong shape (INVALID_CONTEXT). | { "key", "errorCode", "errorDetails" }, without key for bulk evaluation |
| 401 | The token is missing or wrong. | { "_tag": "Unauthorized", "message" } |
| 404 | No flag with this key exists in the environment. | { "key", "errorCode": "FLAG_NOT_FOUND" } |
| 429 | You reached a rate limit. Wait for the Retry-After seconds. | { "code": "RATE_LIMITED", "message" } |
| 503 | A dependency is unavailable. Retry later. | Varies |
See Errors for every error code.
Cross-origin requests (CORS)
The OFREP endpoints accept requests from any origin:
- Allowed method:
POST. - Allowed request headers:
AuthorizationandContent-Type. - Exposed response header:
Retry-After. - Cookies are not used. Do not send
credentials: "include". - Browsers can cache the preflight response for 10 minutes.
Only the OFREP endpoints allow cross-origin requests. The Management API and the sync API do not, and public tokens cannot use them anyway.
What public tokens cannot do
| Action | Public token |
|---|---|
| Evaluate one flag or every flag | Yes |
| Download flag definitions for local evaluation | No. HTTP 403. |
| Read or change flags, segments, environments, or keys | No. HTTP 403. |
| Read analytics or the audit log | No. HTTP 403. |
You cannot rotate or revoke a public token. It stops working only when you delete its environment.
Privacy and safety
- Everything in a response is public. Anyone who loads your page can call the API with your public token and read the evaluated values and metadata. Never put secrets in variant values or metadata.
- Rules stay private. A public token returns evaluated values only. It never returns targeting rules or segment members.
- Send only the context you need. The context goes to Toggld with each evaluation. Evaluation analytics do not store it.
- Use a stable targeting key. For signed-in users, use the user ID. For anonymous visitors, generate a random ID and store it, for example in local storage.
Limits
Public tokens have their own rate limits: 120 requests per minute per IP address and environment, and 6,000 requests per minute per environment across all IP addresses. Use the bulk endpoint once per page load instead of one request per flag.
The API counts these evaluations for Analytics. Do not report them again through the telemetry endpoint.