Identity

Package: agentrouter.identity.v1 Service: IdentityService

Endpoints

Get user

Changed in v0.5.0 (behaviour changes): Reaching a fleet-wide operation now requires an explicit platform binding for a caller that does not hold the admin scope. A management API key that reached one of these operations on a coarse scope alone, such as read or metrics_reader, is refused after this upgrade.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

Changed in v0.2.0 (security updates): Directory lookups through IdentityService.GetUser and ListUsers are now confined to the organizations the calling session belongs to. A signed-in user that held the users_reader scope, including every organization administrator, could previously resolve any user id in any tenant to email, name and role. GetUser now answers "not found" for a user outside the caller's organizations, and ListUsers omits them. A session with no project memberships resolves no users at all, including its own row. This affects users whose only access is an organization-level role, pending invites, and users whose only project is the reserved "default" project. Platform operators keep cross-tenant directory reads only through an explicit platform role binding. In a multi-tenant deployment that binding is a documented provisioning step (docs/runbooks/platform-directory-reach.md).

What it does: Resolves a single user_id to its directory entry (email + name). This is the attribution/display lookup that per-user insights/usage views need: those views key data by the opaque authn.user.id, and this maps that id back to a named person. It is a directory lookup only -- not identity propagation or authorization, and callers must not read the auth DB directly.

Request fields:

FieldRequiredDescription
user_idyesThe user_id to resolve.

Response fields:

