Users, organizations and teams
Provision and deprovision users, group them into organizations and teams, set up verified domains, SAML SSO, SCIM and audit export, and set policy from your account down to each team.
Your account holds every end user of your app. Group users into organizations (your customer companies) and teams to give each customer its own admins, sign-in, directory sync, audit trail and policy. Data isolation does not follow this hierarchy: it is per user at every level.
How it works
Account your app; holds every user, organization and setting.
| Console settings are the policy ceiling for everything below.
+- Organization a customer company (optional): admins, verified domains,
| | SAML SSO, SCIM, audit export, skill library, model tiers
| +- Team a group of users; team admins set policy the org left open
| +- User one end user; owns tasks, chats, memories, contacts,
| connections and a workspace
+- Team a team outside any organization
+- User
| Concept | Rule |
|---|---|
| Isolation | A user's data is visible to that user and to your account-wide credentials, never to other users. Sharing an account, organization or team grants nothing by itself. Sharing is explicit, for example a team-scoped memory or a task collaborator. |
| One active team | A user has exactly one active team membership. Adding a user to a team archives their other memberships. |
| Organization membership | A user belongs to at most one organization, with organizationRole admin, member or guest. |
| Team roles | owner (exactly one per team), admin, member. |
| Policy | A tier can change a setting only where no tier above it has locked it. See Policy. |
Organization and team admins act through the hosted app (the end-user app served for your account) or through the API with their own credentials. The examples in this guide use an account-wide API key, which can administer every organization and team in your account. See Authentication for key levels.
Your app's hosted domain is the domain the hosted app is served on: its AGNT subdomain or your custom domain. SAML sign-in and SCIM are served there.
Create an organization
Create an organization for each customer company.
curl https://api.agnt.ai/organizations \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Harborview Property Management" }'
The response returns the organization with "id": "6702a9c3e1b4f5d6a7b8c901".
PUT /organizations/:orgId sets name, defaultTeam (where organization-scoped provisioning places new users) and defaultAssistant. DELETE /organizations/:orgId deletes the organization and its domains. Its users and teams stay in your account, and teams left with no members are deleted.
Verify a domain
A verified domain proves the customer controls it. It lets the organization claim its users: auto-join, SSO sign-in, and the rule that users at that domain can join only that organization's teams.
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/domains \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "domain": "harborview.co", "autoJoin": true }'
{
"ok": true,
"domain": {
"id": "6702aa14b7c8d9e0f1a2b3c4",
"domain": "harborview.co",
"source": "manual",
"verified": false,
"autoJoin": true,
"txtRecordName": "_agnt-verification.harborview.co",
"txtRecordValue": "agnt-06815aa2c88aa0194d3af3d4476fe650ae6cd63017d0e66d6a4ae065",
"verifiedAt": null,
"lastCheckedAt": null,
"createdAt": "2026-11-02T16:24:11.000Z",
"updatedAt": "2026-11-02T16:24:11.000Z"
}
}
Publish a DNS TXT record named txtRecordName with the value txtRecordValue, then verify:
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/domains/6702aa14b7c8d9e0f1a2b3c4/verify \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY"
The response returns the domain with verified: true and verifiedAt set. Until the record is visible in DNS, verify returns 400 and records lastCheckedAt. Call it again after propagation.
| Name | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | The domain, such as harborview.co. Stored lower-cased. |
autoJoin | boolean | No | Default false. Once the domain is verified, users with an email at this domain join the organization as member when they are provisioned or sign up. |
PUT /organizations/:orgId/domains/:domainId with { autoJoin } changes auto-join. Domains added by an SSO configuration have source: "sso" and cannot be edited or removed directly.
Provision users
POST /users/provision finds or creates a user by email and places them on a team. It is idempotent, so call it on every sign-in. It returns 201 when it creates the user and 200 when the user exists.
Provision Maria Chen onto the Leasing team:
curl https://api.agnt.ai/users/provision \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"firstName": "Maria",
"lastName": "Chen",
"teamId": "6702ab52c3d4e5f6a7b8c9d0"
}'
{
"ok": true,
"user": {
"id": "6702b23a0b1c2d3e4f5a6b7c",
"account": "66f1a2b3c4d5e6f708192a3b",
"email": "[email protected]",
"assistant": null,
"name": "Maria Chen",
"firstName": "Maria",
"lastName": "Chen",
"avatarUrl": null,
"timezone": "UTC",
"locale": "en-US",
"organization": "6702a9c3e1b4f5d6a7b8c901",
"organizationRole": "member",
"team": {
"id": "6702ab52c3d4e5f6a7b8c9d0",
"name": "Leasing",
"organization": "6702a9c3e1b4f5d6a7b8c901",
"status": "active"
},
"teamRole": "member",
"status": "active",
"createdAt": "2026-11-02T16:24:11.000Z",
"updatedAt": "2026-11-02T16:24:11.000Z"
},
"teamId": "6702ab52c3d4e5f6a7b8c9d0",
"created": true,
"addedToTeam": true,
"alreadyMember": false,
"joinSkipped": false
}
Maria joined Harborview Property Management because harborview.co is a verified auto-join domain.
| Name | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Lower-cased and trimmed. Becomes the user's first identifier, so X-User-Email resolves to them. |
firstName, lastName | string | No | Used in the assistant's introductions and signatures. |
teamId | string | No | An existing team in your account. |
id | string | No | Your own id for the user, used only if it is a 24-character hex string. |
Where the user lands:
| Request | Team | Organization |
|---|---|---|
teamId given | That team, as member. If the email's domain is verified by an organization, the team must belong to that organization, or the call returns 403. | As below, by key type |
No teamId, organization-scoped key | The organization's defaultTeam, or a new team in the organization owned by the user | The key's organization |
No teamId, account-wide key | A new team owned by the user | The organization that verified the email's domain with autoJoin, if any |
| Response field | Description |
|---|---|
created | A new user was created. |
addedToTeam | A new team membership was created. |
alreadyMember | The user and the membership already existed. Nothing changed. |
joinSkipped | The user owns another team that still has active members, so they were not moved. Transfer that team's ownership, then call again. |
A new user needs a timezone and working hours before a key can act as them. See the Quickstart.
Update a user
PUT /users/:userId changes a user's profile, organization, role and status. Make Jane Rivera an admin of Harborview:
curl https://api.agnt.ai/users/6702b1e8f9a0b1c2d3e4f5a6 \
-X PUT \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "organization": "6702a9c3e1b4f5d6a7b8c901", "organizationRole": "admin" }'
| Name | Type | Description |
|---|---|---|
organization | string or null | An organization id, or null to remove the user from their organization. |
organizationRole | string | admin, member or guest. |
status | string | active, inactive or suspended. While inactive or suspended, every request acting as the user fails with 403 account_blocked. |
firstName, lastName, name, timezone, locale, metadata | Profile fields. | |
externalId | string | Your id for the user. Unique in the account. |
Set status to suspended to cut off a user's access without deleting anything. An organization admin can change these fields only for users in their own organization.
Add people to an organization
| Method | Use when |
|---|---|
Verified domain with autoJoin: true | Everyone at the customer's domain belongs to the customer. |
PUT /users/:userId with organization | Your backend decides membership. |
| SAML just-in-time sign-in, or SCIM | The customer's identity provider decides. |
POST /organizations/:orgId/members with { email } | An admin adds one person. The person is notified by email and in the app. Provision the user first. |
DELETE /organizations/:orgId/members/:userId removes a user from the organization and its teams.
Teams
Create the Leasing team inside Harborview by calling as Jane, an organization admin. Jane becomes the owner and moves from her current team.
curl https://api.agnt.ai/teams \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "X-User-Email: [email protected]" \
-H "Content-Type: application/json" \
-d '{ "name": "Leasing" }'
The response returns the team with "id": "6702ab52c3d4e5f6a7b8c9d0" and "organization": "6702a9c3e1b4f5d6a7b8c901".
A team belongs to the caller's organization: an organization admin's, or an organization-scoped key's. Called with an account-wide key and no X-User-Email, the team belongs to no organization, and ownerId (a user in your account) is required.
Add a user with POST /teams/:teamId/members. The user moves from their current team. Move Maria to the Maintenance team:
curl https://api.agnt.ai/teams/6702ab9fd4e5f6a7b8c9d0e1/members \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "userId": "6702b23a0b1c2d3e4f5a6b7c", "role": "member" }'
| Name | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | The user to add. |
role | string | No | member (default) or admin. |
newOwnerId | string | No | If the user owns their current team and it has other active members, an active member of that team to hand it to. Without it the call returns 400 with requiresOwnershipTransfer: true and that teamId. |
- Adding a user to an organization's team makes them a member of that organization if they had none. A user in a different organization is refused with
403. - If the user was the last member of their old team, that team is archived.
- The response returns
member.id, the membership id. Use it asmemberIdbelow.GET /teams/:teamId/memberslists memberships.
| Endpoint | Rule |
|---|---|
PUT /teams/:teamId/members/:memberId | role: member or admin. status: active, invited or archived. A team admin cannot change the owner, grant owner, or change another admin except to member. |
POST /teams/:teamId/transfer-ownership | { newOwnerId }, called as the current owner with X-User-Email. The new owner must be an active member. The old owner becomes member. |
DELETE /teams/:teamId/members/:memberId | The owner cannot be removed, and admins cannot remove admins. The removed user moves to another active team, else a team they previously owned, else a new team of their own. |
Deprovision users
POST /users/deprovision removes a user from one team. If the user then has no team membership at all, active or archived, the user record and their identifiers, integrations and chats are deleted. For the full cascade use DELETE /users/:userId.
curl https://api.agnt.ai/users/deprovision \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]", "teamId": "6702ab9fd4e5f6a7b8c9d0e1" }'
{ "ok": true, "deleted": true, "userDeleted": true, "userId": "6702b23a0b1c2d3e4f5a6b7c" }
emailandteamIdare required. The team must be in your account, and in the key's organization for an organization-scoped key, or the call returns404.- An email that matches no user returns
200withdeleted: false. userDeleted: falsemeans the user still has another membership, so the user record and its data remain.
Deprovisioning is refused, with nothing changed, when it would leave something without an administrator:
| Status | Flag | When | Resolve by |
|---|---|---|---|
409 | requiresOrgAdminTransfer: true, organizationId | The user is the organization's only admin | Promote another user with PUT /users/:userId |
400 | requiresOwnershipTransfer: true, teamId | The user owns a team with other active members | POST /teams/:teamId/transfer-ownership |
DELETE /users/:userId deletes a user outright, whatever their memberships, with the same two refusals. Deletion runs asynchronously: the response confirms it is scheduled. DELETE /organizations/:orgId/members/:userId also returns 409 requiresOrgAdminTransfer for the only admin.
SAML SSO
Each organization can sign its users in through its own SAML 2.0 identity provider (IdP), such as Okta, Microsoft Entra ID or Google Workspace. A user enters their email on your app's hosted domain. If the domain is verified by an organization with SSO enabled, the user is sent to that organization's IdP.
-
Register the service provider in the IdP:
IdP setting Value ACS (reply) URL https://<your app's hosted domain>/api/sso/saml/acsSP entity ID and metadata https://<your app's hosted domain>/api/sso/saml/metadataSingle logout URL https://<your app's hosted domain>/api/sso/saml/sloAttributes Email, first name, last name and, optionally, groups -
Configure the organization with the IdP's details:
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/sso \ -X PUT \ -H "Authorization: Bearer $AGNT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "enforced": true, "provider": "saml_generic", "saml": { "entryPoint": "https://harborview.okta.com/app/harborview_agnt/exk7q2m9/sso/saml", "certificate": "MIIDqDCCApCgAwIBAgIGAYk3HarborviewSigningCert", "attributeMapping": { "email": "email", "firstName": "givenName", "lastName": "sn", "groups": "groups" }, "groupFilter": { "enabled": true, "allowedGroups": ["harborview-staff"] }, "groupRoleMapping": [ { "group": "harborview-it", "role": "admin" } ] }, "memberSync": { "autoProvision": true } }'
| Name | Type | Description |
|---|---|---|
enabled | boolean | Turns SSO sign-in on for the organization's verified domains. |
enforced | boolean | Users at those domains, and members of the organization, can sign in only through SSO. Other sign-in methods return 403 sso_required. |
provider | string | saml_generic. Every SAML 2.0 IdP connects through it. |
saml.entryPoint | string | The IdP's SSO URL. Required, with certificate, before sign-in works. |
saml.certificate | string | The IdP's signing certificate. Every response is verified against it. Never returned. |
saml.issuer | string | The IdP's entity ID, stored for your reference. |
saml.signatureAlgorithm | string | Default sha256. |
saml.attributeMapping | object | Attribute names for email, firstName, lastName and groups. Defaults to those names. The email falls back to the NameID. |
saml.groupFilter | object | { enabled, allowedGroups, requireAll }. Only users in any of these groups (all of them, with requireAll) may sign in. Case-insensitive. |
saml.groupRoleMapping | array | [{ group, role }] with role admin or member. Sets the user's organization role at each sign-in. The first matching group wins. |
saml.allowIdpInitiated | boolean | Default false. When true, sign-ins started from the IdP's dashboard are accepted. |
memberSync.autoProvision | boolean | true creates a user on first sign-in. false admits only users you have already provisioned. |
SSO guarantees:
- Assertions must be signed. An unsigned assertion, or one that fails verification against
certificate, is rejected. - An assertion must be addressed to your ACS URL, be within its validity window, and is accepted once for IdP-initiated sign-in. SP-initiated sign-in must complete within 10 minutes of starting.
- The signed-in email must belong to one of the organization's verified domains.
PUT merges each object you send into the stored configuration, so you can rotate saml.certificate alone. DELETE /organizations/:orgId/sso clears the SSO configuration, including the SCIM token.
SCIM 2.0
SCIM lets the customer's IdP create, update and deactivate users and manage teams. It works with or without SAML SSO. Mint the organization's token:
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/sso/scim-token \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY"
{ "ok": true, "scim": { "token": "9b1e0c4f7a2d8e3b6c5a1f0d9e8b7c6a" } }
The token is shown once, and only a hash is stored. Each organization has one token: minting a new one invalidates the previous one immediately. Give the IdP the token as a bearer token and this base URL on your app's hosted domain:
https://<your app's hosted domain>/api/scim/v2
| Method | Path | Behavior |
|---|---|---|
| GET | /Users | Users in the organization. Supports startIndex, count (max 200) and filter=userName eq "[email protected]". |
| POST | /Users | Creates a user in the organization from userName (or the first of emails) and name. Returns 409 if the email exists in the account. |
| GET | /Users/:id | One user. |
| PUT, PATCH | /Users/:id | Updates name.givenName, name.familyName and active. active: false blocks the user. |
| DELETE | /Users/:id | Deactivates the user and keeps their data. Deprovision to delete it. |
| GET, POST | /Groups | Teams in the organization. POST creates a team from displayName. |
| GET, PUT, PATCH, DELETE | /Groups/:id | Renames a team, or adds, removes and replaces members. DELETE deletes the team and archives its memberships. |
| GET | /ServiceProviderConfig | Patch and filter are supported. Bulk and password change are not. |
Responses use application/scim+json. User ids are AGNT user ids and userName is the email. Adding a user to a group moves them from their current team. A user in a different organization is skipped, as is a user who owns another team that still has active members.
Audit events
Administrative actions are recorded as audit events: organization, domain and SSO changes, membership and role changes, team policy changes, audit-export changes and SSO sign-ins. Actions by a signed-in user, or an API key acting as one with X-User-Email, who belongs to a team in an organization with audit logging enabled are recorded. Account-wide key calls without X-User-Email and SCIM changes are not. Events are archived nightly. The API serves the most recent 30 days.
curl "https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/audit-events?action=sso.updated&after=2026-11-01T00:00:00Z" \
-H "Authorization: Bearer $AGNT_API_KEY"
{
"ok": true,
"events": [
{
"id": "6702d1a8e9f0a1b2c3d4e5f6",
"account": "66f1a2b3c4d5e6f708192a3b",
"organization": "6702a9c3e1b4f5d6a7b8c901",
"actor": "[email protected]",
"action": "sso.updated",
"entityType": "organization",
"entityId": "6702a9c3e1b4f5d6a7b8c901",
"metadata": { "provider": "saml_generic", "enabled": true, "enforced": true },
"createdAt": "2026-11-02T16:24:11.000Z"
}
],
"page": 1,
"perPage": 20,
"total": 1
}
| Name | Type | Description |
|---|---|---|
actor | string | The actor's email. Exact match. |
action | string | Such as sso.updated or domain.verified. |
entityType | string | Such as organization or domain. |
after, before | date-time | Time range. |
page, perPage | integer | Newest first. perPage max 100. |
GET /audit-events returns events across your account and also accepts entityId. GET /audit-events/:eventId returns one event.
Export audit events to S3
Deliver audit events to the customer's own S3 bucket to keep them beyond 30 days.
-
In the customer's AWS account, create an IAM role with this permissions policy:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::harborview-agnt-audit/agnt/*" }] }The role's trust policy must allow only the AGNT account that delivers audit exports. Contact [email protected] for the account ID and the exact role to trust. Do not trust the account root. Use a dedicated bucket with versioning enabled.
-
Configure the organization:
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/audit-logging \ -X PUT \ -H "Authorization: Bearer $AGNT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "s3BucketArn": "arn:aws:s3:::harborview-agnt-audit", "s3Prefix": "agnt", "roleArn": "arn:aws:iam::210987654321:role/agnt-audit-writer", "region": "us-west-2" }'The response returns the stored configuration with
"deliveryConfigured": true. -
Deliver a time range. The call returns
202with a delivery job:curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/audit-logging/deliver \ -X POST \ -H "Authorization: Bearer $AGNT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "2026-11-01T00:00:00Z", "to": "2026-11-02T00:00:00Z" }' -
Read the job's status with
GET /organizations/:orgId/audit-logging/deliver/:jobId:{ "ok": true, "deliveryJob": { "id": "6702d2b9f0a1b2c3d4e5f6a7", "organization": "6702a9c3e1b4f5d6a7b8c901", "requestedBy": "[email protected]", "status": "completed", "from": "2026-11-01T00:00:00.000Z", "to": "2026-11-02T00:00:00.000Z", "filesCopied": 1, "deliveryErrors": [], "completedAt": "2026-11-02T16:25:03.000Z", "createdAt": "2026-11-02T16:24:11.000Z" } }
| Name | Type | Description |
|---|---|---|
enabled | boolean | Turns audit logging on for the organization. Delivery returns 403 while it is false. |
s3BucketArn | string | The destination bucket. Delivery returns 400 until both s3BucketArn and roleArn are set. |
s3Prefix | string | Key prefix. Default agnt-audit-logs. |
roleArn | string | The IAM role assumed to write. |
region | string | The bucket's region. Default us-east-1. |
- Each delivery copies one range. Without
fromandto, it covers the 30 days up to 00:00 UTC today. To keep a continuous copy, call deliver on a schedule, for example daily. - Files are JSON Lines, written to
<s3Prefix>/year=YYYY/month=MM/day=DD/. - Delivery is idempotent: delivering a range again overwrites the same objects with the same content.
- Job
statusispending,running,completedorfailed.
Policy
You set the ceiling for your app in the AGNT console. Below it, each control is inherited, tightened or locked. A tier can change a control only where no tier above it has locked it.
| Control | Account (console) | Organization | Team |
|---|---|---|---|
| Skills | Store tiers offered; skills blocked or allowed app-wide; whether users can browse, install, create and share | Skill library: allowed tiers and enabled skills | Store on or off, allowlist, blocklist; create and share rules |
| MCP | mcpAccessLevel cap and lock; whether custom MCP servers can be added | Its own cap and lock; custom MCP servers Inherit, On or Off | |
| Connections | Allowed account types; access per resource with locks; connection catalog | The same fields; each connection Inherit, On or Off | |
| Computer use | Workspace switches with locks; restricted preset | The same switches and preset | |
| Autonomy | Approval mode per action type, and locks | The same, except cells the organization locked | |
| Model tiers | Default chat and task tiers | Default chat and task tiers | |
| Kill switch | Freezes every outbound action for the account |
How tiers combine:
- Computer use and the restricted preset. An
"off"at the account or the user's team wins. With no setting anywhere, each switch is on. See Computer use. - MCP and connection access. The most restrictive level across account, team and user applies. A lock forces the admin's level.
- Skill store. A team with the store off wins. Blocklists add up across tiers. Allowlists narrow.
- Skill library. When an organization configures its library, a skill is available to its users only if its tier is in
allowedTiersand its id is inenabledSkills. Skills the platform installs as locked are always available. An organization with no library configuration inherits everything. - Autonomy. An organization lock pins the cell for every team and user in it. Modes, defaults and the order in which a mode is decided are in Autonomy.
- Connection catalog. A team's Inherit, On or Off decides whether a connection is offered to the team's users in the hosted app. A team value takes precedence over the account's.
Account-tier settings are changed only by account admins signed in to the console. Organization and team settings accept an account-wide key or an admin of that organization or team.
Set team policy
Cap MCP at read-only, pin calendar access to read-only, block one skill, and stop the Leasing team from adding its own MCP servers:
curl https://api.agnt.ai/teams/6702ab52c3d4e5f6a7b8c9d0/settings/resource-permissions \
-X PATCH \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mcpAccessLevel": "read",
"mcpLocked": true,
"connections": {
"allowedTypes": ["google", "azure"],
"connectionPermissions": { "google": { "calendar": "read" }, "azure": { "calendar": "read" } },
"connectionLocks": { "google": { "calendar": true }, "azure": { "calendar": true } }
},
"store": { "blocklist": ["6702c915c6d7e8f9a0b1c2d3"] }
}'
curl https://api.agnt.ai/teams/6702ab52c3d4e5f6a7b8c9d0/settings/custom-mcp \
-X PATCH \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "allowCustomMcp": "off" }'
On team settings, null (or "inherit") inherits and a value is an explicit setting. A lock pins a value so the user's own preference is ignored. A lock with no value is rejected.
| Name | Type | Description |
|---|---|---|
mcpAccessLevel | string or null | off, read or read_write. |
mcpLocked | boolean or null | Locks mcpAccessLevel. Requires a team value. |
connections.allowedTypes | array or null | null inherits, [] allows all, or a list of account types. |
connections.connectionPermissions | object | { <type>: { <resource>: "off" | "read" | "read_write" | null } } |
connections.connectionLocks | object | { <type>: { <resource>: true | false | null } }. A value is required before a lock. A locked value cannot be cleared without clearing its lock in the same request. |
capabilities | object | Computer-use switches. See Computer use. |
store | object | { enabled, allowlist, blocklist } of skill ids. null inherits. |
skills | object | canBrowseStore, canInstallFromStore, canCreate, requireApproval, canShareWithTeam, requirePermissionToShare: true, false or null. |
users | object | createSkills, shareSkills: true, false or null. |
approvalSettings.matrix | object | Autonomy cells and locked. Cells the organization locked are ignored. |
Account types are google, azure (Microsoft), apple, slack, zoom, asana, hubspot, imap, or mcp:<name> for an MCP connection. Resources are calendar, contacts, email, drive, messaging, video, teams, projects and crm.
GET /teams/:teamId/settings/resource-permissions returns the team's stored values plus the organization's locked autonomy cells (orgLockedCells, orgLockedValues), so an admin UI can show what it cannot change.
To set a connection's catalog state for a team, send { "enabled": "inherit" | "on" | "off" } to PATCH /teams/:teamId/settings/connections/:connectionId. GET /teams/:teamId/settings/connections lists each connection with orgEnabled, teamEnabled and effectiveState.
Apply the restricted security preset
The restricted preset turns off and locks MCP servers (including custom ones), the workspace shell, browser automation and workspace handoff in one call. Apply it to the Maintenance team:
curl https://api.agnt.ai/teams/6702ab9fd4e5f6a7b8c9d0e1/settings/security-preset \
-X POST \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "preset": "restricted" }'
Apply it to the whole account in the AGNT console. See Computer use for what each switch covers.
Set organization policy
Offer Harborview's users only first-party and official skills, and only the ones listed:
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/library \
-X PATCH \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "allowedTiers": ["agnt", "official"], "enabledSkills": ["6702c915c6d7e8f9a0b1c2d3"] }'
allowedTiers takes agnt, official and community. bulkEnableTier (one tier name) adds every published skill in that tier to enabledSkills.
To set and lock autonomy for the organization, use PATCH /organizations/:orgId/settings/resource-permissions. See Autonomy.
Default model tiers
Set the organization's default tiers for new chats and tasks. They apply between a task's own tier and your account's default.
curl https://api.agnt.ai/organizations/6702a9c3e1b4f5d6a7b8c901/settings/model-tiers \
-X PATCH \
-H "Authorization: Bearer $AGNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "chat": "medium", "task": "high" }'
{ "ok": true, "defaultModelTiers": { "chat": "medium", "task": "high" } }
Values are low, medium, high, ultra, or null to inherit your account's default. See Model tiers.
Endpoint reference
Every endpoint accepts an account-wide API key. Organization endpoints also accept an admin of that organization, and team endpoints an admin of that team.
| Method | Path | Description |
|---|---|---|
POST | /users/provision | Find or create a user and place them on a team |
POST | /users/deprovision | Remove a user from a team; delete the user if no membership remains |
GET | /users | List users |
PUT | /users/:userId | Update profile, organization, organizationRole, status |
DELETE | /users/:userId | Delete a user and their data (asynchronous) |
GET POST | /teams | List; create |
GET PUT DELETE | /teams/:teamId | Read; update; delete |
GET POST | /teams/:teamId/members | List; add |
PUT DELETE | /teams/:teamId/members/:memberId | Change role or status; remove |
POST | /teams/:teamId/transfer-ownership | Transfer ownership, as the current owner |
GET PATCH | /teams/:teamId/settings/resource-permissions | Team policy |
POST | /teams/:teamId/settings/security-preset | Apply the restricted preset |
GET | /teams/:teamId/settings/connections | Connection catalog with account and team state |
PATCH | /teams/:teamId/settings/connections/:connectionId | Set a connection's catalog state |
PATCH | /teams/:teamId/settings/custom-mcp | Allow or block custom MCP servers |
GET POST | /organizations | List; create |
GET PUT DELETE | /organizations/:orgId | Read; update; delete |
GET POST | /organizations/:orgId/members | List; add and notify |
DELETE | /organizations/:orgId/members/:userId | Remove from the organization and its teams |
GET POST | /organizations/:orgId/domains | List; add |
PUT DELETE | /organizations/:orgId/domains/:domainId | Update auto-join; remove |
POST | /organizations/:orgId/domains/:domainId/verify | Check the TXT record |
PUT DELETE | /organizations/:orgId/sso | Configure (merge); clear |
POST | /organizations/:orgId/sso/scim-token | Mint the SCIM token |
GET PATCH | /organizations/:orgId/settings/resource-permissions | Autonomy matrix and locks |
GET PATCH | /organizations/:orgId/library | Skill library |
GET PATCH | /organizations/:orgId/settings/model-tiers | Default model tiers |
GET | /organizations/:orgId/audit-events | The organization's audit events |
GET PUT | /organizations/:orgId/audit-logging | S3 export configuration |
POST | /organizations/:orgId/audit-logging/deliver | Start a delivery |
GET | /organizations/:orgId/audit-logging/deliver/:jobId | Delivery status |
GET | /audit-events | Account-wide audit events |
GET | /audit-events/:eventId | One audit event |
SAML (/api/sso/saml/acs, /api/sso/saml/metadata, /api/sso/saml/slo) and SCIM (/api/scim/v2) are served on your app's hosted domain, not api.agnt.ai.
Limits
- Audit events are served for 30 days. Export them to keep them longer.
- List endpoints page with
pageandperPage(default 20, max 100). SCIM pages withstartIndexandcount(default 100, max 200), filters only onuserName eq, and has no bulk operations. - Up to 10 organizations can be created per account per minute.
- SAML sign-in and SCIM serve users of the hosted app. If you build your own sign-in, provision and deprovision from your backend.
- Organization-scoped API keys act only within their organization, and with
X-User-Emailthey are limited to organization admin operations. See Authentication.