Skip to content

Actions

Every client method, the API call it makes, and what it returns. Click a method for its full signature; click a type in Returns for every field it carries (see Response types). {ws} is a workspace id. List methods return the records already unwrapped from {"items": [...]}.

Names work everywhere. A workspace, detector, guardrail, policy or virtual key argument takes its id, its name, or its record. Detector, guardrail and policy names are unique in a workspace (8.0.2 refuses a duplicate with 409), so a name is looked up in the method's ws_id (org-wide without one). A detector name may also be a built-in detector's name or slug (a custom detector sharing one is refused as ambiguous). Key names are NOT unique: two keys with one name raise ValueError; a key can also be given by its faig_... secret. An unknown name raises LookupError.

Session & raw calls

Method HTTP Returns Notes
login(username, password) POST /api/v1/login None Optional: the client logs in on its first call. Falls back to the legacy /api/login.
close() POST /api/v1/logout None Also runs on leaving a with block.
me() GET /api/v1/user Me The logged-in user: email, role, memberships, ...
default_workspace() GET /api/v1/user, GET /api/v1/me/workspaces (once) str | None Where a call without ws_id goes: workspace= (or FAIG_WORKSPACE), else a workspace login's only workspace. None for an org admin: admin paths.
request(method, path, body, params) any JSON (untyped) Raw management call with auth, CSRF and retries.
get(path, params) GET JSON (untyped)
post(path, body) POST JSON (untyped) Sends {} when there is no body.
put(path, body) PUT JSON (untyped)
patch(path, body) PATCH JSON (untyped)
delete(path) DELETE JSON (untyped)

Users & invitations

Method HTTP Returns Notes
users() GET /api/v1/admin/users list[User]
user(user_id) GET /api/v1/admin/users/{id} User
user_by_email(email) GET /api/v1/admin/users User | None Case-insensitive match; None if absent.
invite(email, role) POST /api/v1/admin/user-invitations Invitation Users exist only via invitation; no email is sent. A second invite while one is pending is refused (422).
invitations() GET /api/v1/admin/user-invitations list[Invitation] Pending invitations.
invitation_by_email(email) GET /api/v1/admin/user-invitations Invitation | None Case-insensitive; None if there is none.
revoke_invitation(invitation_id) DELETE /api/v1/admin/user-invitations/{id} None Needed before re-inviting an address with one pending.
accept_invite(invitation_id, email, password, display_name) POST /api/v1/invitations/{id}/accept AcceptedInvite Unauthenticated; sets the password.
delete_user(user_id) DELETE /api/v1/admin/users/{id} None
make_workspace_admin(user_id, ws_id) GET + PUT /api/v1/admin/users/{id} User Keeps the user's other memberships.

Workspaces

Every method that takes a workspace (ws_id) accepts its id, its name (names are unique), or its record from workspaces() / workspace_by_name(). Names are resolved once and cached; an unknown name raises LookupError.

Method HTTP Returns Notes
resolve_workspace(ws) GET /api/v1/admin/workspaces (or /api/v1/me/workspaces) str A workspace's id from its id, name or record; cached.
workspaces() GET /api/v1/admin/workspaces list[Workspace] Every workspace (org admin).
my_workspaces() GET /api/v1/me/workspaces list[MyWorkspace] Workspaces the caller belongs to.
workspace_by_name(name) GET /api/v1/admin/workspaces Workspace | None
create_workspace(name, admin_ids, provider_ids, description) POST /api/v1/admin/workspaces Workspace Admins must be existing users.
delete_workspace(ws_id) DELETE /api/v1/admin/workspaces/{ws} None
workspace(ws_id) GET /api/v1/workspaces/{ws} WorkspaceSettings Settings: allowedModels, allowedPolicies, budgets, member defaults.
workspace_members(ws_id) GET /api/v1/workspaces/{ws}/members WorkspaceMembers
workspace_budget(ws_id) GET /api/v1/workspaces/{ws}/budget WorkspaceBudget
workspace_analytics(ws_id, frm, to, limit) GET /api/v1/workspaces/{ws}/analytics Analytics Same as analytics(..., ws_id=).

Detectors