FieldRequiredDescription
usernoThe resolved directory entry. Absent only on error (a missing user returns NOT_FOUND, not an empty response).
{"signatures":{"go":"func (x *IdentityClient) GetUser(ctx context.Context, req *identityv1.GetUserRequest) (*identityv1.GetUserResponse, error)","python":"get_user(req: identity_service_pb2.GetUserRequest) -\u003e GetUserResponse","typescript":"getUser(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.GetUserRequestSchema\u003e): Promise\u003cGetUserResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/users/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.GetUserRequest{}\n\n\tresp, err := client.Identity().GetUser(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/getuser\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.GetUserRequest()\ntry:\n    result = client.identity.get_user(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.getUser(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl \"${AGENTROUTER_BASE_URL}/v1/users/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/users/{user_id}","slug":"get-user"}

List users

Changed in v0.5.0 (behaviour changes): Reaching a fleet-wide operation now requires an explicit platform binding for a caller that does not hold the admin scope. A management API key that reached one of these operations on a coarse scope alone, such as read or metrics_reader, is refused after this upgrade.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

Changed in v0.2.0 (security updates): Directory lookups through IdentityService.GetUser and ListUsers are now confined to the organizations the calling session belongs to. A signed-in user that held the users_reader scope, including every organization administrator, could previously resolve any user id in any tenant to email, name and role. GetUser now answers "not found" for a user outside the caller's organizations, and ListUsers omits them. A session with no project memberships resolves no users at all, including its own row. This affects users whose only access is an organization-level role, pending invites, and users whose only project is the reserved "default" project. Platform operators keep cross-tenant directory reads only through an explicit platform role binding. In a multi-tenant deployment that binding is a documented provisioning step (docs/runbooks/platform-directory-reach.md).

What it does: Batch-resolves user_ids to directory entries in one call, so a stats/management caller can resolve a whole page of grouped insights rows without N round-trips. Unknown ids are silently omitted from the response.

Request fields:

FieldRequiredDescription
user_idsnoThe user_ids to resolve. Unknown ids are omitted from the response rather than erroring, so a partially-stale set still resolves. Capped at 1000 -- the insights page-size cap -- so one page of grouped rows resolves in a single call without becoming an unbounded ANY($1) query.

Response fields:

FieldRequiredDescription
usersnoResolved directory entries, in arbitrary order. May be shorter than the request when some ids are unknown.
{"signatures":{"go":"func (x *IdentityClient) ListUsers(ctx context.Context, req *identityv1.ListUsersRequest) (*identityv1.ListUsersResponse, error)","python":"list_users(req: identity_service_pb2.ListUsersRequest) -\u003e ListUsersResponse","typescript":"listUsers(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.ListUsersRequestSchema\u003e): Promise\u003cListUsersResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/lookup\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_ids\": []\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.ListUsersRequest{}\n\n\tresp, err := client.Identity().ListUsers(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/listusers\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.ListUsersRequest()\ntry:\n    result = client.identity.list_users(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.listUsers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/lookup\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_ids\": []\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/users/lookup","slug":"list-users"}

Ban a user

Changed in v0.4.0 (new features): Administrators can ban and unban a user through the management API. Banning a user signs them out everywhere and disables their API keys. Unbanning lets them sign in again, and they issue new keys -- keys removed by the ban are not restored. Both calls require an interactive session holding the admin scope or the users.edit permission, which is the same authority the delete call requires. An API key is refused even when it carries that permission.

What it does: Bans a user (authn.user.banned = true) with a reason, and immediately revokes every live session and API key the user holds. This is the valet-native equivalent of fraser-auth's better-auth admin ban-user endpoint (fraser#9001): the flag lives on the shared authn.user row, the session revocation matches better-auth's ban-time deletion, and the key soft-delete matches the fraser#8689 hook (keys are marked deleted_at, never restored -- an unbanned user issues fresh keys). Admin-gated and session-only, carrying the same caller contract as DeleteUser (fraser#9151): an interactive session that holds the admin scope, or the users.edit permission on a platform-scope RBAC binding. A ban revokes every session and every API key the target holds, so its blast radius equals a delete's and the two admit the same administrators. users.edit is also the atom fraser-auth authorizes its own ban endpoints on (fraser#8689), so valet and fraser-auth answer a ban from one permission. The request names a bare user_id and no tenant, so users.edit is authorized at PLATFORM reach. The handler re-checks the session half: an API key is refused even when it carries users.edit.

Request fields:

FieldRequiredDescription
user_idyesThe authn.user.id of the user to ban.
reasonnoWhy the user is banned, stored on authn.user.ban_reason and shown to operators. Mirrors the dashboard's cap (fraser#9001).

Response fields:

FieldRequiredDescription
user_idoutput-onlyThe banned user's id (echoes user_id).
bannedoutput-onlyAlways true on success; present so callers can assert the state the way they did against better-auth's user.banned response.
ban_reasonoutput-onlyThe stored ban reason.
{"signatures":{"go":"func (x *IdentityClient) BanUser(ctx context.Context, req *identityv1.BanUserRequest) (*identityv1.BanUserResponse, error)","python":"ban_user(req: identity_service_pb2.BanUserRequest) -\u003e BanUserResponse","typescript":"banUser(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.BanUserRequestSchema\u003e): Promise\u003cBanUserResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../ban\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithSessionToken(os.Getenv(\"AGENTROUTER_SESSION_TOKEN\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.BanUserRequest{}\n\n\tresp, err := client.Identity().BanUser(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/banuser\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    session_token=os.environ[\"AGENTROUTER_SESSION_TOKEN\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.BanUserRequest()\ntry:\n    result = client.identity.ban_user(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  sessionToken: process.env.AGENTROUTER_SESSION_TOKEN,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.banUser(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../ban\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/users/{user_id}/ban","slug":"ban-a-user"}

Unban a user

Changed in v0.4.0 (new features): Administrators can ban and unban a user through the management API. Banning a user signs them out everywhere and disables their API keys. Unbanning lets them sign in again, and they issue new keys -- keys removed by the ban are not restored. Both calls require an interactive session holding the admin scope or the users.edit permission, which is the same authority the delete call requires. An API key is refused even when it carries that permission.

What it does: Clears a user's ban (authn.user.banned, ban_reason, ban_expires). It deliberately restores nothing: sessions deleted by the ban stay logged out and API keys soft-deleted by the ban stay dead, so a re-enabled user must sign in again and issue fresh keys (fraser#8689). Same caller gate as BanUser, declared the same way: lifting a ban is as consequential as writing one.

Request fields:

FieldRequiredDescription
user_idyesThe authn.user.id of the user to unban.

Response fields:

FieldRequiredDescription
user_idoutput-onlyThe unbanned user's id (echoes user_id).
bannedoutput-onlyAlways false on success; present so callers can assert the state the way they did against better-auth's user.banned response.
{"signatures":{"go":"func (x *IdentityClient) UnbanUser(ctx context.Context, req *identityv1.UnbanUserRequest) (*identityv1.UnbanUserResponse, error)","python":"unban_user(req: identity_service_pb2.UnbanUserRequest) -\u003e UnbanUserResponse","typescript":"unbanUser(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.UnbanUserRequestSchema\u003e): Promise\u003cUnbanUserResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../unban\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithSessionToken(os.Getenv(\"AGENTROUTER_SESSION_TOKEN\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.UnbanUserRequest{}\n\n\tresp, err := client.Identity().UnbanUser(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/unbanuser\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    session_token=os.environ[\"AGENTROUTER_SESSION_TOKEN\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.UnbanUserRequest()\ntry:\n    result = client.identity.unban_user(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  sessionToken: process.env.AGENTROUTER_SESSION_TOKEN,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.unbanUser(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../unban\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/users/{user_id}/unban","slug":"unban-a-user"}

Revoke a user's sessions

Changed in v0.5.0 (new features): Administrators can sign a user out of every session through the management plane API, for example after lowering their role. The user's API keys keep working and the account is not banned. It needs the same users.edit permission as banning a user, and only a signed-in administrator can call it, not an API key.

What it does: Signs a user out everywhere by deleting every authn.session row they hold. It touches nothing else: API keys stay live and the account is not banned. This is the valet-native equivalent of fraser-auth's better-auth admin revoke-user-sessions endpoint, which the admin console calls when it lowers a user's role so the old role's sessions do not outlive the change. Revoking your own sessions is allowed, as it is on fraser-auth. Same caller contract as BanUser: an interactive session that holds the admin scope, or the users.edit permission on a platform-scope RBAC binding. users.edit is the atom fraser-auth authorizes its own revoke-user-sessions endpoint on (the same gate as its ban endpoints), so valet and fraser-auth admit the same administrators. The request names a bare user_id and no tenant, so users.edit is authorized at PLATFORM reach, and the handler refuses any credential that is not a session, even an API key carrying users.edit. NOT_FOUND for an unknown user_id. A known user with no sessions succeeds with revoked_count 0.

Request fields:

FieldRequiredDescription
user_idyesThe authn.user.id of the user to sign out.

Response fields:

FieldRequiredDescription
user_idoutput-onlyThe user's id (echoes user_id).
revoked_countoutput-onlyHow many sessions were deleted. Zero when the user held none.
{"signatures":{"go":"func (x *IdentityClient) RevokeUserSessions(ctx context.Context, req *identityv1.RevokeUserSessionsRequest) (*identityv1.RevokeUserSessionsResponse, error)","python":"revoke_user_sessions(req: identity_service_pb2.RevokeUserSessionsRequest) -\u003e RevokeUserSessionsResponse","typescript":"revokeUserSessions(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.RevokeUserSessionsRequestSchema\u003e): Promise\u003cRevokeUserSessionsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../revoke-sessions\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithSessionToken(os.Getenv(\"AGENTROUTER_SESSION_TOKEN\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.RevokeUserSessionsRequest{}\n\n\tresp, err := client.Identity().RevokeUserSessions(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/revokeusersessions\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    session_token=os.environ[\"AGENTROUTER_SESSION_TOKEN\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.RevokeUserSessionsRequest()\ntry:\n    result = client.identity.revoke_user_sessions(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  sessionToken: process.env.AGENTROUTER_SESSION_TOKEN,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.revokeUserSessions(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../revoke-sessions\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/users/{user_id}/revoke-sessions","slug":"revoke-a-users-sessions"}

Delete a user

Changed in v0.4.0 (new features): Platform operators can soft-delete and restore user accounts over the management API. DELETE /v1/users/{user_id} marks the account deleted, revokes its API keys, and ends its sessions in one atomic operation; POST /v1/users/{user_id}/restore reverses it. The delete refuses the last active administrator of the platform or of any organization the user administers, so a deployment cannot be left unadministrable.

What it does: Soft-deletes a user (fraser#8692). The authn.user row is never removed: delete sets banned = true with the USER_DELETED ban reason, stamps deleted_at/deleted_by, revokes every live API key the user owns (writing deleted_at, revoked_at and is_active), deletes the RBAC bindings those keys carried, and removes their authn.session rows -- all in one transaction, so a key-revocation failure leaves the user unchanged. RestoreUser reverses it. Restorable by design, and visibly distinct from an operator ban: a deleted account carries the USER_DELETED sentinel as its ban reason. Refuses with FAILED_PRECONDITION when the target is the last active administrator -- of the platform (legacy admin role or a platform-scope admin binding) or of any customer they hold an org-scope admin binding for -- so a deployment cannot delete its way out of being administrable. Refuses with FAILED_PRECONDITION when the user is already deleted; NOT_FOUND for an unknown user_id.

Request fields:

FieldRequiredDescription
user_idyesThe authn.user.id of the account to soft-delete.

Response fields:

FieldRequiredDescription
user_idnoThe deleted user's id (echoes the request).
deleted_atoutput-onlyWhen the delete landed (the authn.user.deleted_at stamp).
revoked_api_keysoutput-onlyLive API keys the transaction revoked (deleted_at + revoked_at + is_active).
deleted_sessionsoutput-onlyauthn.session rows the transaction deleted.
{"signatures":{"go":"func (x *IdentityClient) DeleteUser(ctx context.Context, req *identityv1.DeleteUserRequest) (*identityv1.DeleteUserResponse, error)","python":"delete_user(req: identity_service_pb2.DeleteUserRequest) -\u003e DeleteUserResponse","typescript":"deleteUser(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.DeleteUserRequestSchema\u003e): Promise\u003cDeleteUserResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/users/01H...\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithSessionToken(os.Getenv(\"AGENTROUTER_SESSION_TOKEN\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.DeleteUserRequest{}\n\n\tresp, err := client.Identity().DeleteUser(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/deleteuser\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    session_token=os.environ[\"AGENTROUTER_SESSION_TOKEN\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.DeleteUserRequest()\ntry:\n    result = client.identity.delete_user(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  sessionToken: process.env.AGENTROUTER_SESSION_TOKEN,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.deleteUser(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/users/01H...\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/users/{user_id}","slug":"delete-a-user"}

Restore a deleted user

Changed in v0.4.0 (new features): Platform operators can soft-delete and restore user accounts over the management API. DELETE /v1/users/{user_id} marks the account deleted, revokes its API keys, and ends its sessions in one atomic operation; POST /v1/users/{user_id}/restore reverses it. The delete refuses the last active administrator of the platform or of any organization the user administers, so a deployment cannot be left unadministrable.

What it does: Reverses DeleteUser: it clears deleted_at/deleted_by, and lifts the USER_DELETED ban the delete wrote. It does not touch an operator's separate suspension (a ban whose reason is not the USER_DELETED sentinel survives a restore), and it does not resurrect the revoked API keys or deleted sessions -- those stay revoked, and the user mints new credentials on next login. NOT_FOUND when the user_id has no row or carries no deleted_at (shaped as "not deleted").

Request fields:

FieldRequiredDescription
user_idyesThe authn.user.id of the account to restore.

Response fields:

FieldRequiredDescription
user_idnoThe restored user's id (echoes the request).
bannedoutput-onlyThe account's ban state AFTER the restore. False when restore lifted the USER_DELETED ban; true when an operator suspension with a different ban reason was left in place (see RestoreUser's docs).
ban_reasonoutput-onlyThe surviving ban reason, when banned is true.
{"signatures":{"go":"func (x *IdentityClient) RestoreUser(ctx context.Context, req *identityv1.RestoreUserRequest) (*identityv1.RestoreUserResponse, error)","python":"restore_user(req: identity_service_pb2.RestoreUserRequest) -\u003e RestoreUserResponse","typescript":"restoreUser(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.RestoreUserRequestSchema\u003e): Promise\u003cRestoreUserResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../restore\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithSessionToken(os.Getenv(\"AGENTROUTER_SESSION_TOKEN\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.RestoreUserRequest{}\n\n\tresp, err := client.Identity().RestoreUser(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/restoreuser\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    session_token=os.environ[\"AGENTROUTER_SESSION_TOKEN\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.RestoreUserRequest()\ntry:\n    result = client.identity.restore_user(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_SESSION_TOKEN in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  sessionToken: process.env.AGENTROUTER_SESSION_TOKEN,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.restoreUser(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/01H.../restore\" \\\n  -H \"Authorization: Bearer $SESSION_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/users/{user_id}/restore","slug":"restore-a-deleted-user"}

Search users

Changed in v0.5.0 (behaviour changes): Reaching a fleet-wide operation now requires an explicit platform binding for a caller that does not hold the admin scope. A management API key that reached one of these operations on a coarse scope alone, such as read or metrics_reader, is refused after this upgrade.

Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.

Changed in v0.4.0 (new features): The management API now serves the user directory the Admin Console reads. POST /v1/users/search returns a page of users matched on name or email substring, filtered by account status, role, team or id set, sorted on a chosen field, and POST /v1/users/stats returns the per-status counts over those same filters. A request that names no status leaves deleted users out, so the active population is what a caller sees by default. A directory user also carries its account status, ban reason and deletion time, so a console can render a deleted user in history instead of resolving nothing.

What it does: Browses the directory the way the admin console's Users page needs (fraser#8695): a case-insensitive substring match on name or email, a status filter, and limit/offset paging with a total, so the console renders its numbered pages and stat cards without reading the auth DB directly (fraser#5521). The same users_reader gate and in-handler tenant boundary as GetUser/ListUsers apply. An UNSPECIFIED status hides deleted users -- deleted_at IS NULL is the default everywhere active lists are rendered -- so a caller sees the active population unless it asks for USER_STATUS_DELETED explicitly. ACTIVE and BANNED also exclude deleted users: a delete is a separate state from an operator ban, not a flavor of one.

Request fields:

FieldRequiredDescription
searchnoCase-insensitive substring match on name OR email. Empty matches everyone (under the filters below).
statusnoStatus filter. UNSPECIFIED hides deleted users (the default active population); USER_STATUS_DELETED returns only deleted users. The value never selects the wire status USER_STATUS_UNSPECIFIED.
rolenoRestrict to this built-in role (authn.user.role). Empty matches any role. An explicit "user" also matches rows whose role is NULL -- the same normalization the console's Role filter applies.
user_group_idnoRestrict to this team (authn.user.tag group id). Empty matches every team; use unassigned_user_group to select users in no team.
user_idsnoRestrict the search to these users (a roster view sends the roster's id set). Empty means no restriction -- a caller holding an empty roster must short-circuit rather than send an empty set.
exclude_user_idsnoExclude these users (the add-member picker sends the current roster so it only offers candidates). Empty excludes none.
limitnoPage size. 0 selects the default of 50; values above 100 are rejected.
offsetnoPage offset; 0 is the first page.
unassigned_user_groupnoRestrict to users in NO team (authn.user.tag is null) -- the console's Team filter's "Unassigned" option. When true, user_group_id is ignored.
sort_bynoPage ordering. The default is created_at descending, then updated_at -- the console's "Recent" default.
sort_dirnoSort direction; UNSPECIFIED follows the console's per-field default (descending for the timestamps, ascending otherwise).
exclude_user_group_idnoExclude members of this team (users whose tag is this id). Users in no team are NOT excluded -- they are not in the team. The team-add picker's candidate list (fraser#8695).
has_user_groupnoRestrict to users in SOME team (authn.user.tag is not null) -- the team-management screens enumerate their org's teamed users in one paged pass and bucket them per team, instead of one call per team.

Response fields:

FieldRequiredDescription
usersnoThe matched page, ordered per the request's sort_by/sort_dir with the id as the tiebreaker.
totalnoUsers matching the filters across all pages -- the count numbered pagination and stat cards render.
{"signatures":{"go":"func (x *IdentityClient) SearchUsers(ctx context.Context, req *identityv1.SearchUsersRequest) (*identityv1.SearchUsersResponse, error)","python":"search_users(req: identity_service_pb2.SearchUsersRequest) -\u003e SearchUsersResponse","typescript":"searchUsers(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.SearchUsersRequestSchema\u003e): Promise\u003cSearchUsersResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/search\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"search\": \"...\",\n    \"status\": \"...\",\n    \"role\": \"...\",\n    \"user_group_id\": \"...\",\n    \"user_ids\": [],\n    \"exclude_user_ids\": [],\n    \"limit\": 0,\n    \"offset\": 0,\n    \"unassigned_user_group\": false,\n    \"sort_by\": \"...\",\n    \"sort_dir\": \"...\",\n    \"exclude_user_group_id\": \"...\",\n    \"has_user_group\": false\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.SearchUsersRequest{}\n\n\tresp, err := client.Identity().SearchUsers(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/searchusers\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.SearchUsersRequest()\ntry:\n    result = client.identity.search_users(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.searchUsers(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/search\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"search\": \"...\",\n    \"status\": \"...\",\n    \"role\": \"...\",\n    \"user_group_id\": \"...\",\n    \"user_ids\": [],\n    \"exclude_user_ids\": [],\n    \"limit\": 0,\n    \"offset\": 0,\n    \"unassigned_user_group\": false,\n    \"sort_by\": \"...\",\n    \"sort_dir\": \"...\",\n    \"exclude_user_group_id\": \"...\",\n    \"has_user_group\": false\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/users/search","slug":"search-users"}

Get user stats

Changed in v0.5.0 (behaviour changes): Reaching a fleet-wide operation now requires an explicit platform binding for a caller that does not hold the admin scope. A management API key that reached one of these operations on a coarse scope alone, such as read or metrics_reader, is refused after this upgrade.

Changed in v0.4.0 (new features): The management API now serves the user directory the Admin Console reads. POST /v1/users/search returns a page of users matched on name or email substring, filtered by account status, role, team or id set, sorted on a chosen field, and POST /v1/users/stats returns the per-status counts over those same filters. A request that names no status leaves deleted users out, so the active population is what a caller sees by default. A directory user also carries its account status, ban reason and deletion time, so a console can render a deleted user in history instead of resolving nothing.

What it does: Returns the per-status counts the Users page's stat cards render, over the same boundary and the same non-status filters as SearchUsers -- one call instead of four filtered searches. The status filter is the one SearchUsers predicate this request omits: the counts ARE the status breakdown. total counts non-deleted users (active + banned), so deleted users never inflate a "total users" card.

Request fields:

FieldRequiredDescription
searchnoOptional case-insensitive substring match on name OR email, the same match SearchUsers applies. Empty counts everyone.
user_idsnoRestrict the counts to these users (a roster view scopes its stat cards to the roster's id set). Empty means no restriction.
exclude_user_idsnoExclude these users from the counts, the same exclusion semantics as SearchUsers. Empty excludes none.
rolenoRestrict the counts to this built-in role, the same normalization SearchUsers applies (an explicit "user" also counts rows whose role is NULL). Empty counts any role.
user_group_idnoRestrict the counts to this team (authn.user.tag group id). Empty counts every team; use unassigned_user_group to count users in no team.
unassigned_user_groupnoCount only users in NO team (authn.user.tag is null). When true, user_group_id is ignored -- the same precedence SearchUsers applies.
exclude_user_group_idnoExclude members of this team from the counts. Users in no team are NOT excluded: they are not in the team.
has_user_groupnoCount only users in SOME team (authn.user.tag is not null).

Response fields:

FieldRequiredDescription
totalnoNon-deleted users (active + banned): a "total users" card never counts deleted accounts.
activenoUsers with no ban in effect and not deleted.
bannednoOperator suspensions only -- a ban in effect on a row that is not deleted.
deletednoDeleted users (deleted_at set).
{"signatures":{"go":"func (x *IdentityClient) GetUserStats(ctx context.Context, req *identityv1.GetUserStatsRequest) (*identityv1.GetUserStatsResponse, error)","python":"get_user_stats(req: identity_service_pb2.GetUserStatsRequest) -\u003e GetUserStatsResponse","typescript":"getUserStats(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.GetUserStatsRequestSchema\u003e): Promise\u003cGetUserStatsResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/stats\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"search\": \"...\",\n    \"user_ids\": [],\n    \"exclude_user_ids\": [],\n    \"role\": \"...\",\n    \"user_group_id\": \"...\",\n    \"unassigned_user_group\": false,\n    \"exclude_user_group_id\": \"...\",\n    \"has_user_group\": false\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.GetUserStatsRequest{}\n\n\tresp, err := client.Identity().GetUserStats(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/getuserstats\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.GetUserStatsRequest()\ntry:\n    result = client.identity.get_user_stats(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.getUserStats(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/users/stats\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"search\": \"...\",\n    \"user_ids\": [],\n    \"exclude_user_ids\": [],\n    \"role\": \"...\",\n    \"user_group_id\": \"...\",\n    \"unassigned_user_group\": false,\n    \"exclude_user_group_id\": \"...\",\n    \"has_user_group\": false\n  }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/users/stats","slug":"get-user-stats"}

Create or update the SSO provider

Changed in v0.5.0 (new features): Corporate SSO can now be registered and used through the management API. Administrators holding sso_providers permissions can create, read and delete the OIDC provider, a sign-in page can ask whether corporate login is available before anyone signs in, and a browser can complete a corporate login against the management API itself. Set SSO_CALLBACK_BASE_URL to the management API's public origin to enable the browser flow.

Changed in v0.5.0 (new features): Corporate SSO now supports SAML 2.0 as well as OIDC. Register the IdP entity id, sign-on URL and signing certificate, then import the service provider metadata the management API publishes for that provider. Encrypted assertions and IdP-initiated sign-in are not supported.

What it does: Upserts the deployment's SSO provider row. The oidc_config jsonb it writes keeps fraser-auth's camelCase keys, because valet's own login parses those exact keys back out (identitysvc.SSOProviderOIDC): a write that renamed them would break the next sign-in rather than fail here. One gate, both verbs. fraser-auth reaches this row two ways and answers differently on each -- /api/sso-providers requires a grant while /api/sso-init requires nothing at all -- and that split is deliberately not ported: create and edit are separate verbs on one resource behind one annotation, so there is no second way in.

Request fields:

FieldRequiredDescription
provider_idnoEmpty selects the deployment default ("corporate").
domainnoDefaults to "*" on create; left alone on an update that omits it.
provider_typeno"oidc" or "saml". The matching config field is required on a create and refused when it names the other protocol, so a row can never describe a provider valet cannot serve.
oidcnoundocumented
samlnoundocumented
organization_idnoundocumented
admin_emailsnoundocumented
enablednoDefaults to true on create; left alone on an update that omits it.
role_claim_pathnoUnset leaves the stored path; "" clears it.
role_mappingnoUnset leaves the stored mapping; a message with no entries clears it.
role_sync_modenoUnset leaves the stored mode; "" resets it to "permissive". Any other value must be one of "off", "on_create", "permissive", "strict" -- an unknown mode is refused rather than stored, because fraser-auth's login would read it back and fall through to a default the operator never chose.

Response fields:

FieldRequiredDescription
providernoundocumented
createdoutput-onlyTrue when this call inserted the row, false when it updated one.
{"signatures":{"go":"func (x *IdentityClient) CreateOrUpdateSSOProvider(ctx context.Context, req *identityv1.CreateOrUpdateSSOProviderRequest) (*identityv1.CreateOrUpdateSSOProviderResponse, error)","python":"create_or_update_sso_provider(req: identity_service_pb2.CreateOrUpdateSSOProviderRequest) -\u003e CreateOrUpdateSSOProviderResponse","typescript":"createOrUpdateSSOProvider(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.CreateOrUpdateSSOProviderRequestSchema\u003e): Promise\u003cCreateOrUpdateSSOProviderResponse\u003e","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/sso-providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_id\": \"...\",\n    \"domain\": \"...\",\n    \"provider_type\": \"...\",\n    \"oidc\": {},\n    \"saml\": {},\n    \"organization_id\": \"...\",\n    \"admin_emails\": \"...\",\n    \"enabled\": false,\n    \"role_claim_path\": \"...\",\n    \"role_mapping\": {},\n    \"role_sync_mode\": \"...\"\n  }'"},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.CreateOrUpdateSSOProviderRequest{}\n\n\tresp, err := client.Identity().CreateOrUpdateSSOProvider(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/createorupdatessoprovider\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.CreateOrUpdateSSOProviderRequest()\ntry:\n    result = client.identity.create_or_update_sso_provider(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.createOrUpdateSSOProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/sso-providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"provider_id\": \"...\",\n    \"domain\": \"...\",\n    \"provider_type\": \"...\",\n    \"oidc\": {},\n    \"saml\": {},\n    \"organization_id\": \"...\",\n    \"admin_emails\": \"...\",\n    \"enabled\": false,\n    \"role_claim_path\": \"...\",\n    \"role_mapping\": {},\n    \"role_sync_mode\": \"...\"\n  }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/sso-providers","slug":"create-or-update-the-sso-provider"}

List SSO providers

Changed in v0.5.0 (new features): Corporate SSO can now be registered and used through the management API. Administrators holding sso_providers permissions can create, read and delete the OIDC provider, a sign-in page can ask whether corporate login is available before anyone signs in, and a browser can complete a corporate login against the management API itself. Set SSO_CALLBACK_BASE_URL to the management API's public origin to enable the browser flow.

What it does: Returns every registered provider. Secrets are never included: client_secret is write-only on this surface.

Request body: None.

Response fields:

FieldRequiredDescription
providersnoundocumented
{"signatures":{"go":"func (x *IdentityClient) ListSSOProviders(ctx context.Context, req *identityv1.ListSSOProvidersRequest) (*identityv1.ListSSOProvidersResponse, error)","python":"list_sso_providers(req: identity_service_pb2.ListSSOProvidersRequest) -\u003e ListSSOProvidersResponse","typescript":"listSSOProviders(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.ListSSOProvidersRequestSchema\u003e): Promise\u003cListSSOProvidersResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/sso-providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.ListSSOProvidersRequest{}\n\n\tresp, err := client.Identity().ListSSOProviders(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/listssoproviders\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.ListSSOProvidersRequest()\ntry:\n    result = client.identity.list_sso_providers(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.listSSOProviders(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl \"${AGENTROUTER_BASE_URL}/v1/sso-providers\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/sso-providers","slug":"list-sso-providers"}

Get an SSO provider

Changed in v0.5.0 (new features): Corporate SSO can now be registered and used through the management API. Administrators holding sso_providers permissions can create, read and delete the OIDC provider, a sign-in page can ask whether corporate login is available before anyone signs in, and a browser can complete a corporate login against the management API itself. Set SSO_CALLBACK_BASE_URL to the management API's public origin to enable the browser flow.

What it does: Returns one provider by id. Same secret rule as the list.

Request fields:

FieldRequiredDescription
provider_idyesundocumented

Response fields:

FieldRequiredDescription
providernoundocumented
{"signatures":{"go":"func (x *IdentityClient) GetSSOProvider(ctx context.Context, req *identityv1.GetSSOProviderRequest) (*identityv1.GetSSOProviderResponse, error)","python":"get_sso_provider(req: identity_service_pb2.GetSSOProviderRequest) -\u003e GetSSOProviderResponse","typescript":"getSSOProvider(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.GetSSOProviderRequestSchema\u003e): Promise\u003cGetSSOProviderResponse\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/sso-providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.GetSSOProviderRequest{}\n\n\tresp, err := client.Identity().GetSSOProvider(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/getssoprovider\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.GetSSOProviderRequest()\ntry:\n    result = client.identity.get_sso_provider(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.getSSOProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl \"${AGENTROUTER_BASE_URL}/v1/sso-providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"GET","httpPath":"/v1/sso-providers/{provider_id}","slug":"get-an-sso-provider"}

Delete an SSO provider

Changed in v0.5.0 (new features): Corporate SSO can now be registered and used through the management API. Administrators holding sso_providers permissions can create, read and delete the OIDC provider, a sign-in page can ask whether corporate login is available before anyone signs in, and a browser can complete a corporate login against the management API itself. Set SSO_CALLBACK_BASE_URL to the management API's public origin to enable the browser flow.

What it does: Removes a provider row. Corporate login stops working the moment it lands, so it admits the same callers a write does.

Request fields:

FieldRequiredDescription
provider_idyesundocumented

Response fields:

FieldRequiredDescription
provider_idnoThe deleted provider id (echoes the request).
{"signatures":{"go":"func (x *IdentityClient) DeleteSSOProvider(ctx context.Context, req *identityv1.DeleteSSOProviderRequest) (*identityv1.DeleteSSOProviderResponse, error)","python":"delete_sso_provider(req: identity_service_pb2.DeleteSSOProviderRequest) -\u003e DeleteSSOProviderResponse","typescript":"deleteSSOProvider(req: MessageInitShape\u003ctypeof tars_identity_v1_identity_service_pb.DeleteSSOProviderRequestSchema\u003e): Promise\u003cDeleteSSOProviderResponse\u003e","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/sso-providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"examples":{"go":{"files":[{"name":"main.go","content":"// Command example is a runnable example for the AgentRouter Go SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then `go run .`.\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tagentrouter \"github.com/tetrateio/agentrouter-go\"\n\tidentityv1 \"github.com/tetrateio/agentrouter-go/genapi/api/tars/identity/v1\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\tclient, err := agentrouter.New(ctx,\n\t\tagentrouter.WithBaseURL(os.Getenv(\"AGENTROUTER_BASE_URL\")),\n\t\tagentrouter.WithAPIKey(os.Getenv(\"AGENTROUTER_API_KEY\")),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"client: %v\", err)\n\t}\n\n\t// Populate the request fields -- see the \"Request fields\" table above for\n\t// the available fields and which are required.\n\treq := \u0026identityv1.DeleteSSOProviderRequest{}\n\n\tresp, err := client.Identity().DeleteSSOProvider(ctx, req)\n\tif err != nil {\n\t\tlog.Fatalf(\"call: %v\", err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", resp)\n}\n"},{"name":"go.mod","content":"module github.com/tetrateio/agentrouter-go-examples/identity/deletessoprovider\n\ngo 1.26\n\nrequire github.com/tetrateio/agentrouter-go v0.1.1\n\n// Point this at the directory you extracted the downloaded Go SDK tarball into.\n// The directory name matches the tarball stem on the Download SDK page.\nreplace github.com/tetrateio/agentrouter-go =\u003e ./third_party/agentrouter-go-0.1.1\n"}]},"python":{"files":[{"name":"main.py","content":"\"\"\"Runnable example for the AgentRouter Python SDK.\n\nSet AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `python main.py`.\n\"\"\"\nimport os\n\nfrom tars.identity.v1 import identity_service_pb2\n\nfrom agentrouter_sdk import Client\n\nclient = Client(\n    base_url=os.environ[\"AGENTROUTER_BASE_URL\"],\n    api_key=os.environ[\"AGENTROUTER_API_KEY\"],\n)\n\n# Populate the request fields -- see the \"Request fields\" table above\n# for the available fields and which are required.\nreq = identity_service_pb2.DeleteSSOProviderRequest()\ntry:\n    result = client.identity.delete_sso_provider(req)\n    print(result)\nexcept Exception as err:\n    print(\"Error:\", err)\n"},{"name":"requirements.txt","content":"# Point this at the directory you extracted the downloaded Python SDK tarball\n# into. The directory name matches the tarball stem on the Download SDK page.\n# To install instead from PyPI once published, replace the line below with:\n#   agentrouter-sdk\u003e=0.1.0\nagentrouter-sdk @ file:./third_party/agentrouter-python-0.1.1\n"}]},"typescript":{"files":[{"name":"index.ts","content":"// Runnable example for the AgentRouter TypeScript SDK.\n// Set AGENTROUTER_BASE_URL and AGENTROUTER_API_KEY in the environment, then run `npm install \u0026\u0026 npx tsx index.ts`.\nimport { Client } from '@tetrate/agentrouter-sdk'\n\nconst client = new Client({\n  baseUrl: process.env.AGENTROUTER_BASE_URL,\n  apiKey: process.env.AGENTROUTER_API_KEY,\n})\n\n// Populate the request fields -- see the \"Request fields\" table above\n// for the available fields and which are required.\nconst req = {}\ntry {\n  const result = await client.identity.deleteSSOProvider(req)\n  console.log(result)\n} catch (err) {\n  console.error('Error:', err)\n}\n"},{"name":"package.json","content":"{\n  \"name\": \"identity\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@tetrate/agentrouter-sdk\": \"file:./third_party/agentrouter-typescript-0.1.1\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.0.0\",\n    \"typescript\": \"^5.4.0\"\n  }\n}\n"},{"name":"tsconfig.json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"}]},"curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/sso-providers/01H...\" \\\n  -H \"Authorization: Bearer ${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/sso-providers/{provider_id}","slug":"delete-an-sso-provider"}