# Aggregate activities Source: https://docs.modernloop.io/api-reference/activity/aggregate-activities /openapi.json post /v1/activities/aggregate Returns COUNT(*) buckets for externally visible activities over a required UTC window of at most 92 days. Values follow group_by order, followed by TIME_BUCKET when requested. Empty time buckets are not zero-filled; CARDINALITY and other measures are future extensions. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List activities Source: https://docs.modernloop.io/api-reference/activity/list-activities /openapi.json get /v1/activities Returns paginated scheduling activity log entries for the authenticated organization. Each entry is a flat object with a subject_type discriminant (TASK, APPLICATION, or CANDIDATE) and sparse, top-level relationship refs (task, application, candidate, job, job_stage) that are populated when the underlying rows hydrate and null otherwise. Requires a timestamp range and optionally filters by activity type. Results are ordered by activity timestamp; use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List activity types Source: https://docs.modernloop.io/api-reference/activity/list-activity-types /openapi.json get /v1/activity-types Lists the valid activity action types and their descriptions. The type enum is open and grows over time; clients must tolerate unknown values. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get an application Source: https://docs.modernloop.io/api-reference/application/get-an-application /openapi.json get /v1/applications/{applicationId} Returns the application summary with its candidate, job, current stage, status, and hiring-team assignments. The application must belong to the authenticated organization or the request returns not found. Inaccessible applications return PERMISSION_DENIED. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List applications Source: https://docs.modernloop.io/api-reference/application/list-applications /openapi.json get /v1/applications Returns paginated application summaries with the candidate, job, current stage, and hiring-team assignments. Combine IDs, candidate IDs, job IDs, statuses, ATS IDs, and record timestamps to narrow results; every supplied filter is applied together. Results are newest first, ordered by created_at descending. Use the cursor to continue the same filtered result set. Jobs the caller cannot access are omitted. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update an application Source: https://docs.modernloop.io/api-reference/application/update-an-application /openapi.json patch /v1/applications/{applicationId} Updates the supplied hiring-team assignments. Omitted fields are preserved; nullable team IDs clear their assignment. The response is re-read after the update and contains the application summary. Inaccessible applications return PERMISSION_DENIED. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List API audit logs Source: https://docs.modernloop.io/api-reference/audit-log/list-api-audit-logs /openapi.json get /v1/audit-logs/api-requests Returns paginated REST API request audit log entries for the authenticated organization, including method, path, status code, and captured request and response payloads. Requires the audit_logs:read scope and an acting user with the owner-only READ_AUDIT_LOGS permission; other callers receive PERMISSION_DENIED. Results are newest first. Requires a timestamp window of at most 366 days; use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List MCP audit logs Source: https://docs.modernloop.io/api-reference/audit-log/list-mcp-audit-logs /openapi.json get /v1/audit-logs/mcp-tool-calls Returns paginated MCP tool-call audit log entries for the authenticated organization, including tool name, caller intent, status, and captured tool input and output payloads. Requires the audit_logs:read scope and an acting user with the owner-only READ_AUDIT_LOGS permission; other callers receive PERMISSION_DENIED. Results are newest first. Requires a timestamp window of at most 366 days; use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List privacy audit logs Source: https://docs.modernloop.io/api-reference/audit-log/list-privacy-audit-logs /openapi.json get /v1/audit-logs/privacy Returns paginated privacy audit ledger entries for the authenticated organization: who accessed whose personal data, when, from which IP addresses, and through which product area. Reads of this ledger are themselves recorded in the API and MCP audit ledgers. Requires the audit_logs:read scope and an acting user with the owner-only READ_AUDIT_LOGS permission; other callers receive PERMISSION_DENIED. Results are newest first. Requires a timestamp window of at most 366 days; use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a candidate Source: https://docs.modernloop.io/api-reference/candidate/get-a-candidate /openapi.json get /v1/candidates/{candidateId} Returns the candidate's identity, contact details, hiring-team assignments, ATS metadata, and anonymization state. For anonymized candidates, PII fields may be redacted; an unknown or out-of-organization ID returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List candidates Source: https://docs.modernloop.io/api-reference/candidate/list-candidates /openapi.json get /v1/candidates Returns paginated candidate summaries with contact details, hiring-team assignments, ATS metadata, and anonymization state. Combine IDs, email, name, ATS, and record-timestamp filters to narrow results; every supplied filter is applied together. Results are newest first, ordered by created_at descending. Anonymized candidates return redacted PII, and the returned cursor continues the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update a candidate Source: https://docs.modernloop.io/api-reference/candidate/update-a-candidate /openapi.json patch /v1/candidates/{candidateId} Updates the supplied hiring-team assignments and candidate profile fields. Omitted fields are preserved; nullable team IDs clear their assignment. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get an interview event Source: https://docs.modernloop.io/api-reference/interview-event/get-an-interview-event /openapi.json get /v1/interview-events/{interviewEventId} Returns one scheduled interview event with its people, application, job, timing, and status details. The event must belong to the authenticated organization or the request returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List interview events Source: https://docs.modernloop.io/api-reference/interview-event/list-interview-events /openapi.json get /v1/interview-events Flat scheduled interview-event rows for BI exports and person/candidate/date filtering. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Add a member to an interview module Source: https://docs.modernloop.io/api-reference/interview-module/add-a-member-to-an-interview-module /openapi.json post /v1/interview-modules/{moduleId}/members Adds one employee as a member of an interview module with optional initial training status and per-member requirements. When supplied, the member weekly-limit override uses null to mean unlimited. The response returns the new membership and calculated training progress. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Create an interview module Source: https://docs.modernloop.io/api-reference/interview-module/create-an-interview-module /openapi.json post /v1/interview-modules Creates an interview module with its shadow and reverse-shadow requirements, graduation rules, and weekly interview limit. The create body supplies the complete training configuration; null weekly_interview_limit means unlimited. The response includes the new module and its initial member counts. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get an interview module Source: https://docs.modernloop.io/api-reference/interview-module/get-an-interview-module /openapi.json get /v1/interview-modules/{moduleId} Returns an interview module's training requirements, graduation configuration, weekly limit, and member counts. The module must belong to the authenticated organization or the request returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get an interview module member Source: https://docs.modernloop.io/api-reference/interview-module/get-an-interview-module-member /openapi.json get /v1/interview-modules/{moduleId}/members/{memberId} Returns one employee's membership in the module, including current training status, pause state, limits, and calculated training progress. The module and member must be in the authenticated organization or the request returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get interview module member stats Source: https://docs.modernloop.io/api-reference/interview-module/get-interview-module-member-stats /openapi.json get /v1/interview-modules/{moduleId}/members/{memberId}/stats Returns detailed training counts, remaining requirements, current session state, and pause state for one interview module member. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get interview module statistics Source: https://docs.modernloop.io/api-reference/interview-module/get-interview-module-statistics /openapi.json get /v1/interview-modules/{moduleId}/stats Returns member training counts for one interview module. Modules outside the authenticated organization are reported as not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List interview module members Source: https://docs.modernloop.io/api-reference/interview-module/list-interview-module-members /openapi.json get /v1/interview-modules/{moduleId}/members Returns paginated module memberships with each employee's current training status, pause state, limits, and training progress. Filter by member IDs or training statuses; every supplied filter is applied together. Use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List interview modules Source: https://docs.modernloop.io/api-reference/interview-module/list-interview-modules /openapi.json get /v1/interview-modules Returns paginated interview modules with training requirements, weekly limits, and member counts. Combine IDs, an exact case-insensitive name, and record timestamps to narrow results; every supplied filter is applied together. Use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Permanently delete an interview module Source: https://docs.modernloop.io/api-reference/interview-module/permanently-delete-an-interview-module /openapi.json delete /v1/interview-modules/{moduleId} Permanently deletes the interview module and all member training history in it. This action cannot be undone. Unknown and cross-organization module IDs return not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Remove a member from an interview module Source: https://docs.modernloop.io/api-reference/interview-module/remove-a-member-from-an-interview-module /openapi.json delete /v1/interview-modules/{moduleId}/members/{memberId} Removes a member from an interview module and deletes that member's training progress in the module. This does not delete the employee or the module itself. An unknown module or member returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update an interview module Source: https://docs.modernloop.io/api-reference/interview-module/update-an-interview-module /openapi.json patch /v1/interview-modules/{moduleId} Updates the supplied interview-module configuration, including training requirements, graduation rules, weekly limit, and fast-track setting. Omitted fields are preserved, while supplied approver lists replace the complete list for that graduation step. Null weekly_interview_limit means unlimited. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update an interview module member Source: https://docs.modernloop.io/api-reference/interview-module/update-an-interview-module-member /openapi.json patch /v1/interview-modules/{moduleId}/members/{memberId} Partially updates a member's training requirements, status, pause state, timestamps, and weekly limit. Changes to required counts can advance training through the module's configured approval rules; setting training_status to TRAINED marks the member trained directly. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a job stage Source: https://docs.modernloop.io/api-reference/job-stage/get-a-job-stage /openapi.json get /v1/job-stages/{jobStageId} Returns a job stage with its job reference and resolved settings. An unknown or out-of-organization stage ID returns not found. The request returns PERMISSION_DENIED when the caller cannot access the job. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List job stages Source: https://docs.modernloop.io/api-reference/job-stage/list-job-stages /openapi.json get /v1/job-stages Returns job-stage summaries and resolved settings for the requested stage IDs or a single job. At least one of ids or job_id is required; when both are supplied, only stages that satisfy both are returned. This operation returns a single unpaginated result page. Jobs the caller cannot access are omitted. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update a job stage Source: https://docs.modernloop.io/api-reference/job-stage/update-a-job-stage /openapi.json patch /v1/job-stages/{jobStageId} Updates a job stage's settings. Targets the stage settings only; the base stage (name, index, ATS identity, schedulable) is ATS-sync-owned and read-only. Every supplied settings group merges per field, including `self_schedule_defaults` and `availability_request_defaults`; omitted fields are preserved. At least one group is required, each supplied group must contain at least one field, and unknown fields are rejected rather than ignored. Set `automation.create_automated_task_on_behalf_of` to `null` to clear it. The Java handler does not support clearing `automation.default_task`; omit it to preserve the current value. Requires a token with the `jobs:write` scope. The request returns PERMISSION_DENIED when the caller cannot access the job. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a job Source: https://docs.modernloop.io/api-reference/job/get-a-job /openapi.json get /v1/jobs/{jobId} Returns one job with its resolved scheduling settings and job-stage information. The job must belong to the authenticated organization or the request returns not found. The request returns PERMISSION_DENIED when the caller cannot access the job. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List jobs Source: https://docs.modernloop.io/api-reference/job/list-jobs /openapi.json get /v1/jobs Returns paginated job summaries with status and ATS information. Combine IDs, status, name, ATS ID, and record timestamps to narrow results; every supplied filter is applied together. Use the cursor to continue the same filtered result set. Jobs the caller cannot access are omitted. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update a job Source: https://docs.modernloop.io/api-reference/job/update-a-job /openapi.json patch /v1/jobs/{jobId} Updates the supplied fallback name or internal note for a job. Omitted fields are preserved, and both fields are write-only because the current job summary RPC does not return them. An empty PATCH body is rejected. The request returns PERMISSION_DENIED when the caller cannot access the job. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get current identity Source: https://docs.modernloop.io/api-reference/me/get-current-identity /openapi.json get /v1/me Returns the acting user, organization, granted scopes, and registry-level MCP tool access for the authenticated token. tool_access predicts whether each public tool can succeed with the granted scopes; endpoint variant and connection-level tool filtering can further restrict visibility. A tool can still appear in tools/list yet return INSUFFICIENT_SCOPE, so use tool_access to plan calls and tools/list for this connection's visibility. Available to every valid token; no scope is required. No parameters are accepted because identity is determined entirely from authentication. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get organization Source: https://docs.modernloop.io/api-reference/organization/get-organization /openapi.json get /v1/organization Returns the organization associated with the authenticated token, including its scheduling defaults. No organization ID is accepted because the caller's organization is determined from authentication. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update organization Source: https://docs.modernloop.io/api-reference/organization/update-organization /openapi.json patch /v1/organization Partially updates the authenticated organization's scheduling defaults. Work hours and daily or weekly load-limit options replace atomically; scalar groups merge per field. Omitted settings are preserved and the response returns the updated organization representation. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a schedule Source: https://docs.modernloop.io/api-reference/schedule/get-a-schedule /openapi.json get /v1/schedules/{scheduleId} Returns a schedule group and the interview events it contains, including their timing and participants. The schedule must belong to the authenticated organization or the request returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List schedules Source: https://docs.modernloop.io/api-reference/schedule/list-schedules /openapi.json get /v1/schedules Returns paginated schedule groups, each with its nested interview events. Record timestamp filters narrow the schedule records and are combined with IDs when supplied. Use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Cancel a scheduling task Source: https://docs.modernloop.io/api-reference/scheduling-task/cancel-a-scheduling-task /openapi.json delete /v1/tasks/{taskId} Cancels a scheduling task, optionally recording a cancellation reason. Cancellation is rejected when the underlying scheduler reports a conflict. The returned task shows the resulting scheduling state. Inaccessible jobs return PERMISSION_DENIED. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Create a scheduling task Source: https://docs.modernloop.io/api-reference/scheduling-task/create-a-scheduling-task /openapi.json post /v1/tasks Creates a scheduling task for the supplied application and job stage. The task starts with the requested urgency and optional initial note; the server assigns the scheduling-task type. An idempotency key is required so retries return the original result instead of creating another task. Inaccessible jobs return PERMISSION_DENIED. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a scheduling task Source: https://docs.modernloop.io/api-reference/scheduling-task/get-a-scheduling-task /openapi.json get /v1/tasks/{taskId} Returns one scheduling task with its application, stage, assignee, queue, tags, flags, delegation, notes, and timing metadata. The task must belong to the authenticated organization or the request returns not found. Inaccessible jobs return PERMISSION_DENIED. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List scheduling tasks Source: https://docs.modernloop.io/api-reference/scheduling-task/list-scheduling-tasks /openapi.json get /v1/tasks Lists scheduling tasks with status, flag, urgent, queue, tag, delegation, assignee, job, application, and my_tasks filters. Results are newest first, ordered by created_at descending. Inaccessible jobs are omitted. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update a scheduling task Source: https://docs.modernloop.io/api-reference/scheduling-task/update-a-scheduling-task /openapi.json patch /v1/tasks/{taskId} Updates the supplied assignee, urgency, queue, tags, debrief requirement, or meeting location for a scheduling task. Omitted fields are preserved; null clears the assignee, queue, or meeting location, while supplying tags replaces the task's tag list. An empty PATCH body is rejected. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a task queue Source: https://docs.modernloop.io/api-reference/task-queue/get-a-task-queue /openapi.json get /v1/task-queues/{taskQueueId} Returns the name and timestamps for one active scheduling-task queue. Unknown, deleted, or out-of-organization queues return not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List task queues Source: https://docs.modernloop.io/api-reference/task-queue/list-task-queues /openapi.json get /v1/task-queues Returns paginated active scheduling-task queues. IDs and a name filter can be combined to narrow results, and deleted queues are excluded. Use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a template Source: https://docs.modernloop.io/api-reference/template/get-a-template /openapi.json get /v1/templates/{templateId} Returns one organization email or calendar template, including its type, subject, HTML body, and send metadata. Bodies contain unexpanded {{TOKEN}} placeholders. The template must belong to the authenticated organization or the request returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List templates Source: https://docs.modernloop.io/api-reference/template/list-templates /openapi.json get /v1/templates Returns paginated organization email and calendar templates with their subject, HTML body, and send metadata. Bodies contain unexpanded {{TOKEN}} placeholders. Combine IDs, template types, an exact case-insensitive name, and record timestamps to narrow results; every supplied filter is applied together. Use the cursor to continue the same filtered result set. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Get a user Source: https://docs.modernloop.io/api-reference/user/get-a-user /openapi.json get /v1/users/{userId} Returns a user profile with load limits, pause state, work hours, attributes, and interview-module memberships. The user must belong to the authenticated organization or the request returns not found. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # List users Source: https://docs.modernloop.io/api-reference/user/list-users /openapi.json get /v1/users Lists users with interviewer load, pause state, work hours, and module training. Omit statuses for the default active-only view; pass statuses=ACTIVE,ARCHIVED to include both active and archived users. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Update a user Source: https://docs.modernloop.io/api-reference/user/update-a-user /openapi.json patch /v1/users/{userId} Updates the admin-managed user profile, scheduling controls, load-limit overrides, and organization attributes. Example: `{"title":"Principal Engineer","timezone":"America/Chicago","daily_load_limit":{"limit":4,"type":"NUMBER_OF_INTERVIEWS"}}`. Set nullable overrides to `null` to clear them. Email and ATS identity are read-only. Requires a token with the `users:write` scope. Changes are attributed to the acting user in API and backend audit telemetry; this administrative update does not create a scheduling activity-timeline entry. Directory- or SCIM-managed profile fields (name, title, manager, LinkedIn URL) are rejected with `CANNOT_UPDATE_SYNC_MANAGED_FIELDS` when the organization pref assigns them to an external sync source. **Beta**: this endpoint may change or be removed without notice while in beta. There is no compatibility promise until it reaches general availability. # Errors Source: https://docs.modernloop.io/errors The standard error envelope and error codes returned by the ModernLoop Platform API and MCP server. Every REST endpoint and MCP tool reports failures with the same JSON envelope: ```json theme={"dark"} { "error": { "code": "CANNOT_UPDATE_SYNC_MANAGED_FIELDS", "message": "These fields are managed by an external sync source (directory/SCIM) and cannot be updated via the API: title (SCIM).", "docs_url": "https://docs.modernloop.io/errors", "details": [{ "field": "title", "source": "SCIM" }] } } ``` * `code` — a stable machine-readable error code from the table below. Branch on this, never on `message`. * `message` — a human-readable explanation. Wording may change without notice. * `docs_url` — optional link to relevant documentation. * `details` — optional list of machine-readable entries carrying structured context, such as the specific fields a write was rejected for. Codes that populate `details` document the entry shape below. ## Error codes | Code | Meaning | How to recover | | - | - | - | | `UNAUTHENTICATED` | Authentication was missing or invalid. | Reconnect and complete OAuth. | | `INSUFFICIENT_SCOPE` | The token lacks permission for this operation. | Reconnect with the required scope or use a permitted operation. | | `VALIDATION_FAILED` | Input did not match the request schema. | Correct the listed fields and retry. | | `INVALID_CURSOR` | The cursor does not belong to these filters. | Restart the list request and reuse the cursor only with unchanged filters. | | `PAYLOAD_TOO_LARGE` | The request body exceeds the size limit. | Reduce the request payload. | | `NOT_FOUND` | The resource is absent or outside this organization. | Discover a valid ID first. | | `IDEMPOTENCY_KEY_REQUIRED` | The create request needs an idempotency key. | Generate a fresh key for this logical create. | | `IDEMPOTENCY_KEY_REUSED` | The idempotency key was used with a different payload. | Use a fresh key for the changed request. | | `RATE_LIMITED` | Too many requests were made. | Wait and retry with backoff. | | `CONFLICT` | The requested state transition conflicts with current data. | Read the object and resolve the conflict before retrying. | | `CANNOT_UPDATE_SYNC_MANAGED_FIELDS` | A profile field is managed by directory or SCIM sync and cannot be updated via the API. | Drop the fields listed in `details`, or change the field's sync source in ModernLoop settings and update the value in the source system. | | `NOT_IMPLEMENTED` | This operation is not available. | Use a supported operation. | | `INTERNAL` | ModernLoop encountered an unexpected error. | Retry later or contact support. | | `UPSTREAM_TIMEOUT` | An upstream ModernLoop dependency timed out. | Retry the idempotent operation later. | ## `CANNOT_UPDATE_SYNC_MANAGED_FIELDS` details Returned with HTTP 409 by `PATCH /v1/users/{userId}` (and the `update_user` MCP tool) when the request writes profile fields whose source of truth the organization has delegated to an external sync source. All rejected fields are reported in one response so a single retry can fix the request. Each `details` entry has: * `field` — the rejected request field: `name`, `title`, `manager`, or `linkedin_url`. * `source` — the configured source of truth: `DIRECTORY` or `SCIM`. A field is rejected even when the submitted value equals the stored value, so read-modify-write clients should omit sync-managed fields rather than echo them back. # ModernLoop Platform API Source: https://docs.modernloop.io/index Programmatic access to ModernLoop scheduling data and actions through REST and MCP. ModernLoop exposes a Platform API for integrations, automation, and AI agents. Use the REST API for direct HTTP calls, or connect an MCP client for tool-based agent workflows. Most REST endpoints are currently in **beta** and may change without notice. See individual endpoint pages in the **API Reference** tab for stability tags. ## Base URL All requests use `https://api.modernloop.io`. | Surface | Path | | - | - | | REST resources | `/v1/...` | | OpenAPI document | `/openapi.json` | | MCP (read and write) | `/mcp` | | MCP (read-only) | `/mcp/readonly` | ## REST API The REST API lets you list, read, and update recruiting and scheduling data in your ModernLoop organization. ### Authentication Send a ModernLoop API token as a Bearer token: ```http theme={"dark"} Authorization: Bearer ``` Tokens are scoped to your organization and act on behalf of the user who created them. Grant only the read and write scopes your integration needs. ### Resources The API covers these areas. See the **API Reference** tab for request and response schemas. | Area | What you can do | | - | - | | Applications | List and update applications | | Candidates | List and update candidates | | Interview events | List and read interview events | | Interview modules | Manage modules and module membership | | Interviewers | List and update interviewer settings | | Jobs & job stages | List, read, and update jobs; read and update job stages | | Organization | Read and update organization scheduling defaults | | Schedules | List and read schedules | | Scheduling tasks | Create, update, and cancel scheduling tasks | | Task queues | List task queues | | Templates | List and read email templates | ### Conventions * Resource IDs use typed prefixes such as `can_` (candidate), `app_` (application), `job_` (job), and `usr_` (user). * Field names use `lower_snake_case`. * Timestamps are ISO 8601 in UTC. * List endpoints use cursor-based pagination. Pass the `cursor` query parameter from `pagination.next_cursor` to continue the same filtered result set. ### Errors Failed requests return a JSON envelope with an `error` object containing a machine-readable `error.code`, a human-readable `error.message`, and an optional `error.docs_url`. ## MCP server ModernLoop also provides a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server over Streamable HTTP. MCP exposes scheduling operations as tools that AI clients such as Claude Code, Codex, and Cursor can call directly. | Endpoint | Use when | | - | - | | `https://api.modernloop.io/mcp/readonly` | The agent only needs to look up data | | `https://api.modernloop.io/mcp` | The agent may create, update, or delete data | MCP connections use OAuth 2.1 with PKCE, or a static API token in the `Authorization` header. The read-only and read-write endpoints use separate OAuth resources. See [ModernLoop MCP](/mcp/setup) for client setup, [toolsets](/mcp/toolsets) for endpoint selection, and [tools](/mcp/tools) for the full tool reference. ## Support Questions about the Platform API? Contact [support@modernloop.io](mailto:support@modernloop.io). # MCP Data Model Source: https://docs.modernloop.io/mcp/data-model Understand ModernLoop scheduling objects, canonical IDs, discovery flows, and pagination. Use this page to navigate the objects returned by ModernLoop MCP tools. Start a new session with `get_me`: it identifies the acting user, organization, and scopes available to the connection. ## Object graph An organization contains jobs, users, interview modules, templates, task queues, schedules, and their related records. ```text theme={"dark"} Organization ├── Jobs ──┬── Job stages │ └── Applications ── Candidate │ └── Scheduling tasks ── Task queue │ └── Assignee (user) ├── Schedules ── Interview events ── Application / Candidate / Users ├── Users ── Interview-module memberships ── Interview modules └── Email and calendar templates ``` * An **application** connects a candidate to a job and has a current job stage. * A **scheduling task** is created for an application and a job stage. It can be assigned to a user and placed in a task queue. * A **schedule** is a group of interview events. Events identify their participants and connect back to the relevant application and candidate. * An **interview module** defines training requirements. Its memberships connect users to that module and record their training progress. * **Templates** are searchable reference records. No current MCP write or scheduling tool consumes a template directly. ## Canonical ID prefixes Canonical external IDs are a prefix, an underscore, and a 32-character hexadecimal UUID body. For example, `can_a1b2c3d4e5f64789a1b2c3d4e5f64789` is a candidate ID. | Object | Prefix | Example | | - | - | - | | Candidate | `can_` | `can_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Application | `app_` | `app_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Job | `job_` | `job_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Job stage | `stg_` | `stg_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Scheduling task | `tsk_` | `tsk_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Task queue | `que_` | `que_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | User | `usr_` | `usr_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Interview module | `mod_` | `mod_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Interview event | `int_` | `int_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Schedule | `sch_` | `sch_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Template | `tpl_` | `tpl_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Organization | `org_` | `org_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | User attribute | `att_` | `att_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | User attribute value | `atv_` | `atv_a1b2c3d4e5f64789a1b2c3d4e5f64789` | | Help article | `hlp_` | `hlp_a1b2c3d4e5f64789a1b2c3d4e5f64789` | The API also accepts UUID forms where the tool schema permits them, but use canonical prefixed IDs in conversation and stored references so the object type is clear. ## Recommended discovery sequences Use list tools to discover an ID, then use the matching get tool before a consequential update. | Goal | Recommended sequence | | - | - | | Orient a new connection | `get_me` → `get_organization` when `organization:read` is available | | Inspect a candidate's progress | `list_candidates` → `get_candidate` → `list_applications` → `get_application` | | Create a scheduling task | `list_candidates` → `list_applications` → `get_application` → `list_job_stages` (with `job_id` or `ids`) → `get_job_stage` → user confirmation → `create_scheduling_task` | | Triage your assigned tasks | `get_me` → `list_scheduling_tasks` with `my_tasks: true` → `get_scheduling_task` for detail | | Investigate scheduling | `list_applications` → `list_scheduling_tasks` → `get_scheduling_task` → `list_schedules` or `list_interview_events` | | Select an assignee | `list_users` → `get_user` → `update_scheduling_task` after confirmation | | Inspect interview training | `list_interview_modules` → `get_interview_module` → `list_interview_module_members` → member stats | | Find a queue's work | `list_task_queues` → `get_task_queue` → `list_scheduling_tasks` filtered to that queue | | Answer a how-to or troubleshooting question | `list_help_articles` with a focused query → `get_help_article` for the best match | Read the current record before an update. For destructive operations, explicitly confirm the target and impact with the user first. ## Pagination and filters List tools return a cursor when more results are available. To fetch the next page, pass `pagination.next_cursor` back unchanged and retain the exact same filters and sort context used on the first request. Do not reuse a cursor with a different name, status, date, ID, or other filter; start a new list request instead. List-tool filters are conjunctive when more than one is supplied: each result must satisfy every provided filter. Start with a narrow, stable query when you expect to paginate. Omit a filter parameter to skip that filter. Providing an empty array filter (for example `assignee_ids=` or `ids: []`) returns `VALIDATION_FAILED`; supply at least one value or omit the parameter entirely. `list_job_stages` requires at least one of `ids` or `job_id`. `list_scheduling_tasks` accepts `my_tasks: true` as shorthand for tasks assigned to the acting user; it cannot be combined with `assignee_ids`. When a related object is missing or inaccessible, nested relation fields are returned as `null` rather than placeholder records (for example task application, candidate, job, job stage, or note author; schedule application; user `attribute_name` or `module`). ## Naming conventions in tool inputs Get tools commonly take a camelCase path-style ID such as `candidateId`, `jobStageId`, or `taskQueueId`. List and write payloads can use snake\_case fields. Use the input schema returned by `tools/list` for the exact field names and required values for your client. ## Further reading * [MCP Tools](/mcp/tools) — complete tool and scope reference * [ModernLoop MCP](/mcp/setup) — endpoint and OAuth troubleshooting # ModernLoop MCP Source: https://docs.modernloop.io/mcp/setup Connect your AI agent to the ModernLoop MCP Server. The ModernLoop MCP Server exposes scheduling data and actions as tools your AI agent can call. Select your client below to connect. ModernLoop does not yet offer official marketplace or directory integrations. Use the custom connector steps for every client. Connect ChatGPT to ModernLoop with a custom MCP connector. 1. Open **ChatGPT** → **Settings** → **Connectors** (or **Apps & Connectors**). 2. Choose **Add connector** or **Create custom connector**. 3. Enter a name such as `ModernLoop`. 4. Set the server URL to one of the endpoints below. 5. Save the connector and complete the ModernLoop OAuth sign-in when prompted. ```text Read and write theme={"dark"} https://api.modernloop.io/mcp ``` ```text Read-only theme={"dark"} https://api.modernloop.io/mcp/readonly ``` Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Connect Claude on the web or desktop with a custom MCP connector. 1. Open **Claude** → **Settings** → **Connectors** (or **Integrations**). 2. Choose **Add custom connector** or **Add MCP server**. 3. Enter a name such as `ModernLoop`. 4. Set the server URL to one of the endpoints below. 5. Save and complete the ModernLoop OAuth sign-in when prompted. ```text Read and write theme={"dark"} https://api.modernloop.io/mcp ``` ```text Read-only theme={"dark"} https://api.modernloop.io/mcp/readonly ``` Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Add the ModernLoop MCP server from a terminal, then complete OAuth sign-in in Claude Code. ```bash Read and write theme={"dark"} claude mcp add --transport http modernloop \ https://api.modernloop.io/mcp ``` ```bash Read-only theme={"dark"} claude mcp add --transport http modernloop-readonly \ https://api.modernloop.io/mcp/readonly ``` Use `--scope user` to make the connection available in every project, or `--scope project` to share its configuration with one project. Do not commit credentials. Alternatively, add the server to your Claude Code MCP configuration file: ```json Read and write ~/.claude.json theme={"dark"} { "mcpServers": { "modernloop": { "type": "http", "url": "https://api.modernloop.io/mcp" } } } ``` ```json Read-only ~/.claude.json theme={"dark"} { "mcpServers": { "modernloop-readonly": { "type": "http", "url": "https://api.modernloop.io/mcp/readonly" } } } ``` Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Add the ModernLoop MCP server, then start its OAuth sign-in flow. ```bash Read and write theme={"dark"} codex mcp add modernloop \ --url https://api.modernloop.io/mcp codex mcp login modernloop ``` ```bash Read-only theme={"dark"} codex mcp add modernloop-readonly \ --url https://api.modernloop.io/mcp/readonly codex mcp login modernloop-readonly ``` Alternatively, add the server to `~/.codex/config.toml`: ```toml Read and write theme={"dark"} [mcp_servers.modernloop] url = "https://api.modernloop.io/mcp" ``` ```toml Read-only theme={"dark"} [mcp_servers.modernloop-readonly] url = "https://api.modernloop.io/mcp/readonly" ``` Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Add the ModernLoop MCP server with the Copilot CLI, then complete OAuth sign-in. ```bash Read and write theme={"dark"} copilot mcp add modernloop \ --url https://api.modernloop.io/mcp ``` ```bash Read-only theme={"dark"} copilot mcp add modernloop-readonly \ --url https://api.modernloop.io/mcp/readonly ``` Alternatively, add the server to `~/.copilot/mcp-config.json`: ```json Read and write theme={"dark"} { "mcpServers": { "modernloop": { "type": "http", "url": "https://api.modernloop.io/mcp" } } } ``` ```json Read-only theme={"dark"} { "mcpServers": { "modernloop-readonly": { "type": "http", "url": "https://api.modernloop.io/mcp/readonly" } } } ``` Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Add the ModernLoop MCP server in Cursor settings or your MCP configuration file. **In Cursor:** 1. Open **Settings** → **Tools & MCP** → **New MCP Server**. 2. Choose an HTTP server. 3. Enter one of the endpoint URLs below. 4. Save. Cursor starts the OAuth sign-in flow when it connects. **From the terminal:** ```bash Read and write theme={"dark"} cursor --add-mcp '{"name":"modernloop","url":"https://api.modernloop.io/mcp"}' ``` ```bash Read-only theme={"dark"} cursor --add-mcp '{"name":"modernloop-readonly","url":"https://api.modernloop.io/mcp/readonly"}' ``` **In `~/.cursor/mcp.json` or project `.cursor/mcp.json`:** ```json Read and write theme={"dark"} { "mcpServers": { "modernloop": { "url": "https://api.modernloop.io/mcp" } } } ``` ```json Read-only theme={"dark"} { "mcpServers": { "modernloop-readonly": { "url": "https://api.modernloop.io/mcp/readonly" } } } ``` Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Add the ModernLoop MCP server with the Gemini CLI. ```bash Read and write theme={"dark"} gemini mcp add modernloop \ --url https://api.modernloop.io/mcp ``` ```bash Read-only theme={"dark"} gemini mcp add modernloop-readonly \ --url https://api.modernloop.io/mcp/readonly ``` Alternatively, add the server to `~/.gemini/settings.json`: ```json Read and write theme={"dark"} { "mcpServers": { "modernloop": { "httpUrl": "https://api.modernloop.io/mcp" } } } ``` ```json Read-only theme={"dark"} { "mcpServers": { "modernloop-readonly": { "httpUrl": "https://api.modernloop.io/mcp/readonly" } } } ``` Complete the ModernLoop OAuth sign-in when the client prompts you. Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. Configure a remote Streamable HTTP MCP server with one of the ModernLoop endpoint URLs. ```json Read and write theme={"dark"} { "mcpServers": { "modernloop": { "type": "http", "url": "https://api.modernloop.io/mcp" } } } ``` ```json Read-only theme={"dark"} { "mcpServers": { "modernloop-readonly": { "type": "http", "url": "https://api.modernloop.io/mcp/readonly" } } } ``` Your client must support OAuth authorization-code flow with PKCE and dynamic client registration. It should follow the `WWW-Authenticate` challenge and the protected-resource metadata published by the endpoint. Use the read-only endpoint unless your workflow needs to change ModernLoop data. See [Toolsets](/mcp/toolsets) for details. Verify that your connection can list tools and that the granted scopes match your workflow. ## Toolsets ModernLoop provides two toolsets. Each maps to a separate endpoint and OAuth resource. | Toolset | Endpoint | Tools | | - | - | -: | | Read-only | `https://api.modernloop.io/mcp/readonly` | Read tools only | | Default | `https://api.modernloop.io/mcp` | Read and write tools | A token for one endpoint cannot call the other. See [MCP Toolsets](/mcp/toolsets) for the full comparison. ## Supported clients | Client | Connection method | Notes | | - | - | - | | ChatGPT | Custom connector | OAuth during connector setup | | Claude | Custom connector | OAuth during connector setup | | Claude Code | `claude mcp add` or `~/.claude.json` | OAuth during first use | | Codex | `codex mcp add` or `~/.codex/config.toml` | `codex mcp login` for OAuth | | Copilot CLI | `copilot mcp add` or `~/.copilot/mcp-config.json` | OAuth during first use | | Cursor | Settings, CLI, or `mcp.json` | OAuth during first use | | Gemini CLI | `gemini mcp add` or `~/.gemini/settings.json` | OAuth during first use | | Other HTTP MCP clients | Generic `mcpServers` config | Must support OAuth 2.1 + PKCE + DCR | ## Required permissions Each MCP tool requires an OAuth scope. Grant only the scopes your workflow needs. ### Read scopes | Scope | Grants access to | | - | - | | `applications:read` | Application listing and lookup | | `candidates:read` | Candidate listing and lookup | | `interview_modules:read` | Interview-module and membership reads | | `interviews:read` | Interview event listing and lookup | | `jobs:read` | Job and job-stage listing and lookup | | `organization:read` | Organization settings (read) | | `schedules:read` | Schedule listing and lookup | | `tasks:read` | Scheduling-task and task-queue reads | | `templates:read` | Template listing and lookup | | `users:read` | User listing and lookup | ### Write scopes | Scope | Grants access to | | - | - | | `applications:write` | Application updates | | `candidates:write` | Candidate updates | | `interview_modules:write` | Interview-module and membership writes | | `jobs:write` | Job and job-stage updates | | `organization:write` | Organization settings updates | | `scheduling:write` | Scheduling-task create, update, and cancel | | `users:write` | User updates | The read-only endpoint accepts read scopes only. The default endpoint accepts read and write scopes. Tools for resources your organization cannot access return not found. ## Troubleshooting access ### A tool is missing from `tools/list` `tools/list` is scoped to the current session. A missing write tool usually means the client is connected to `/mcp/readonly`; that endpoint never exposes write tools. A missing read or write tool can also mean the token was not granted its required scope, or the organization does not have the corresponding entitlement. Check the [tool reference](/mcp/tools) for the exact scope and endpoint requirement. ### A tool call returns `NOT_FOUND` If the tool appears in `tools/list` but its call returns `NOT_FOUND`, the ID may be unknown, deleted, outside the authenticated organization, or inaccessible to that organization. Confirm the ID with its list tool and make sure you are using the same organization. Do not infer that a missing tool is callable by guessing its name: reconnect with the required scope or endpoint and check `tools/list` again. ### I need additional scopes Reconnect the MCP server and start a fresh OAuth authorization flow requesting the additional scopes. Depending on your client, remove and re-add the connector or sign out/revoke the existing ModernLoop connection before reconnecting. Then complete consent again and call `get_me` and `tools/list` to verify the granted scopes and available tools. For a static API token, mint or obtain a replacement token with the required scopes. ### My token works on one endpoint but not the other `/mcp` and `/mcp/readonly` are separate OAuth protected resources with distinct audiences. Their tokens are not interchangeable: use an access token issued for the exact endpoint URL your client calls. Re-authorize against the other endpoint rather than reusing the existing token. ## Authentication ### OAuth 2.1 (recommended) OAuth is the recommended authentication method for interactive AI clients. 1. Your client connects to the MCP endpoint URL. 2. The server responds with a `WWW-Authenticate` challenge. 3. Your client fetches protected-resource metadata and discovers the authorization server. 4. Your client registers dynamically (RFC 7591) and starts an authorization-code flow with PKCE. 5. You sign in to ModernLoop and grant the requested scopes. 6. Your client exchanges the authorization code for an access token. The identity that authorizes the connection is used for all tool calls. ### Static API token If your client does not support OAuth, send a ModernLoop API token in the `Authorization` header. ```json theme={"dark"} { "mcpServers": { "modernloop-readonly": { "url": "https://api.modernloop.io/mcp/readonly", "headers": { "Authorization": "Bearer ${MODERNLOOP_API_TOKEN}" } } } } ``` Store the token in your client's secret store or environment. Do not commit tokens to source control. The token must include the scopes required by the tools you call. Match the endpoint to the token's granted scopes. ## Test access to the MCP Server 1. Connect your client using one of the configurations above. 2. Complete OAuth sign-in or configure a valid API token. 3. Call `tools/list` and confirm the expected tools appear. 4. Call a read tool such as `get_organization` to verify authorization. For local development, run the Platform API at `http://localhost:8787` and use `/mcp` or `/mcp/readonly` on that host. See the [Platform API README](https://github.com/modernloop/mloop-backend/tree/main/backend/node) for token minting. ## Further reading * [MCP Toolsets](/mcp/toolsets) — read-only vs default toolset * [MCP Tools](/mcp/tools) — per-tool reference * [MCP Data Model](/mcp/data-model) — relationships, IDs, discovery, and pagination * [ModernLoop Platform API](/) — REST API overview # MCP Tools Source: https://docs.modernloop.io/mcp/tools Reference for every tool exposed by the ModernLoop MCP Server. The ModernLoop MCP Server exposes read and write tools on the default endpoint. Tool availability is specific to your endpoint, OAuth scopes, and organization entitlements. Call `tools/list` after connecting for the authoritative tool list and input schema for your session. Two of the read tools are skill guides rather than data operations: `list_modernloop_skills` and `load_modernloop_skill` document the correct workflow, tool order, safety rules, and pitfalls for a scheduling domain. Load a guide before starting domain work — see [Skill guides](#skill-guides). Use [the data model](/mcp/data-model) to find the right object and canonical ID, and [MCP setup](/mcp/setup) to troubleshoot missing tools or scopes. Call `get_me` first: its `tool_access` field predicts whether each public MCP tool can succeed with the token's scopes. Endpoint variant and connection-level `include_tools`/`exclude_tools` filtering can further restrict visibility, while a listed tool can still return `INSUFFICIENT_SCOPE`; use `tools/list` for the active connection's visible tools. ## Tool reference | Tool | Description | Scope | Read-only toolset | | - | - | - | - | | `list_candidates` | Lookup candidates by id, name, email, ATS details, or creation and update timestamps. | `candidates:read` | Yes | | `list_mcp_audit_logs` | List MCP tool-call audit log entries within a required timestamp window of at most 366 days. Owner-only: the acting user needs the `READ_AUDIT_LOGS` permission. | `audit_logs:read` | Yes | | `list_api_audit_logs` | List REST API request audit log entries within a required timestamp window of at most 366 days. Owner-only: the acting user needs the `READ_AUDIT_LOGS` permission. | `audit_logs:read` | Yes | | `list_privacy_audit_logs` | List privacy audit ledger entries (accesses to personal data) within a required timestamp window of at most 366 days. Owner-only: the acting user needs the `READ_AUDIT_LOGS` permission. | `audit_logs:read` | Yes | | `get_candidate` | Get details for one candidate. | `candidates:read` | Yes | | `update_candidate` | Update a candidate. | `candidates:write` | No | | `list_applications` | List applications by candidate, job, status, ATS id, or timestamps. | `applications:read` | Yes | | `get_application` | Get details for one application. | `applications:read` | Yes | | `update_application` | Update an application. | `applications:write` | No | | `list_jobs` | List jobs by name, status, ATS id, or timestamps. | `jobs:read` | Yes | | `get_job` | Get one job, including its resolved scheduling settings. | `jobs:read` | Yes | | `update_job` | Update a job's fallback name or internal note. | `jobs:write` | No | | `list_job_stages` | List job stages by job id or by ids. Includes stage settings. At least one of ids or job\_id is required; when both are supplied, only stages that satisfy both are returned. | `jobs:read` | Yes | | `get_job_stage` | Get one job stage by id, including its settings. | `jobs:read` | Yes | | `update_job_stage` | Update a job stage's settings: automation, candidate notifications, self-schedule or availability-request defaults. | `jobs:write` | No | | `list_users` | List user load, limits, pause status, and module training. | `users:read` | Yes | | `get_user` | Get details for one user. | `users:read` | Yes | | `update_user` | Update a user's admin-managed profile, scheduling controls, load limits, or organization attributes. | `users:write` | No | | `get_me` | Get the acting user, organization, and granted scopes for the current token. | No scope (any authenticated token) | Yes | | `list_help_articles` | Search the ModernLoop help knowledge base by relevance-ranked query. Returns title, URL, snippet, and score. | No scope (any authenticated token) | Yes | | `get_help_article` | Read one help article as Markdown with its canonical URL. | No scope (any authenticated token) | Yes | | `list_interview_modules` | List interview modules by name, including member-count aggregates and training status. Use list\_interview\_module\_members to retrieve the member list. | `interview_modules:read` | Yes | | `get_interview_module` | Get details for one interview module. | `interview_modules:read` | Yes | | `create_interview_module` | Create an interview module with training requirements and graduation rules. | `interview_modules:write` | No | | `update_interview_module` | Update an interview module's name, training requirements, graduation rules, or weekly limit. | `interview_modules:write` | No | | `delete_interview_module` | Permanently delete one interview module and all of its interviewer memberships. This hard delete is irreversible. | `interview_modules:write` | No | | `create_interview_module_member` | Add one interviewer to an interview module, optionally with training overrides. | `interview_modules:write` | No | | `get_interview_module_stats` | Get member training counts for one interview module. | `interview_modules:read` | Yes | | `list_interview_module_members` | List the interviewers in one interview module with their training progress, optionally filtered by training status. | `interview_modules:read` | Yes | | `get_interview_module_member` | Get details for one interview module member. | `interview_modules:read` | Yes | | `get_interview_module_member_stats` | Get detailed training statistics for one interview module member. | `interview_modules:read` | Yes | | `update_interview_module_member` | Update an interviewer's training membership, pause state, required counts, timestamps, or weekly limit in one interview module. | `interview_modules:write` | No | | `delete_interview_module_member` | Remove one interviewer from an interview module, deleting their membership and training progress in it. | `interview_modules:write` | No | | `get_organization` | Get the caller's organization and its scheduling defaults. | `organization:read` | Yes | | `update_organization` | Update the organization's scheduling defaults: work hours, interviewer load limits, interview buffers, feedback writing time, or conflict keywords. | `organization:write` | No | | `list_interview_events` | List interview events using person, candidate, application, job, status, and date filters. | `interviews:read` | Yes | | `get_interview_event` | Get details for one interview event. | `interviews:read` | Yes | | `list_schedules` | List schedule groups with nested interviews, optionally bounded by timestamps. | `schedules:read` | Yes | | `get_schedule` | Get details for one schedule. | `schedules:read` | Yes | | `list_scheduling_tasks` | List scheduling tasks by status, flagged, urgency, queue IDs, tags, delegation status, assignee, job, or application. By default, results cover all tasks in the organization; use `my_tasks: true` as the my tasks shorthand for tasks assigned to the acting user. | `tasks:read` | Yes | | `get_scheduling_task` | Get details for one scheduling task. | `tasks:read` | Yes | | `create_scheduling_task` | Create a scheduling task for an application and job stage. | `scheduling:write` | No | | `update_scheduling_task` | Update assignee, urgency, queue, tags, debrief requirement, or meeting location. | `scheduling:write` | No | | `cancel_scheduling_task` | Cancel a scheduling task with an optional reason. | `scheduling:write` | No | | `list_task_queues` | List active scheduling task queues, optionally filtered by name. | `tasks:read` | Yes | | `get_task_queue` | Get details for one scheduling task queue. | `tasks:read` | Yes | | `list_templates` | List organization email and calendar templates by name or type. | `templates:read` | Yes | | `get_template` | Get details for one organization email or calendar template. | `templates:read` | Yes | | `list_modernloop_skills` | List available ModernLoop skill guides, optionally ranked by a fuzzy `query`. | No scope (any authenticated token) | Yes | | `load_modernloop_skill` | Load one skill guide by exact name, its header only, or one bundled reference. | No scope (any authenticated token) | Yes | | `submit_mcp_feedback` | Submit feedback about the MCP server itself: a tool bug, a missing capability, or workflow friction. Never includes candidate or customer data, PII, secrets, or raw tool arguments. | No scope (any authenticated token) | No | `delete_interview_module`, `delete_interview_module_member`, and `cancel_scheduling_task` are destructive. Read the current record and obtain explicit confirmation before calling them. `create_scheduling_task` requires an `idempotency_key`; reuse that key only when retrying the same intended create. ## Skill guides Skill guides are Markdown playbooks served over MCP. They describe the correct tool order, required inputs, safety rules, and common pitfalls for one scheduling domain, so an agent does not have to infer a workflow from `tools/list`. 1. Call `list_modernloop_skills` with topic keywords in `query` and a brief `telemetry.intent`. Omit `query` to list every applicable guide. Add `include_header: true` for descriptions, related guides, and bundled reference paths. 2. Call `load_modernloop_skill` with the **exact** `skill_name` from that response. Skill names are case-sensitive and are never inferred from topic words. 3. Use `header_only: true` to preview a guide, or `resource_path` to load one bundled reference without reloading the whole guide. Both tools require `telemetry.intent`: a brief English statement of what you are doing. Never put candidate or employee data, argument values, or secrets in it — ModernLoop does not retain the raw text, and it is not a place for sensitive input. The beta catalog covers `modernloop/task-triage`, `modernloop/candidate-investigation`, `modernloop/scheduling-task-creation`, and `modernloop/interviewer-capacity`. A guide is only listed and loadable when **every** tool it documents is visible to your token, endpoint, and connection filters. On `/mcp/readonly`, guides covering task writes are absent. An unavailable or unknown skill name returns the same `NOT_FOUND` response, so a failed load is never evidence that a guide exists. ## Workflow prompts Copy one of these into a connected MCP client. Replace the bracketed text with your context. ### Triage my scheduling tasks > Use `get_me` first, then call `list_scheduling_tasks` with `my_tasks: true` for your open scheduling tasks. Group them by urgency, status, and queue; call `get_scheduling_task` for the highest-priority items. Do not change anything. ### Create a scheduling task for a candidate > Find candidate \[name or email], then find their active application for \[job]. Read the application and its job stages, identify the requested stage, and summarize the target application and stage before creating a scheduling task. After I confirm, call `create_scheduling_task` with a new idempotency key and report the result. ### Investigate why a candidate is not scheduled > Find candidate \[name or email], then inspect their applications, scheduling tasks, schedules, and interview events. Explain the current status and blockers using only the returned data. Do not make changes. ### Review interviewer capacity > List users matching \[team, name, or module], then inspect the relevant users and interview-module training statistics. Identify people who are paused or near their configured limits. Do not make changes. ### Troubleshoot a ModernLoop issue > Search the help knowledge base for \[issue or error message] with `list_help_articles`, read the best matches with `get_help_article`, and summarize the recommended steps with canonical article links. If nothing relevant is found, say so and ask one clarifying question. ### Find stale tasks in a queue > Find the task queue named \[queue name], then list its scheduling tasks that have not been updated since \[date]. Summarize status, assignee, urgency, and the next useful follow-up. Do not make changes. ## Further reading * [MCP Data Model](/mcp/data-model) — object relationships, IDs, discovery, and pagination * [ModernLoop MCP](/mcp/setup) — scopes and troubleshooting * [MCP Toolsets](/mcp/toolsets) — read-only versus default endpoint # MCP Toolsets Source: https://docs.modernloop.io/mcp/toolsets Choose the default or read-only toolset for your MCP connection. ModernLoop exposes two MCP toolsets. Each toolset maps to a separate endpoint and OAuth resource. A token issued for one endpoint cannot call the other. Use the read-only toolset unless your workflow needs to create, update, or delete ModernLoop data. ## Available toolsets | Toolset | Endpoint | Tools | OAuth scopes | Use when | | - | - | -: | - | - | | **Read-only** | `https://api.modernloop.io/mcp/readonly` | Read tools only | Read scopes only | The agent only looks up scheduling data | | **Default** | `https://api.modernloop.io/mcp` | All read and write tools | Read and write scopes | The agent may change ModernLoop data | Both toolsets use [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) transport and OAuth 2.1 with PKCE. See [ModernLoop MCP](/mcp/setup) for client configuration. ## Connection-level tool filtering Add one of these query parameters to the MCP endpoint URL to narrow the tools available to a connection: | Parameter | Behavior | Use when | | - | - | - | | `include_tools` | Allowlist. Exposes only the named tools that are otherwise available to the connection. | The connection supports a small, stable workflow and should hide every unrelated tool. | | `exclude_tools` | Blocklist. Hides the named tools and leaves all other available tools visible. | The connection needs most of a toolset but should remove specific tools. | Each parameter accepts a comma-separated list of exact names from [MCP Tools](/mcp/tools). Use only names available on the selected endpoint. Whitespace and trailing commas are ignored. ```text theme={"dark"} https://api.modernloop.io/mcp?include_tools=get_me,list_candidates,list_scheduling_tasks https://api.modernloop.io/mcp/readonly?exclude_tools=list_templates ``` The parameters cannot be combined. An empty list or an unknown tool name returns HTTP `400` with `VALIDATION_FAILED`, preventing a typo from silently changing the connection's tool surface. Filtering can only remove access. It intersects with the selected endpoint, OAuth scopes, and organization entitlements; it does not request, grant, or alter permissions. For example, adding a tool to `include_tools` does not make it visible when the token lacks its required scope. The filter applies throughout the connection: * `tools/list` omits filtered tools. * Calling a filtered tool directly returns `NOT_FOUND`. * Built-in prompts and workflow guidance are omitted when they require a filtered tool. Keep `get_me` in an allowlist so agents can inspect granted scopes and `tool_access`. After connecting, use `tools/list` as the authoritative list of tools visible to that endpoint, token, organization, and filter. ### Read-only toolset The read-only toolset exposes lookup and list tools only. It does not include create, update, or delete operations. Included areas: * Candidates, applications, jobs, and job stages * Users and interviewer capacity * Interview modules and module membership * Organization settings (read) * Interview events and schedules * Scheduling tasks and task queues * Email and calendar templates OAuth tokens for this endpoint are limited to read scopes. The authorization server issues a separate resource identifier for `/mcp/readonly`. ### Default toolset The default toolset includes every read-only tool plus 15 write tools. Additional write capabilities: | Area | Write tools | | - | - | | Candidates | `update_candidate` | | Applications | `update_application` | | Jobs | `update_job`, `update_job_stage` | | Users | `update_user` | | Interview modules | `create_interview_module`, `update_interview_module`, `delete_interview_module`, `create_interview_module_member`, `update_interview_module_member`, `delete_interview_module_member` | | Organization | `update_organization` | | Scheduling tasks | `create_scheduling_task`, `update_scheduling_task`, `cancel_scheduling_task` | `delete_interview_module`, `delete_interview_module_member`, and `cancel_scheduling_task` are marked destructive. Confirm with the user before calling them. ## Tool availability Tool availability depends on four factors: 1. **Endpoint** — The read-only endpoint omits all write tools. 2. **OAuth scopes** — The token must include the scope each tool requires. See [Required permissions](/mcp/setup#required-permissions). 3. **Organization entitlements** — Tools for resources your organization cannot access return not found. 4. **Connection filter** — `include_tools` or `exclude_tools` can further narrow the connection's tool surface. After connecting, call `tools/list` for the authoritative tool list and input schemas for your session. ## Choose a toolset Point your MCP client at: ``` https://api.modernloop.io/mcp/readonly ``` Grant only the read scopes your workflow needs during OAuth consent. Point your MCP client at: ``` https://api.modernloop.io/mcp ``` Grant read and write scopes during OAuth consent. Prefer the read-only endpoint if write access is not required. ## Further reading * [ModernLoop MCP](/mcp/setup) — client-specific connection steps * [MCP Tools](/mcp/tools) — per-tool reference with read-only toolset membership * [MCP Data Model](/mcp/data-model) — relationships, IDs, discovery, and pagination