Method HTTP Returns Notes
detectors(ws_id=None) GET /api/v1/workspaces/{ws}/detectors or GET /api/v1/admin/detectors list[Detector] Custom detectors.
builtin_detectors(ws_id=None) GET /api/v1/workspaces/{ws}/built-in-detectors or GET /api/v1/admin/built-in-detectors list[BuiltinDetector] Identified by slug id.
detector_by_name(ws_id, name) GET /api/v1/workspaces/{ws}/detectors Detector | None
create_detector(ws_id, body) POST /api/v1/workspaces/{ws}/detectors Detector Build body with regex_detector_body / dlp_detector_body.
update_detector(ws_id, uuid, body) PUT /api/v1/workspaces/{ws}/detectors/{uuid} Detector An active detector changes at once.
delete_detector(uuid, ws_id=None) DELETE /api/v1/workspaces/{ws}/detectors/{uuid} or DELETE /api/v1/admin/detectors/{uuid} None
playground(text, body, ws_id=None) POST /api/v1/workspaces/{ws}/detectors/test or POST /api/v1/admin/detectors/test (builds without it: a regex body is matched locally, checkedLocally) DetectorTest Scan text with an UNSAVED detector body (the console Playground).
test_detector(ws_id, uuid, text) POST /api/v1/workspaces/{ws}/detectors/{uuid}/test DetectorTest Scan with a SAVED detector: matched, score, spans.
resolve_detector(ref, ws_id=None) GET .../detectors (+ built-ins, cached) str A detector's uuid from its uuid, name, slug or record.
ensure_detector(ws_id, body, approve=True) list, then POST or PUT, then approval Ensured Create, update or leave alone, by body["name"]. Returns Ensured.

Guardrails

Method HTTP Returns Notes
guardrails(ws_id=None) GET /api/v1/workspaces/{ws}/guardrails or GET /api/v1/admin/guardrails list[Guardrail]
guardrail(gid, ws_id=None) GET /api/v1/workspaces/{ws}/guardrails/{id} or GET /api/v1/admin/guardrails/{id} Guardrail
guardrail_by_name(ws_id, name) as guardrails Guardrail | None ws_id=None searches org guardrails.
create_guardrail(ws_id, name, detector_ids, description, deny_suspicious_characters=) POST /api/v1/workspaces/{ws}/guardrails Guardrail Needs at least one detector (ids or names).
update_guardrail(ws_id, gid, name, detector_ids, description, deny_suspicious_characters=) PUT /api/v1/workspaces/{ws}/guardrails/{id} Guardrail
delete_guardrail(gid, ws_id=None) DELETE /api/v1/workspaces/{ws}/guardrails/{id} or DELETE /api/v1/admin/guardrails/{id} None
test_guardrail(text, detector_ids, guardrail_id=, deny_suspicious_characters=, ws_id=) POST /api/v1/workspaces/{ws}/guardrails/test or POST /api/v1/admin/guardrails/test (builds without it: one POST .../detectors/{uuid}/test per custom detector; built-ins untested) GuardrailTest The guardrail tester: scans text without an LLM; finalDisposition plus a result per detector.
resolve_guardrail(ref, ws_id=None) GET .../guardrails str A guardrail's id from its id, name or record.
ensure_guardrail(ws_id, name, detector_ids, description, deny_suspicious_characters=, approve=True) list, then POST or PUT, then approval Ensured Returns Ensured.

Policies

Method HTTP Returns Notes
policies(ws_id=None) GET /api/v1/workspaces/{ws}/policies or GET /api/v1/admin/policies list[Policy]
policy(pid, ws_id=None) GET /api/v1/admin/policies/{id} Policy ws_id scopes a name lookup.
policy_by_name(ws_id, name) as policies Policy | None
create_policy(ws_id, name, input_guardrail_ids, output_guardrail_ids, provider_ids=, description=, response_scan_mode=) POST /api/v1/workspaces/{ws}/policies Policy provider_ids grants all of those providers' models; some builds require at least one.
update_policy(ws_id, pid, name, input_guardrail_ids, output_guardrail_ids, provider_ids=, description=, response_scan_mode=) PUT /api/v1/workspaces/{ws}/policies/{id} Policy By an org admin, an edit to an active policy applies at once.
delete_policy(pid, ws_id=None) DELETE /api/v1/workspaces/{ws}/policies/{id} or DELETE /api/v1/admin/policies/{id} None
resolve_policy(ref, ws_id=None) GET .../policies str A policy's id from its id, name or record.
ensure_policy(ws_id, name, input_guardrail_ids, output_guardrail_ids, provider_ids=, description=, response_scan_mode=, approve=True) list, then POST or PUT, then approval Ensured Guardrails by id or name. Returns Ensured.

Approval workflow

