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

# Find endpoints

> Find API endpoints that support your token type, key scope, and permissions.

export const ApiEndpointFilters = () => {
  const [snapshot, setSnapshot] = useState(null);
  useEffect(() => {
    let unsubscribe;
    const connect = () => {
      const filter = window.servalApiEndpointFilter;
      if (!filter) return;
      unsubscribe?.();
      const refresh = () => setSnapshot(filter.getSnapshot());
      refresh();
      unsubscribe = filter.subscribe(refresh);
    };
    connect();
    window.addEventListener("serval-api-filter-ready", connect);
    return () => {
      unsubscribe?.();
      window.removeEventListener("serval-api-filter-ready", connect);
    };
  }, []);
  if (!snapshot) return <p role="status">Loading endpoint filters…</p>;
  const {selection, permissions: availablePermissions, endpoints, total} = snapshot;
  const {tokenType, keyScope, fullAccess, permissions, query} = selection;
  const update = patch => window.servalApiEndpointFilter.update(patch);
  const togglePermission = permission => update({
    permissions: permissions.includes(permission) ? permissions.filter(value => value !== permission) : [...permissions, permission]
  });
  const fieldClass = "mt-2 w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100";
  return <div className="not-prose space-y-6">
      <div className="rounded-xl border border-gray-200 p-5 dark:border-gray-800">
        <div className="grid gap-4 sm:grid-cols-2">
          <label className="text-sm font-medium" htmlFor="endpoint-token-type">
            Token type
            <select id="endpoint-token-type" className={fieldClass} value={tokenType} onChange={event => update({
    tokenType: event.target.value
  })}>
              <option value="all">All token types</option>
              <option value="api_key">API key</option>
              <option value="oauth">OAuth (user token)</option>
            </select>
          </label>
          {tokenType === "api_key" && <label className="text-sm font-medium" htmlFor="endpoint-key-scope">
              API key scope
              <select id="endpoint-key-scope" className={fieldClass} value={keyScope} onChange={event => update({
    keyScope: event.target.value
  })}>
                <option value="organization">Organization-scoped</option>
                <option value="team">Team-scoped</option>
              </select>
            </label>}
        </div>
        {tokenType === "api_key" ? <div className="mt-5 space-y-3">
            <label className="flex items-center gap-2 text-sm">
              <input type="checkbox" checked={fullAccess} onChange={event => update({
    fullAccess: event.target.checked
  })} />
              Full-access key (no permission restrictions)
            </label>
            {!fullAccess && <fieldset className="rounded-lg border border-gray-200 p-4 dark:border-gray-700">
                <legend className="px-1 text-sm font-medium">Permissions granted to your key</legend>
                <div className="mb-3 flex gap-4 text-sm">
                  <button type="button" className="underline" onClick={() => update({
    permissions: availablePermissions
  })}>Select all</button>
                  <button type="button" className="underline" onClick={() => update({
    permissions: []
  })}>Clear permissions</button>
                </div>
                <div className="grid max-h-64 gap-2 overflow-y-auto sm:grid-cols-2">
                  {availablePermissions.map(permission => <label key={permission} className="flex items-center gap-2 text-sm">
                      <input type="checkbox" checked={permissions.includes(permission)} onChange={() => togglePermission(permission)} />
                      <span className="font-mono text-xs">{permission}</span>
                    </label>)}
                </div>
              </fieldset>}
            <p className="text-sm text-gray-600 dark:text-gray-400">
              {keyScope === "team" ? "Every team checked by a request must be on the key’s allowlist. Organization and user permissions remain unavailable, even with full access." : "Full access includes the public API key permissions. Some endpoints require a user identity and remain unavailable."}
            </p>
          </div> : tokenType === "oauth" ? <p className="mt-4 text-sm text-gray-600 dark:text-gray-400">These endpoints accept a user token. Your user’s roles, team membership and resource access still determine which requests succeed.</p> : null}
      </div>
      <label className="block text-sm font-medium" htmlFor="endpoint-search">
        Search endpoints
        <input id="endpoint-search" type="search" className={fieldClass} value={query} onChange={event => update({
    query: event.target.value
  })} placeholder="Name, path, method or API group" />
      </label>
      <p role="status" aria-live="polite" className="text-sm text-gray-600 dark:text-gray-400">
        {endpoints.length} of {total} endpoints shown in the API navigation. Open a matching endpoint from the sidebar, or the Navigation menu on a small screen.
      </p>
      {endpoints.length === 0 && <div className="rounded-lg border border-gray-200 p-6 dark:border-gray-800">
          No endpoints match these filters. Check the selected permissions or clear the search.
        </div>}
      <button type="button" className="text-sm underline" onClick={() => window.servalApiEndpointFilter.reset()}>
        Show all endpoints
      </button>
    </div>;
};

Choose the kind of token you use. For API keys, choose organization or team scope and the permissions granted to the key. The filters narrow the existing API groups and endpoint links in the navigation. Your selection stays active as you browse endpoint pages in this tab. Use **Show all endpoints** to restore the full navigation. No token or secret is needed here.

<ApiEndpointFilters />
