Summary and recommendation
Agiloft exposes a REST API at `https://{instance}.agiloft.com/ewws/rest/{kb}/` that supports full CRUD operations on the People table, covering user creation, profile updates, deactivation, and deletion.
Authentication is via Basic Auth (Base64-encoded `username:password` in the `Authorization` header) or a session token obtained from `POST /ewws/rest/{kb}/login`; session tokens expire and require refresh logic, making Basic Auth simpler for server-to-server integrations. There is no native SCIM 2.0 endpoint - provisioning and deprovisioning must be implemented entirely through REST calls.
The knowledge base (KB) name is a required path segment in every request URL, and internal field names in the API may differ from display labels shown in the admin UI. Rate limits are not publicly documented; behavior is instance-specific and should be validated in a staging environment before production automation.
Pagination uses `limit` and `offset` query parameters, with a default page size of 10 and a maximum of 1,000 records per request. Stitchflow connects to Agiloft through an MCP server with ~100 deep IT/identity integrations, normalizing Agiloft's REST API surface into a consistent provisioning and deprovisioning interface alongside the rest of your app stack.
API quick reference
| Has user API | Yes |
| Auth method | Basic Auth (username:password Base64-encoded) or session token obtained via login endpoint |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | Enterprise |
Authentication
Auth method: Basic Auth (username:password Base64-encoded) or session token obtained via login endpoint
Setup steps
- Identify your Agiloft instance hostname (e.g., yourcompany.agiloft.com).
- Create or designate an API user account in Agiloft with appropriate permissions.
- For Basic Auth: Base64-encode 'username:password' and pass as Authorization: Basic
header. - Alternatively, POST credentials to the login endpoint to obtain a session token, then pass it as a cookie or header on subsequent requests.
- Ensure the API user has read/write access to the relevant tables (e.g., People/Users table).
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| login_name | string | Unique login username | required | optional | Used for authentication; must be unique. |
| password | string | User password (hashed internally) | required | optional | Not returned in GET responses. |
| first_name | string | User's first name | required | optional | |
| last_name | string | User's last name | required | optional | |
| string | Primary email address | required | optional | Used for notifications. | |
| phone | string | Phone number | optional | optional | |
| department | string | User's department | optional | optional | |
| title | string | Job title | optional | optional | |
| groups | array | Group memberships | optional | optional | Controls permissions and access. |
| is_active | boolean | Whether the user account is active | optional | optional | Set to false to disable without deleting. |
| locale | string | User locale/language preference | optional | optional | |
| timezone | string | User timezone | optional | optional | |
| id | integer | Internal record ID | system-generated | read-only | Used to reference the record in API calls. |
| created_date | datetime | Record creation timestamp | system-generated | read-only | |
| modified_date | datetime | Last modification timestamp | system-generated | read-only |
Core endpoints
List users
- Method: GET
- URL:
https://{instance}.agiloft.com/ewws/EWService?wsdl (REST: GET /ewws/rest/{kb}/People) - Watch out for: The table name for users may vary by KB configuration (commonly 'People' or 'Users'). Confirm the exact table name in your Agiloft instance.
Request example
GET /ewws/rest/mykb/People?limit=50&offset=0
Authorization: Basic <base64creds>
Response example
{
"records": [
{"id": 101, "login_name": "jdoe", "first_name": "Jane", "last_name": "Doe", "email": "jdoe@example.com", "is_active": true}
],
"total": 1
}
Get user by ID
- Method: GET
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/People/{id} - Watch out for: ID must be the internal Agiloft record integer ID, not the login_name.
Request example
GET /ewws/rest/mykb/People/101
Authorization: Basic <base64creds>
Response example
{
"id": 101,
"login_name": "jdoe",
"first_name": "Jane",
"last_name": "Doe",
"email": "jdoe@example.com",
"is_active": true
}
Create user
- Method: POST
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/People - Watch out for: Required fields depend on KB configuration. Mandatory fields set in the Agiloft admin UI must be satisfied or the API will return a validation error.
Request example
POST /ewws/rest/mykb/People
Authorization: Basic <base64creds>
Content-Type: application/json
{
"login_name": "jsmith",
"first_name": "John",
"last_name": "Smith",
"email": "jsmith@example.com",
"password": "SecurePass1!"
}
Response example
{
"id": 205,
"login_name": "jsmith",
"first_name": "John",
"last_name": "Smith",
"email": "jsmith@example.com"
}
Update user
- Method: PUT
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/People/{id} - Watch out for: Agiloft REST API typically uses PUT (full or partial update behavior may vary by version). Confirm whether PATCH is supported on your instance version.
Request example
PUT /ewws/rest/mykb/People/205
Authorization: Basic <base64creds>
Content-Type: application/json
{
"email": "jsmith.new@example.com",
"is_active": true
}
Response example
{
"id": 205,
"email": "jsmith.new@example.com",
"is_active": true
}
Deactivate/disable user
- Method: PUT
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/People/{id} - Watch out for: There is no SCIM-based deprovisioning. Disabling via API requires knowing the internal record ID. No automatic deprovisioning on SSO session end.
Request example
PUT /ewws/rest/mykb/People/205
Authorization: Basic <base64creds>
Content-Type: application/json
{
"is_active": false
}
Response example
{
"id": 205,
"is_active": false
}
Search users (query)
- Method: GET
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/People?query=... - Watch out for: Query syntax follows Agiloft's internal expression language. Refer to the KB-specific field names; they may differ from display labels.
Request example
GET /ewws/rest/mykb/People?query=login_name='jdoe'&limit=10
Authorization: Basic <base64creds>
Response example
{
"records": [
{"id": 101, "login_name": "jdoe", "email": "jdoe@example.com"}
],
"total": 1
}
Delete user
- Method: DELETE
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/People/{id} - Watch out for: Deletion is permanent. Prefer setting is_active=false for audit trail preservation. Deletion may be restricted by referential integrity if the user is linked to contracts or records.
Request example
DELETE /ewws/rest/mykb/People/205
Authorization: Basic <base64creds>
Response example
{
"status": "deleted",
"id": 205
}
Authenticate / obtain session token
- Method: POST
- URL:
https://{instance}.agiloft.com/ewws/rest/{kb}/login - Watch out for: Session tokens expire. Implement token refresh logic. Alternatively use Basic Auth on every request to avoid session management.
Request example
POST /ewws/rest/mykb/login
Content-Type: application/json
{
"login": "apiuser",
"password": "apipassword"
}
Response example
{
"token": "abc123sessiontoken",
"expires": "2024-12-31T23:59:59Z"
}
Rate limits, pagination, and events
Rate limits: No publicly documented rate limits found in official Agiloft documentation.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: Rate limiting behavior is not publicly specified. Agiloft is a self-hosted or private-cloud product; limits may be instance-specific or configurable by the administrator.
Pagination method: offset
Default page size: 10
Max page size: 1000
Pagination pointer: limit / offset (query parameters)
Webhooks available: Yes
Webhook notes: Agiloft supports outbound actions and rule-based notifications that can POST data to external URLs (webhook-like behavior) when records are created or modified. This is configured via Agiloft's built-in automation rules.
Alternative event strategy: Use Agiloft's scheduled REST API polling if webhook-style push is not sufficient. Agiloft's native automation rules can call external HTTP endpoints on record events.
Webhook events: Record created (e.g., new user/People record), Record updated, Record deleted, Field value change trigger
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: Enterprise
- Endpoint: Not documented
Limitations:
- No native SCIM 2.0 support.
- JIT provisioning only – users are created on first SSO login via SAML attribute mapping.
- User attribute updates occur via SAML attributes on subsequent logins.
- No automatic deprovisioning; accounts must be manually disabled or deactivated via REST API or admin UI.
- Okta and Entra ID supported for SSO/JIT; no SCIM provisioning connector available.
Common scenarios
Three automation scenarios cover the majority of identity lifecycle events in Agiloft. For provisioning, POST to /ewws/rest/{kb}/People with login_name, first_name, last_name, email, password, and optionally groups.
required fields are KB-specific and a missing mandatory field returns a validation error - confirm the schema with your Agiloft admin before automating at scale. For deprovisioning, search by login_name via `GET /ewws/rest/{kb}/People?
query=login_name='jdoe', retrieve the internal integer record ID, then PUT {"is_active": false}` to disable the account. critically, disabling via API does not terminate active sessions, and if SAML SSO is active, the user will be JIT re-provisioned on their next login attempt unless also removed from the IdP.
For HR-driven profile sync, retrieve the record ID by login_name, then PUT updated fields (email, department, title, etc. ); be aware that SAML attribute assertions on subsequent logins may overwrite fields managed by JIT mapping, depending on your IdP configuration.
Prefer setting is_active=false over DELETE in all deprovisioning flows - deletion is permanent, may be blocked by referential integrity constraints if the user is linked to contracts or records, and destroys audit trail data.
Provision a new user via REST API
- Authenticate using Basic Auth or obtain a session token via POST /ewws/rest/{kb}/login.
- POST to /ewws/rest/{kb}/People with required fields: login_name, first_name, last_name, email, password.
- Capture the returned record ID for future updates.
- Optionally assign the user to groups by including the groups field in the payload.
Watch out for: Required fields are KB-specific. A missing mandatory field returns a validation error. Confirm schema with your Agiloft admin before automating.
Deprovision a user when they leave the organization
- Search for the user by login_name: GET /ewws/rest/{kb}/People?query=login_name='jdoe'.
- Retrieve the internal record ID from the response.
- PUT /ewws/rest/{kb}/People/{id} with {"is_active": false} to disable the account.
- Optionally revoke SSO access in your IdP (Okta/Entra) to prevent JIT re-provisioning on next login.
Watch out for: Disabling via API does not automatically revoke active sessions. Also disable the user in your IdP to prevent JIT re-creation on next SSO login attempt.
Sync user profile updates from HR system
- On HR system change event, identify the affected user's Agiloft login_name.
- GET /ewws/rest/{kb}/People?query=login_name='{login}' to find the record ID.
- PUT /ewws/rest/{kb}/People/{id} with updated fields (email, department, title, etc.).
- Log the API response and handle errors (e.g., field validation failures).
Watch out for: If SAML SSO is active, some attributes (email, name) may be overwritten by SAML assertions on the user's next login, depending on JIT attribute mapping configuration.
Why building this yourself is a trap
The primary automation trap in Agiloft is the JIT/SCIM gap: because there is no SCIM endpoint, removing a user from Okta or Entra ID does not trigger any action in Agiloft.
A user deprovisioned in the IdP retains a fully active Agiloft account until the REST API is called explicitly to set is_active=false and Group memberships are cleared. A second trap is the KB-scoped URL structure - every API call must include the correct KB identifier, and multi-KB deployments require separate automation logic per KB.
Field name mismatches between the UI and API are a consistent source of integration failures; internal field names must be verified via admin schema inspection, not inferred from display labels. Session token expiry is an operational risk for long-running automation jobs; implement refresh logic or use Basic Auth with a dedicated service account.
Finally, the People table schema is deployment-specific: required fields, available fields, and group assignment behavior vary per KB configuration, meaning automation built against one instance may not transfer to another without schema re-validation.
Automate Agiloft workflows without one-off scripts
Stitchflow builds and maintains identity workflows for your exact setup. We cover every app, including the ones without APIs, and run deterministic trigger-to-report workflows with human approvals where they matter.