Method HTTP Returns Notes
submit(ws_id, kind, obj_id) POST /api/v1/workspaces/{ws}/{kind}/{id}/submit Detector | Guardrail | Policy kind: detectors, guardrails, policies.
withdraw(ws_id, kind, obj_id) DELETE /api/v1/workspaces/{ws}/{kind}/{id}/pending None Cancel a pending submission or change.
approve(kind, obj_id, ws_id=None) POST /api/v1/admin/{kind}/{id}/approve Detector | Guardrail | Policy By name only with ws_id (a name can be pending in several workspaces).
reject(kind, obj_id, reason, ws_id=None) POST /api/v1/admin/{kind}/{id}/reject Detector | Guardrail | Policy As approve.
review_queue() GET /api/v1/admin/review-queue list[ReviewItem] Map an item's type with QUEUE_KIND.

See also approve_new.

Virtual keys

Method HTTP Returns Notes
virtual_keys(ws_id=None, status=) GET /api/v1/workspaces/{ws}/virtual-keys or GET /api/v1/admin/virtual-keys list[VirtualKey]
virtual_key(key_id, ws_id=None) GET /api/v1/workspaces/{ws}/virtual-keys/{id} or GET /api/v1/admin/virtual-keys/{id} VirtualKey Every key call takes ws_id= for the workspace path.
create_virtual_key(ws_id, name, policy_ids=, provider_ids=, expires_at=, tpm=, rpm=) POST /api/v1/workspaces/{ws}/virtual-keys NewVirtualKey The secret is returned once.
update_virtual_key(key_id, expires_at=, tpm=, rpm=, policy_ids=, provider_ids=, ws_id=) GET + PUT .../virtual-keys/{id} VirtualKey Resends the record's writable fields with your changes.
rotate_virtual_key(key_id, ws_id=None) POST .../virtual-keys/{id}/rotate NewVirtualKey New secret, once.
renew_virtual_key(key_id, expires_in_days=, ws_id=) GET, PUT (expired only), then POST .../rotate Renewed A new secret for the same key: rotates an active key, and extends an expired one first (8.0.2 only rotates an active key). Refuses a revoked or suspended key.
revoke_virtual_key(key_id, reason, ws_id=None) POST .../virtual-keys/{id}/revoke VirtualKey The secret stops working; a reason is required.
delete_virtual_key(key_id, ws_id=None) DELETE .../virtual-keys/{id} None
resolve_virtual_key(ref, ws_id=None) GET .../virtual-keys str A key's id from its id, name, record or faig_... secret.
ensure_virtual_key(ws_id, name, policy_ids=, provider_ids=, expires_at=, tpm=, rpm=) list, then POST or GET + PUT Ensured Create the active key name (secret in Ensured.secret) or bring it in line.

Models & what a key can use

Method HTTP Returns Notes
ai_providers() GET /api/v1/admin/ai-providers list[AiProvider]
models() GET /api/v1/admin/models list[Model] Every model: costs, health, provider.
model_groups(ws_id=None) GET /api/v1/workspaces/{ws}/model-groups or GET /api/v1/model-groups list[ModelGroup]
workspace_models(ws_id) GET /api/v1/workspaces/{ws} list[str] The workspace's allowedModels.
grantable_providers(ws_id=None) GET /api/v1/workspaces/{ws}/grantable-providers or GET /api/v1/admin/grantable-providers list[GrantableProvider] Providers, models and upstream keys a key can be granted.
attachable_policies(ws_id) GET /api/v1/workspaces/{ws}/attachable-policies list[Policy] Policies a key in the workspace can attach.
dlp_labels() GET /api/v1/admin/dlp-labels list[DlpLabel] Category names for dlp_detector_body.

Usage, cost & analytics

Dates are date objects or "YYYY-MM-DD"; omitted, the window is the last 30 days. ws_id= switches every call to the workspace path. Values are checked before sending: by workspace | user | key | model; interval hourly | daily | weekly | monthly; end top | bottom | both. Read ranking rows with rank_items(result, end): the API answers items, top/bottom lists, or only meta when nothing was used.

Method HTTP Returns Notes
usage_summary(frm, to, ws_id=) GET .../usage/summary UsageSummary Requests, tokens, previous window, key/user adoption.
usage_trend(frm, to, interval, ws_id=) GET .../usage/trend UsageTrend points: [{at, requests, tokens}].
usage_rankings(frm, to, by, limit, end=, order_by=, interval=, ws_id=) GET .../usage/rankings Rankings order_by: tokens | requests.
usage_breakdown(by, item_id, frm, to, ws_id=) GET .../usage/breakdown Breakdown A key/user/workspace by model; a model by who used it. Rows: breakdown_items(). 404 for a deleted key.
cost_summary(frm, to, ws_id=) GET .../cost/summary CostSummary totals.chargebackSpend, volume, unit costs.
cost_trend(frm, to, interval, ws_id=) GET .../cost/trend CostTrend
cost_rankings(frm, to, by, limit, end=, order_by=, interval=, ws_id=) GET .../cost/rankings Rankings order_by: providerSpend | chargebackSpend | per1kTokens | perRequest.
cost_breakdown(by, item_id, frm, to, ws_id=) GET .../cost/breakdown Breakdown As usage_breakdown, with spend. Rows: breakdown_items().
analytics(frm, to, limit, ws_id=) GET /api/v1/admin/analytics or .../workspaces/{ws}/analytics Analytics Guardrail violations, severity, trend, scanner latency.

