API Reference
Quick Start
Getting an Access Key
To use the Mesh API, you need an Access Key. Access Keys are created through the mesh CLI.
Step 1. Log in to the CLI with your Google account:
$ mesh login
Step 2. Create a personal Access Key:
$ mesh accesskey create --name "my-script" Key ID: ak_01JQ... Secret: mesh_sk_abc123... Role: viewer Expires: never Save this key — it cannot be retrieved later.
Step 3. Use the key in API requests:
curl https://mesh.langgenius.ai/api/v1/employees \ -H "Authorization: Bearer mesh_sk_abc123..."
mesh admin accesskey create --name "slack-bot" --role viewer.Conventions
Authentication
Most endpoints require authentication via one of the following methods:
// Access Key (for scripts and integrations) Authorization: Bearer mesh_sk_xxxx // Session Token (for CLI sessions) Authorization: Bearer mesh_at_xxxx // Stub (NODE_ENV=development only) Authorization: Bearer stub:you@langgenius.ai
Response Format
All responses include an X-Request-Id header.
// Success { "data": <payload> } // Success + Pagination { "data": [...], "meta": { "page": 1, "limit": 20, "total": 86, "totalPages": 5 } } // Error { "error": { "code": "NOT_FOUND", "message": "Employee not found", "requestId": "req_abc123def456" } }
Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Request parameter validation failed |
| 401 | UNAUTHORIZED | Not authenticated or token invalid |
| 403 | FORBIDDEN | Insufficient permissions |
| 404 | NOT_FOUND | Resource not found |
| 409 | CONFLICT | General conflict |
| 409 | EMPLOYEE_NUMBER_TAKEN | Employee number already in use |
| 409 | DEPARTMENT_NAME_EXISTS | Department name already exists |
| 409 | EMPLOYEE_IM_PLATFORM_EXISTS | Duplicate IM platform for the same employee |
| 409 | LAST_ADMIN_CANNOT_DEMOTE | The last admin cannot be demoted |
| 409 | OFFBOARD_HAS_DEPENDENTS | Cannot offboard while employee has direct reports |
| 409 | OFFBOARD_HAS_PROJECT_OWNERSHIP | Cannot offboard while employee is a project owner |
| 401 | ACCESS_KEY_EXPIRED | Access Key has expired |
| 500 | INTERNAL_ERROR | Internal server error |
Pagination
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
limit | number | 20 | Items per page, max 100 |
Deletion Policy
Hard deletion is not supported for employees, departments, projects, legal entities, or offices. To "delete" these resources, use PATCH to set isActive = false for a soft deactivation. Sub-resources (phones, IMs, titles, employment records, mentorship relations, department members, project members) support hard deletion via DELETE.
Permission Roles
| Role | Scope |
|---|---|
viewer | All GET queries + self-service profile updates |
editor | viewer + all business write operations |
admin | editor + Google Sync, Access Key, and role management |
Employee Reference Values
All :id parameters accept three formats: email, employeeNumber (e.g. LG-0003), or internal id. The first two are recommended.
Health & Meta
Response
{ "status": "ok" }
Returns the latest CLI version declared by the server, used for lightweight upgrade prompts. Source: environment variable LATEST_CLI_VERSION.
Response
{ "data": { "latestVersion": "0.2.0" } }
Response
{
"data": {
"latestVersion": "0.2.0",
"apiVersion": "v1",
"supportedApiVersions": ["v1"]
}
}
Auth & Session
Only available when NODE_ENV=development. Pass an email address to receive session tokens.
Request Body
{ "email": "luyu@langgenius.ai" }
Response
{
"data": {
"accessToken": "mesh_at_...",
"refreshToken": "mesh_rt_...",
"expiresAt": "2026-04-06T12:00:00.000Z",
"employee": {
"id": "clx...", "employeeNumber": "LG-0001",
"email": "luyu@langgenius.ai", "displayName": "Luyu Zhang",
"role": "admin", "isActive": true
}
}
}
Use a refresh token to obtain a new token pair. The old refresh token is invalidated immediately; if replay is detected, all active sessions for the employee are revoked.
Request Body
{ "refreshToken": "mesh_rt_..." }
Response
{
"data": {
"accessToken": "mesh_at_...",
"refreshToken": "mesh_rt_...",
"expiresAt": "2026-04-06T13:00:00.000Z"
}
}
The web login page sends a Google ID token to this endpoint. After validation, the API generates a one-time code (valid for 5 minutes).
Request Body
{ "idToken": "eyJhbGciOiJSUzI1NiIs..." }
Response
{
"data": {
"code": "MESH-7K3F",
"expiresAt": "2026-04-06T12:05:00.000Z",
"employee": { "email": "luyu@langgenius.ai", "displayName": "Luyu Zhang" }
}
}
INITIAL_ADMIN_EMAIL logs in for the first time and no matching employee exists, an employee record is automatically created with the admin role.A lightweight login page opened in the browser with Google Sign-In integration. The parameter cli=true enables CLI mode; api_url specifies the API base URL.
The CLI sends the code pasted by the user to this endpoint in exchange for Mesh session tokens. The code is invalidated immediately after use and expires automatically if unused within 5 minutes.
Request Body
{ "code": "MESH-7K3F" }
Response
{
"data": {
"accessToken": "mesh_at_...",
"refreshToken": "mesh_rt_...",
"expiresAt": "2026-04-06T12:00:00.000Z",
"employee": { "id": "clx...", "email": "luyu@langgenius.ai", "role": "admin" }
}
}
Response (Personal Key / OAuth)
{
"data": {
"principal": {
"actorType": "user", "role": "viewer",
"authKind": "api_key", "email": "minco@langgenius.ai"
},
"employee": {
"id": "emp_minco", "employeeNumber": "LG-0003",
"email": "minco@langgenius.ai", "displayName": "Minco Wang",
"role": "viewer", "isActive": true
}
}
}
employee is null.Request Body
{
"name": "my-bot",
"expiresAt": "2026-07-01T00:00:00.000Z" // optional
}
Response
{
"data": {
"id": "key_01", "key": "mesh_sk_abc123...",
"name": "my-bot", "role": "viewer",
"createdAt": "2026-04-05T10:00:00Z",
"expiresAt": "2026-07-01T00:00:00Z"
}
}
key is returned only once at creation time and cannot be retrieved later.Response
{
"data": [{
"id": "key_01", "name": "my-bot", "role": "viewer",
"createdAt": "2026-04-05T10:00:00Z",
"lastUsedAt": "2026-04-05T12:30:00Z",
"expiresAt": "2026-07-01T00:00:00Z"
}]
}
Response: 204 No Content
Passkey
Returns WebAuthn public-key credential request options for initiating a Passkey login ceremony.
Validates the WebAuthn assertion and returns a one-time login code. Response: 201 Created
Returns WebAuthn credential creation options for registering a new Passkey. Authenticates via loginCode in the request body.
Completes Passkey registration using a one-time login code for authentication. Response: 201 Created
Returns WebAuthn credential creation options for registering a new Passkey. Requires Bearer token authentication.
Completes Passkey registration using Bearer token authentication. Response: 201 Created
Returns all Passkeys registered to the authenticated employee.
Removes a registered Passkey. Response: 204 No Content
SSO / OAuth2
1. Register your app in the
OAuthClient database table (client_id, secret hash, redirect URIs).2. Redirect users to
/auth/authorize?client_id=...&redirect_uri=...&state=...3. After login, Mesh redirects back to your
redirect_uri with ?code=...&state=...4. Exchange the code via
POST /auth/token with your client_secret.5. Use the returned
accessToken to call GET /auth/me for user identity.Renders the login page in SSO mode. The user authenticates and is redirected back to the client application.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
client_id | string | Required. The registered client identifier. |
redirect_uri | string | Required. URI to redirect after authorization. |
state | string | Required. Opaque value for CSRF protection. |
Exchanges a one-time loginCode (from Passkey or Google login) for an OAuth2 authorization code. Response: 201 Created
Standard OAuth2 token endpoint. Exchanges an authorization code for access and refresh tokens (authorization_code grant type).
Employees
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page, limit | number | Pagination |
departmentId | string | Filter by department |
primaryOfficeId | string | Filter by primary office |
legalEntityId | string | Filter by legal entity |
countryCode | string | Filter by country (CN, US) |
employmentType | string | FULL_TIME, INTERN, LABOR, CONSULTANT |
role | string | viewer, editor, admin |
isActive | boolean | Active status |
hireDateAfter | string | Hire date lower bound (YYYY-MM-DD) |
hireDateBefore | string | Hire date upper bound (YYYY-MM-DD) |
include | string | Comma-separated: phones, imAccounts, titles |
search | string | Fuzzy search by name, email, or employee number |
Response
{
"data": [{
"id": "clx...", "employeeNumber": "LG-0003",
"legalName": "Haiming Wang", "displayName": "Minco Wang",
"email": "minco@langgenius.ai", "employmentType": "FULL_TIME",
"isActive": true,
"primaryOffice": { "name": "Shanghai", "countryCode": "CN" },
"manager": { "displayName": "Alice Chen", "email": "alice@langgenius.ai" },
"departments": [{ "name": "Backend", "isPrimary": true }],
"primaryTitle": "Senior Engineer"
}],
"meta": { "page": 1, "limit": 20, "total": 86, "totalPages": 5 }
}
:id accepts email, employeeNumber, or internal id. Returns the full employee object including all sub-resources: titles, phones, imAccounts, badges, employments, departments, etc.
Response
{
"data": {
"id": "clx...", "employeeNumber": "LG-0003",
"legalName": "Haiming Wang", "displayName": "Minco Wang",
"romanizedName": "Wang Haiming", "englishName": "Minco Wang",
"email": "minco@langgenius.ai", "githubHandle": "minco",
"hireDate": "2023-06-15", "employmentType": "FULL_TIME",
"isActive": true,
"primaryOffice": { "name": "Shanghai", "timezone": "Asia/Shanghai" },
"manager": { "displayName": "Alice Chen" },
"directReports": [...], "departments": [...],
"titles": [...], "phones": [...],
"imAccounts": [...], "badges": [...],
"employments": [...]
}
}
All fields are optional; only include the fields you want to update.
Request Body
{
"employeeNumber": "LG-0003",
"legalName": "Haiming Wang", "displayName": "Minco Wang",
"romanizedName": "Wang Haiming", "englishName": "Minco Wang",
"githubHandle": "minco", "hireDate": "2023-06-15",
"employmentType": "FULL_TIME",
"primaryOfficeId": "...", "managerId": "..."
}
Response
Returns the full updated employee object.
Employee Lifecycle
When confirm is omitted or set to false, only a preview is returned (dependency checks, action list, blockers). Set confirm: true to execute the offboarding.
Request Body
{ "confirm": true }
Response (Preview)
{
"data": {
"canProceed": true,
"actions": [
"Deactivate employee",
"Close 1 active title: Engineer",
"Remove from 2 projects: Loom, Dify Enterprise"
],
"blockers": []
}
}
canProceed: false, blockers lists the reasons (e.g. has direct reports, is a project owner).Restores from the offboard snapshot: reactivates the employee and restores titles, departments, projects, and mentorship relations. Also supports confirm preview mode.
Employee Relations
Response
{
"data": {
"id": "...",
"displayName": "Alice Chen",
"email": "alice@langgenius.ai",
"avatarUrl": "https://..."
}
}
Response
{
"data": [
{
"id": "...",
"displayName": "Bob Li",
"email": "bob@langgenius.ai",
"avatarUrl": "..."
}
]
}
Response
{
"data": {
"myMentors": [{ "displayName": "Alice", "note": "..." }],
"myMentees": [{ "displayName": "Dave", "note": "..." }]
}
}Request Body
{ "mentorId": "alice@langgenius.ai", "note": "Q1 onboarding" }Response: 201 Created
Response: 204 No Content
Each project includes owner (dotted-line manager) information.
Response
{
"data": [
{ "departmentId": "...", "name": "Backend", "isPrimary": true },
{ "departmentId": "...", "name": "AI Platform", "isPrimary": false }
]
}
Request Body
{ "departmentId": "...", "isPrimary": false }isPrimary: true, the isPrimary flag of all other departments for this employee is automatically set to false.Removing the primary department is not allowed. To change the primary department, first set the new department as primary, then remove the old one. Response: 204 No Content
Employments
Sorted by isCurrent DESC, startDate DESC.
Request Body
{
"legalEntityId": "...", "officeId": "...",
"employmentType": "FULL_TIME", "startDate": "2024-01-01",
"isCurrent": true, "jobTitle": "Senior Engineer",
"note": "Transferred from CN entity"
}isCurrent: true, all other records will have their isCurrent set to false and endDate set to this record's startDate.Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
legalEntityId | string | Legal entity ID |
officeId | string | Office ID |
employmentType | string | FULL_TIME / INTERN / LABOR / CONSULTANT |
startDate | string | YYYY-MM-DD |
endDate | string | YYYY-MM-DD |
isCurrent | boolean | Setting to true automatically closes other records |
jobTitle | string | Job title |
note | string | Note |
Response: the full updated employment record object.
Phones
Response
{
"data": [
{
"id": "...",
"number": "13800138000",
"countryCode": "+86",
"label": "WORK",
"isPrimary": true
}
]
}
Request Body
{
"number": "13800138000", "countryCode": "+86",
"label": "WORK", // WORK | PERSONAL | WHATSAPP | WECHAT | OTHER
"isPrimary": true
}Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
number | string | Phone number |
countryCode | string | Country code, e.g. +86, +1 |
label | string | WORK / PERSONAL / WHATSAPP / WECHAT / OTHER |
isPrimary | boolean | Setting to true automatically unmarks other numbers as primary |
Response: 204 No Content
IM Accounts
Response
{
"data": [
{
"platform": "FEISHU",
"accountId": "ou_xxx",
"username": "minco.wang",
"note": ""
},
{
"platform": "SLACK",
"accountId": "U0123ABC",
"username": "minco",
"note": ""
}
]
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | FEISHU / WECOM / DINGTALK / SLACK |
accountId | string | Yes | Platform user ID |
username | string | No | Platform username (for display) |
note | string | No | Note |
{
"platform": "FEISHU",
"accountId": "ou_xxx",
"username": "minco.wang",
"note": ""
}
Response: 201 Created
Path Parameters
| Parameter | Description |
|---|---|
:platform | FEISHU / WECOM / DINGTALK / SLACK |
Response: 204 No Content
Titles
Query Parameters
| Parameter | Type | Description |
|---|---|---|
current | boolean | true returns only currently active titles |
Response
{
"data": [
{
"id": "...",
"title": "Senior Engineer",
"isPrimary": true,
"isCurrent": true,
"startDate": "2024-01-01",
"endDate": null,
"note": ""
}
]
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Title name |
isPrimary | boolean | No | Setting to true automatically unmarks other primary titles |
startDate | string | No | YYYY-MM-DD, defaults to today |
note | string | No | Note |
{
"title": "Senior Engineer",
"isPrimary": true,
"startDate": "2024-01-01"
}
Response: 201 Created
Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
title | string | Title name |
isPrimary | boolean | Setting to true automatically unmarks other primary titles |
startDate | string | YYYY-MM-DD |
endDate | string | YYYY-MM-DD |
note | string | Note |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
endDate | string | No | YYYY-MM-DD, defaults to today |
Marks the title as isCurrent: false and isPrimary: false, and sets the endDate.
Hard deletes the title record. Response: 204 No Content
Org Chart
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | string | tree | tree (mixed department + employee tree) or graph (matrix relationship graph) |
rootId | string | — | Specify root node (employee reference or department ID); returns only the subtree/subgraph |
format=tree Response
A mixed department + employee tree. Employees are placed under their department. When managerId is inconsistent with department membership, a conflict object is annotated on the node.
{
"data": [{
"type": "employee", "id": "...",
"displayName": "CEO",
"employeeNumber": "LG-0001", "email": "ceo@langgenius.ai",
"children": [{
"type": "department", "id": "...", "name": "Engineering",
"children": [{
"type": "employee", "displayName": "Engineer A",
"conflict": {
"type": "manager_department_mismatch",
"message": "Employee primary department differs from manager."
},
"children": []
}]
}]
}]
}
format=graph Response
Returns a flat nodes + edges structure.
| Edge Type | Source |
|---|---|
department | Department parent-child / DepartmentMember |
manager | Employee.managerId |
project_owner | ProjectMember + Project.ownerId |
mentor | EmployeeRelation |
{
"data": {
"nodes": [
{ "id": "dept_backend", "type": "department", "label": "Backend" },
{ "id": "emp_minco", "type": "employee", "label": "Minco Wang",
"employeeNumber": "LG-0003", "email": "minco@langgenius.ai" }
],
"edges": [
{ "from": "dept_eng", "to": "dept_backend", "type": "department" },
{ "from": "emp_alice", "to": "emp_minco", "type": "manager" }
]
}
}
Departments
Response
{
"data": [{
"id": "...", "name": "Backend",
"description": "...",
"parent": { "id": "...", "name": "Engineering" },
"children": [{ "id": "...", "name": "Backend Infra" }],
"memberCount": 12
}]
}
Returns department info + parent department + child departments + member list.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
recursive | boolean | false | When true, recursively includes members from all child departments |
Response
{
"data": [{
"id": "...", "displayName": "Minco Wang",
"employeeNumber": "LG-0003", "email": "minco@langgenius.ai",
"isPrimary": true,
"department": "Backend" // indicates source when recursive=true
}]
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Department name (unique) |
description | string | No | Department description |
parentId | string | No | Parent department ID; omit for a top-level department |
{
"name": "AI Platform",
"description": "AI platform and infrastructure",
"parentId": "..."
}
Response: 201 Created
Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
name | string | Department name (unique) |
description | string | Department description |
parentId | string | Parent department ID |
isActive | boolean | Set to false to deactivate the department |
Projects
Response
{
"data": [{
"id": "...", "name": "Loom",
"description": "Internal HR API",
"isActive": true,
"owner": {
"id": "...", "employeeNumber": "LG-0001",
"displayName": "John Smith", "email": "john@langgenius.ai"
},
"memberCount": 8
}]
}
Returns project info + owner + member list (including each member's role and employeeNumber).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name |
description | string | No | Project description |
ownerId | string | Yes | Employee reference (email / employeeNumber / id) |
{
"name": "Loom",
"description": "Internal HR API",
"ownerId": "luyu@langgenius.ai"
}
Response: 201 Created
Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
name | string | Project name |
description | string | Project description |
ownerId | string | Employee reference (email / employeeNumber / id) |
isActive | boolean | Set to false to deactivate the project |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
employeeId | string | Yes | Employee reference (email / employeeNumber / id) |
role | string | No | Role within the project (e.g. Backend Dev) |
{ "employeeId": "minco@langgenius.ai", "role": "Backend Dev" }
Response: 201 Created
Path Parameters
| Parameter | Description |
|---|---|
:employeeId | Employee reference (email / employeeNumber / id) |
Response: 204 No Content
Legal Entities
Query Parameters
| Parameter | Type | Description |
|---|---|---|
countryCode | string | Filter by country (CN / US / JP) |
isActive | boolean | Filter by status |
Response
{
"data": {
"id": "entity_cn",
"name": "LangGenius CN Co., Ltd.",
"localName": "Hangzhou LangGenius Technology Co., Ltd.",
"shortName": "LG-CN",
"countryCode": "CN", "currency": "CNY",
"taxId": "913301...", "isActive": true,
"offices": [
{ "id": "...", "name": "Shanghai", "city": "Shanghai", "countryCode": "CN" }
],
"activeEmployees": [
{ "id": "...", "employeeNumber": "LG-0003", "displayName": "Minco Wang" }
]
}
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Full legal entity name |
localName | string | No | Local language name |
shortName | string | Yes | Short name (e.g. LG-CN) |
legalRegisteredName | string | No | Registered business name |
countryCode | string | Yes | ISO country code (CN / US / JP) |
currency | string | Yes | ISO currency code (CNY / USD) |
taxId | string | No | Tax ID / Unified Social Credit Code |
{
"name": "LangGenius CN Co., Ltd.",
"shortName": "LG-CN",
"countryCode": "CN", "currency": "CNY",
"taxId": "913301..."
}
Response: 201 Created
Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
name | string | Full legal entity name |
localName | string | Local language name |
shortName | string | Short name |
legalRegisteredName | string | Registered business name |
countryCode | string | ISO country code |
currency | string | ISO currency code |
taxId | string | Tax ID |
isActive | boolean | Set to false to deactivate the entity |
Offices
Query Parameters
| Parameter | Type | Description |
|---|---|---|
countryCode | string | Filter by country |
legalEntityId | string | Filter by owning entity |
isActive | boolean | Filter by status |
Response
{
"data": {
"id": "office_shanghai",
"name": "Shanghai", "localName": "Shanghai Office",
"countryCode": "CN", "city": "Shanghai",
"address": "Pudong", "timezone": "Asia/Shanghai",
"isActive": true,
"legalEntity": { "id": "...", "shortName": "LG-CN" },
"activeEmployees": [
{ "id": "...", "employeeNumber": "LG-0003", "displayName": "Minco Wang" }
]
}
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Office name |
localName | string | No | Local language name |
countryCode | string | Yes | ISO country code |
city | string | Yes | City |
address | string | No | Full address |
timezone | string | Yes | IANA timezone (e.g. Asia/Shanghai) |
legalEntityId | string | Yes | Owning legal entity ID |
{
"name": "Shanghai Office", "countryCode": "CN",
"city": "Shanghai", "timezone": "Asia/Shanghai",
"legalEntityId": "..."
}Request Body (all fields optional)
| Field | Type | Description |
|---|---|---|
name | string | Office name |
localName | string | Local language name |
countryCode | string | ISO country code |
city | string | City |
address | string | Full address |
timezone | string | IANA timezone |
legalEntityId | string | Owning legal entity ID |
isActive | boolean | Set to false to deactivate the office |
Badges
Response
{
"data": [{
"id": "badge_01",
"name": "Founding Member",
"description": "Joined before Series A",
"asciiArt": "...",
"colors": ["#FFC330", "#FFB118", "#EB8900", "#FFC634", "#FF9600"],
"createdAt": "2026-04-01T08:00:00Z",
"awardedCount": 12
}]
}
Request Body
{
"name": "Founding Member",
"description": "Joined before Series A",
"designId": 22 // from GET /badges/designs
}:id accepts template id or name. Templates that have been awarded cannot be deleted (409).
Returns 4 random preset designs each time, including asciiArt, colors, and hint.
Response
{
"data": [{
"id": "award_01",
"awardedAt": "2026-04-06T10:00:00Z",
"citation": "Day-one builder",
"badge": {
"id": "badge_01", "name": "Founding Member",
"description": "Joined before Series A",
"asciiArt": "...",
"colors": ["#FFC330", "..."]
},
"awardedBy": {
"id": "...", "employeeNumber": "LG-0001",
"displayName": "Luyu Zhang",
"email": "luyu@langgenius.ai"
}
}]
}
Request Body
{
"badge": "Founding Member", // or badgeId
"citation": "Day-one builder"
}Request Body
{
"badge": "Mesh Launch",
"projectId": "proj_loom",
"citation": "Launch team"
}Automatically skips employees who already have the same badge; returns awardedCount and skippedCount.
:badgeId accepts template id or name. Response: 204 No Content
Google Sync
Query: ?dryRun=true returns a preview without writing changes.
Response
{
"data": {
"synced": 86, "created": 2, "updated": 84,
"departments": 12, "errors": []
}
}Returns the last sync time, result statistics, and the number of unresolved warnings.
Returns a list of SUSPENDED / DELETED events.
Request Body
{ "action": "offboard" } // offboard | dismissImport & Audit
Matches existing employees by email (does not create new employees). Empty fields do not overwrite existing values.
Request Body
{
"dryRun": true,
"rows": [{
"email": "minco@langgenius.ai",
"legalName": "Haiming Wang", "displayName": "Minco Wang",
"employmentType": "FULL_TIME", "hireDate": "2023-06-15",
"primaryOffice": "Shanghai",
"phone": "13800138000", "phoneCountryCode": "+86"
}]
}Query: ?level=required|recommended|all, ?department=..., ?employee=...
Returns a summary (totalActiveEmployees, fullyComplete, requiredAction, recommendedAction) and a per-employee issues list.
Query: ?department=..., ?employee=...
Checks for manager-department conflicts, missing primary departments, orphaned employees, etc.
Admin
Request Body
{
"name": "ticket-system",
"role": "viewer",
"expiresAt": "2027-04-01T00:00:00.000Z"
}Includes both system-level and personal Keys, with owner information.
Response: 204 No Content
Request Body
{ "role": "editor" } // viewer | editor | adminResponse
{
"data": {
"employeeId": "...",
"email": "minco@langgenius.ai",
"role": "editor"
}
}