Traffic & ICAP logs

Time: range= 24h (default) | 7d | month | all, or start=/end= (datetime or epoch ms). filters= maps a field to a value, a list (is), or {"operator": "is" | "is not" | "contains" | "does not contain", "value": [...]}. Unknown fields or operators raise ValueError: the API would silently ignore them and return every row.

Method HTTP Returns Notes
traffic_logs(range=, start=, end=, filters=, max_items=, page_size=, ws_id=) GET .../traffic-logs Iterator[TrafficLogRow] Iterator; follows nextCursor. Filters: verdict, user, workspace, virtual_key, model, traffic_type, request_path.
traffic_logs_page(cursor, ...) GET .../traffic-logs TrafficLogPage One page with nextCursor, hasNext, total (first page).
traffic_log(uuid, ws_id=) GET .../traffic-logs/{uuid} TrafficLog Full record: verdict, action, detector, guardrail, policy, prompt, cost, latency.
traffic_log_filter_options(range=, start=, end=, ws_id=) GET .../traffic-logs/filter-options TrafficFilterOptions Values each filter can take.
blocked_requests(since=, until=, range=, max_items=, ws_id=) GET .../traffic-logs + one GET .../traffic-logs/{uuid} per row + GET .../virtual-keys list[BlockedRequest] Blocked requests with the prompt, the detectors that fired and why, and the sending key's id, status and owner email (looked up by keyAlias). since alone means since then until now: a poller's last-pull time.
wait_for_traffic(since, filters=, count=1, timeout=60, interval=2, ws_id=) GET .../traffic-logs (polled) list[TrafficLogRow] Rows land seconds after a request: wait for count rows from since on. TimeoutError otherwise.
icap_logs(...) GET .../icap-logs Iterator[dict[str, Any]] Iterator (offset paging). Filters: verdict, direction, user, application, fortigate, shadow_ai, inspection. 404 when ICAP is off.
icap_logs_page(offset, ...) GET .../icap-logs IcapLogPage
icap_log(uuid, ws_id=) GET .../icap-logs/{uuid} dict[str, Any]
icap_log_filter_options(...) GET .../icap-logs/filter-options dict[str, Any]

Audit log & licenses

The audit log takes the same range= / start= / end= and filters= as the traffic log. Filters: user, role, action, message, workspace; spell actions as audit_log_filter_options() lists them (Approve, Create, ...).

Method HTTP Returns Notes
iter_audit_logs(range=, start=, end=, filters=, max_items=, page_size=, ws_id=) GET .../audit-logs Iterator[AuditLogRow] Iterator; follows nextCursor.
audit_logs_page(cursor, ...) GET .../audit-logs AuditLogPage One page.
audit_logs(offset, limit) GET /api/v1/admin/audit-logs AuditLogPage One page by offset, no filters.
audit_log_filter_options(range=, start=, end=, ws_id=) GET .../audit-logs/filter-options AuditFilterOptions Users, roles, actions, workspaces seen.
licenses() GET /api/v1/licenses Licenses Serial, status, end date, GPU mapping.

Gateway (data plane)

Authenticated with a virtual key secret, never the session.

Method HTTP Returns Notes
check_key(api_key) GET /ai/openai/v1/models KeyCheck {"valid", "model_count", "http_status"}.
available_models(api_key) GET /ai/openai/v1/models list[str] Model names the key may call. A model missing here 404s with "model not available to this API key".
can_use_model(api_key, model) GET /ai/openai/v1/models bool model in available_models(api_key).
chat_completion(api_key, model, messages, max_tokens=, temperature=, **extra) POST /ai/openai/v1/chat/completions ChatCompletion A guardrail block is a 200; test it with blocked(). A model the key lacks raises ModelNotAvailable.
chat_completion_stream(api_key, model, messages, max_tokens=, temperature=, **extra) POST /ai/openai/v1/chat/completions (stream: true) Iterator[dict[str, Any]] Yields chunks; a block arrives as a content_filter chunk. collect_stream() joins them.