https://mcp.eschedule.it/mcphttps://mcp.eschedule.it/v1 · OpenAPI 3.1: /openapi.json/.well-known/oauth-protected-resourcehttps://auth.eschedule.it · discovery /.well-known/openid-configurationresource=: https://mcp.eschedule.it and https://mcp.eschedule.it/mcpeschedule:read, eschedule:write, eschedule:messaging.https://auth.eschedule.it/connect/authorize with resource=https://mcp.eschedule.it/mcp (or the base URL), then exchange at https://auth.eschedule.it/connect/token. The user signs in, picks one account, and grants scopes. Access tokens live 1 hour; refresh tokens 30 days, and refresh re-checks that the user may still use the account.Authorization: Bearer <token> on every call. A 401 with WWW-Authenticate: Bearer resource_metadata="…" means start over; a 403 with error="insufficient_scope", scope="…" means re-authorize requesting that scope.The connected account is part of the token. No request takes an account identifier; any such parameter is rejected with 400.
The account this connection is locked to: its name, distance unit, decline timeout, and its locations with addresses. Use it to resolve a place the user names in conversation. No ids, provisioning or billing fields.
eschedule:read · Posture: read-onlyReadAccountGET /v1/account{
"type": "object",
"additionalProperties": false
}
Find-or-create a client by name plus phone or email, and propose an appointment for them with the given staff. Staged as a booking request for approval unless the account auto-approves bookings. Check find_open_appointment_slots first, and quote the returned request_id to the user.
eschedule:write · Posture: staged for approval unless the account allows automatic approvalBookAppointmentPOST /v1/appointments/book-for-contact{
"type": "object",
"properties": {
"contact_name": {
"type": "string"
},
"contact_phone": {
"type": [
"string",
"null"
]
},
"contact_email": {
"type": [
"string",
"null"
]
},
"start_utc": {
"type": "string",
"format": "date-time"
},
"end_utc": {
"type": "string",
"format": "date-time"
},
"performer_resource_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"offering_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"description": {
"type": [
"string",
"null"
]
},
"notes": {
"type": [
"string",
"null"
]
},
"time_zone": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Find bookable slots. Offering mode uses the offering's duration and requirements; custom mode takes a duration plus required people and tag requirements. Window ≤ 31 days. Each candidate lists the people who would be booked, an authorization/capacity verdict (Ok, Warning, Critical, Unknown) and warnings — surface a Critical verdict to the user before proposing the slot.
eschedule:read · Posture: read-onlySearchAppointment, SearchAvailabilityPOST /v1/appointments/candidates{
"type": "object",
"properties": {
"search_mode": {
"type": "string"
},
"offering_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"duration": {
"type": [
"string",
"null"
]
},
"required_resource_ids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"additional_resource_ids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"required_tags": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"tag_id": {
"type": "string",
"format": "uuid"
},
"operand": {
"type": "string"
},
"value1": {
"type": "integer"
},
"value2": {
"type": [
"integer",
"null"
]
}
},
"additionalProperties": false
}
},
"start_utc": {
"type": "string",
"format": "date-time"
},
"end_utc": {
"type": "string",
"format": "date-time"
},
"start_time_of_day": {
"type": [
"string",
"null"
]
},
"end_time_of_day": {
"type": [
"string",
"null"
]
},
"proximity_type": {
"type": [
"string",
"null"
]
},
"proximity_miles": {
"type": [
"number",
"null"
]
},
"max_results": {
"type": "integer"
},
"timezone": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Propose appointment changes — create, reschedule/update, cancel or delete, one batch per request (at most 25). The proposal is STAGED: it waits for approval in eScheduleIt unless the account auto-approves that kind of change. Times are UTC instants; the approver sees them in the account's zone. Use find_open_appointment_slots first when creating, and quote the returned request_id to the user so they can find it.
eschedule:write · Posture: staged for approval unless the account allows automatic approvalCreateAppointment, UpdateAppointment, CancelAppointment, DeleteAppointmentPOST /v1/appointments/changes{
"type": "object",
"properties": {
"change_reason": {
"type": "string"
},
"time_zone": {
"type": [
"string",
"null"
]
},
"appointments_to_create": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"start_utc": {
"type": "string",
"format": "date-time"
},
"end_utc": {
"type": "string",
"format": "date-time"
},
"resource_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"offering_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"notes": {
"type": [
"string",
"null"
]
},
"subjects": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"role_name": {
"type": "string"
},
"resource_id": {
"type": "string",
"format": "uuid"
}
},
"additionalProperties": false
}
},
"replaces_appointment_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"recurrence": {
"type": [
"object",
"null"
],
"properties": {
"frequency": {
"type": "string"
},
"days_of_week": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"interval": {
"type": "integer"
},
"monthly_mode": {
"type": [
"string",
"null"
]
},
"until_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"count": {
"type": [
"integer",
"null"
]
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"appointments_to_update": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"appointment_id": {
"type": "string",
"format": "uuid"
},
"occurrence_start_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"new_start_date": {
"type": [
"string",
"null"
]
},
"new_start_time": {
"type": [
"string",
"null"
]
},
"new_end_time": {
"type": [
"string",
"null"
]
},
"new_description": {
"type": [
"string",
"null"
]
},
"new_resource_ids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"new_offering_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"new_notes": {
"type": [
"string",
"null"
]
},
"update_reason": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
},
"appointments_to_cancel": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"appointment_id": {
"type": "string",
"format": "uuid"
},
"occurrence_start_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"cancellation_reason": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
},
"appointments_to_delete": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"appointment_id": {
"type": "string",
"format": "uuid"
},
"occurrence_start_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"delete_reason": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
Appointments for one person (resource_id) in a window of at most 180 days. Returns start/end in UTC and in the requested time zone, offering, status (Confirmed, Pending, Cancelled…), recurrence flag, and the other participants by id, name, status and tags — no contact details (use lookup_resource for those). Holidays overlapping the window are included.
eschedule:read · Posture: read-onlySearchAppointmentGET /v1/appointments{
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"start_utc": {
"type": "string",
"format": "date-time"
},
"end_utc": {
"type": "string",
"format": "date-time"
},
"timezone": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Standing assignments between a client and the staff who cover them: coverage role, kind, status, and the dates the assignment runs between. Pass resource_id for everything a person is part of on either side, OR name one side with beneficiary_resource_id or performer_resource_id — not both, they ask different questions. Ended assignments are excluded unless include_ended is true. Use it to keep continuity — the person already assigned is usually the right one to book.
eschedule:read · Posture: read-onlyengagement.viewGET /v1/assignments{
"type": "object",
"properties": {
"resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"beneficiary_resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"performer_resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"include_ended": {
"type": "boolean"
}
},
"additionalProperties": false
}
For an open demand entry (a client needing a standing assignment), have eScheduleIt score candidates and create an assignment proposal — optionally preferring one staff member. The proposal waits for approval unless the account auto-approves assignments. Scores are not returned; the approver sees them in the app.
eschedule:write · Posture: staged for approval unless the account allows automatic approvalengagement.view, engagement.editPOST /v1/assignments/propose{
"type": "object",
"properties": {
"demand_entry_id": {
"type": "string",
"format": "uuid"
},
"preferred_performer_resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"rationale": {
"type": "string"
}
},
"additionalProperties": false
}
Why one allocation was allowed, warned about or refused: the thresholds that applied, what was already committed, and which rule decided. Use it when a user asks why a booking was blocked, instead of guessing from the refusal message.
eschedule:read · Posture: read-onlyauthz.capacity.viewGET /v1/authorizations/allocations/{allocation_id}/explain{
"type": "object",
"properties": {
"allocation_id": {
"type": "string",
"format": "uuid"
}
},
"additionalProperties": false
}
People whose authorized hours are going unused: how many units remain, how many weeks are left in the period, the weekly burn required to use them against what is actually scheduled, and an urgency score. Ranked most urgent first. Use it to decide who to schedule next.
eschedule:read · Posture: read-onlyauthz.reports.utilization.viewGET /v1/authorizations/coverage-opportunities{
"type": "object",
"properties": {
"min_urgency": {
"type": "number"
},
"max_results": {
"type": "integer"
}
},
"additionalProperties": false
}
Staff who are under their billable target for the ISO week containing week_start (default: this week): planned minutes against base and overtime thresholds, and how far under target they are. Ranked by the largest shortfall first, so the first name is the person to give work to.
eschedule:read · Posture: read-onlyauthz.reports.utilization.viewGET /v1/authorizations/resources-needing-hours{
"type": "object",
"properties": {
"week_start": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"max_results": {
"type": "integer"
}
},
"additionalProperties": false
}
Authorized-hours balances per beneficiary and bucket: authorized, held, consumed, scheduled, remaining and available-to-book units, utilization percent, projected run-out date and runway warning level. Filter by beneficiary, bucket, minimum warning level or a utilization band.
eschedule:read · Posture: read-onlyauthz.reports.balances.viewGET /v1/authorizations/balances{
"type": "object",
"properties": {
"beneficiary_resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"allowance_bucket_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"min_warning_level": {
"type": [
"string",
"null"
]
},
"min_utilization_percent": {
"type": [
"number",
"null"
]
},
"max_utilization_percent": {
"type": [
"number",
"null"
]
}
},
"additionalProperties": false
}
How one authorization has been used over time, weekly or monthly: authorized, scheduled, consumed and remaining units per period. Use it to say whether usage is on track or falling behind, rather than guessing from a single balance.
eschedule:read · Posture: read-onlyauthz.reports.trends.viewGET /v1/authorizations/{allowance_grant_id}/trends{
"type": "object",
"properties": {
"allowance_grant_id": {
"type": "string",
"format": "uuid"
},
"granularity": {
"type": "string"
},
"range_start": {
"type": "string",
"format": "date-time"
},
"range_end": {
"type": "string",
"format": "date-time"
}
},
"additionalProperties": false
}
Authorizations ending within within_days (1-365, default 30): when each period ends, how many units are still unused and therefore at risk, whether a renewal grant already exists, and whether anything is already booked past the end date with no renewal — which is the case worth raising with the user first.
eschedule:read · Posture: read-onlyauthz.reports.expiring.viewGET /v1/authorizations/expiring{
"type": "object",
"properties": {
"within_days": {
"type": "integer"
}
},
"additionalProperties": false
}
A person's weekly capacity and authorization balances for the ISO week containing week_start (default: this week): planned minutes against thresholds, per capacity kind and per authorization bucket. Use it before proposing extra work, so you can say whether it fits.
eschedule:read · Posture: read-onlyauthz.capacity.viewGET /v1/people/{resource_id}/capacity{
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"week_start": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"source_filter": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
A suggested plan for recovering under-used authorized hours over the chosen horizon: which beneficiaries are behind, roughly how much to schedule, and which staff have the capacity to take it. Read-only advice — nothing is booked, and every suggestion still has to go through find_open_appointment_slots.
eschedule:read · Posture: read-onlyauthz.reports.utilization.viewGET /v1/authorizations/recovery-plan{
"type": "object",
"properties": {
"horizon": {
"type": "string"
}
},
"additionalProperties": false
}
Free slots for a person: working hours minus booked appointments and holiday closures, cut into slots of slot_duration_minutes (default 30), over a window of at most 31 days. Each entry says whether it is available and names the holiday closing it when it is not.
eschedule:read · Posture: read-onlyReadAvailabilityGET /v1/people/{resource_id}/open-availability{
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"start_date": {
"type": "string",
"format": "date-time"
},
"end_date": {
"type": "string",
"format": "date-time"
},
"timezone": {
"type": [
"string",
"null"
]
},
"slot_duration_minutes": {
"type": "integer"
}
},
"additionalProperties": false
}
A person's declared working hours (availability patterns) in a window of at most 180 days, expanded to concrete entries in UTC and the requested time zone, with a plain-language summary. This is when they are meant to be working, not when they are free — use check_resource_open_availability for that.
eschedule:read · Posture: read-onlyReadAvailabilityGET /v1/people/{resource_id}/working-schedule{
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"start_date": {
"type": "string",
"format": "date-time"
},
"end_date": {
"type": "string",
"format": "date-time"
},
"timezone": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Holiday closures that apply to a person in a window of at most a year, in UTC and the requested time zone. Use it before proposing appointments on or near public holidays, so the user is not offered a slot the office is shut for.
eschedule:read · Posture: read-onlyReadAvailabilityGET /v1/people/{resource_id}/holidays{
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"start_utc": {
"type": "string",
"format": "date-time"
},
"end_utc": {
"type": "string",
"format": "date-time"
},
"timezone": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Propose changes to one person's working hours — add slots, block slots, or end, delete, suspend or replace an existing recurring pattern (at most 25 changes per request). The proposal is STAGED: it waits for approval in eScheduleIt unless the account auto-approves that kind of change. Check check_resource_working_schedule first to see what is already there, and quote the returned request_id to the user.
eschedule:write · Posture: staged for approval unless the account allows automatic approvalCreateAvailability, UpdateAvailability, DeleteAvailabilityPOST /v1/availability/request{
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"update_reason": {
"type": "string"
},
"time_zone": {
"type": [
"string",
"null"
]
},
"slots_to_add": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"start_date_time": {
"type": "string",
"format": "date-time"
},
"end_date_time": {
"type": "string",
"format": "date-time"
},
"recurrence": {
"type": [
"object",
"null"
],
"properties": {
"frequency": {
"type": "string"
},
"days_of_week": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"interval": {
"type": "integer"
},
"monthly_mode": {
"type": [
"string",
"null"
]
},
"until_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"count": {
"type": [
"integer",
"null"
]
}
},
"additionalProperties": false
},
"notes": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
},
"slots_to_block": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/properties/slots_to_add/items"
}
},
"pattern_operations": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"operation": {
"type": "string"
},
"availability_id": {
"type": "string",
"format": "uuid"
},
"effective_from_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"resume_from_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"replacement": {
"type": [
"object",
"null"
],
"properties": {
"start_date_time": {
"type": "string",
"format": "date-time"
},
"end_date_time": {
"type": "string",
"format": "date-time"
},
"recurrence": {
"$ref": "#/properties/slots_to_add/items/properties/recurrence"
},
"notes": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
Who you are acting for. Returns the signed-in person's name, the account this connection is locked to, the account's time zone, today's date in that zone, the scopes this connection was granted, and the tools you may call. Call this first in a conversation. Never ask the user for an account id — the account is fixed by the connection.
eschedule:read · Posture: read-onlyGET /v1/me{
"type": "object",
"additionalProperties": false
}
Who could replace one or more people on an existing appointment, honouring its offering requirements, tags and proximity. For a recurring series you must pass occurrence_start_utc and occurrence_end_utc for the specific instance — the series seed date is not a valid anchor. Read-only; propose the change with manage_appointments.
eschedule:read · Posture: read-onlySearchAppointment, SearchAvailabilityPOST /v1/coverage/analyze-appointment{
"type": "object",
"properties": {
"appointment_id": {
"type": "string",
"format": "uuid"
},
"resource_ids_to_replace": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"required_tag_ids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"proximity_miles": {
"type": [
"number",
"null"
]
},
"timezone": {
"type": [
"string",
"null"
]
},
"occurrence_start_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"occurrence_end_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": false
}
For a requirement (duration, window ≤ 31 days, required people and tags), report where coverage exists (open slots), where it is missing (coverage gaps) and who could be asked to fill gaps (outreach candidates). Read-only analysis; to book, use find_open_appointment_slots and then manage_appointments.
eschedule:read · Posture: read-onlySearchAppointment, SearchAvailabilityPOST /v1/coverage/analyze{
"type": "object",
"properties": {
"duration_minutes": {
"type": "integer"
},
"start_utc": {
"type": "string",
"format": "date-time"
},
"end_utc": {
"type": "string",
"format": "date-time"
},
"start_time_of_day": {
"type": [
"string",
"null"
]
},
"end_time_of_day": {
"type": [
"string",
"null"
]
},
"required_resource_ids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"required_tags": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"tag_id": {
"type": "string",
"format": "uuid"
},
"operand": {
"type": "string"
},
"value1": {
"type": "integer"
},
"value2": {
"type": [
"integer",
"null"
]
}
},
"additionalProperties": false
}
},
"exclude_resource_ids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"proximity_type": {
"type": [
"string",
"null"
]
},
"proximity_miles": {
"type": [
"number",
"null"
]
},
"timezone": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Propose an SMS or email announcement to everyone carrying the given tags. It is QUEUED FOR APPROVAL in eScheduleIt and never sent directly, unless the account auto-approves announcements. Sending identical content twice creates one announcement, not two.
eschedule:messaging · Posture: staged for approval unless the account allows automatic approvalSendAnnouncementPOST /v1/announcements{
"type": "object",
"properties": {
"tag_names": {
"type": "array",
"items": {
"type": "string"
}
},
"channel_policy": {
"type": "string"
},
"sms_body": {
"type": [
"string",
"null"
]
},
"email_subject": {
"type": [
"string",
"null"
]
},
"email_body": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
Offerings (services) the account schedules, by name/description search with fuzzy matching and optional enabled/public filters. Paged, 1-based, at most 50 per page. Returns each offering's duration and the tag and people requirements it imposes, which find_open_appointment_slots then honours in offering mode.
eschedule:read · Posture: read-onlySearchOfferingGET /v1/offerings{
"type": "object",
"properties": {
"query": {
"type": [
"string",
"null"
]
},
"enabled": {
"type": [
"boolean",
"null"
]
},
"is_public": {
"type": [
"boolean",
"null"
]
},
"page": {
"type": "integer"
},
"page_size": {
"type": "integer"
},
"match_threshold": {
"type": [
"number",
"null"
]
}
},
"additionalProperties": false
}
Find a person (staff or client) in the account by id, phone, name or email. Returns contact details, tags, time zone and linked logins. This is the ONLY tool that returns contact details; search tools return ids and names. Fuzzy matching may return several candidates — ask the user to disambiguate rather than guessing.
eschedule:read · Posture: read-onlySearchResourceGET /v1/people/lookup{
"type": "object",
"properties": {
"resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"phone_number": {
"type": [
"string",
"null"
]
},
"name": {
"type": [
"string",
"null"
]
},
"email": {
"type": [
"string",
"null"
]
},
"match_threshold": {
"type": [
"number",
"null"
]
}
},
"additionalProperties": false
}
Propose changes to people (staff or clients) — create, update or delete, one batch per request (at most 25). The proposal is STAGED: it waits for approval in eScheduleIt unless the account auto-approves that kind of change. Quote the returned request_id to the user so they can find it.
eschedule:write · Posture: staged for approval unless the account allows automatic approvalCreateResource, UpdateResource, DeleteResourcePOST /v1/resources/changes{
"type": "object",
"properties": {
"change_reason": {
"type": "string"
},
"resources_to_create": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
]
},
"active": {
"type": "boolean"
},
"preferred_language": {
"type": [
"string",
"null"
]
},
"preferred_contact_method": {
"type": [
"string",
"null"
]
},
"timezone": {
"type": [
"string",
"null"
]
},
"contacts": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"value": {
"type": "string"
}
},
"additionalProperties": false
}
},
"tags": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
}
},
"additionalProperties": false
}
},
"resources_to_update": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"new_name": {
"type": [
"string",
"null"
]
},
"new_description": {
"type": [
"string",
"null"
]
},
"new_active": {
"type": [
"boolean",
"null"
]
},
"new_preferred_language": {
"type": [
"string",
"null"
]
},
"new_preferred_contact_method": {
"type": [
"string",
"null"
]
},
"new_timezone": {
"type": [
"string",
"null"
]
},
"contacts_to_add": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/properties/resources_to_create/items/properties/contacts/items"
}
},
"contact_ids_to_remove": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
},
"tags_to_add": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"tags_to_remove": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
}
},
"additionalProperties": false
}
},
"resources_to_delete": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"deletion_reason": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
Tags (skills, credentials, regions, groups) used to label people, with the people carrying each tag by id and name. Fuzzy search, paged, 1-based, at most 50 per page. Use it to turn a phrase the user says — 'a Spanish speaking RBT' — into the tag ids that find_open_appointment_slots takes.
eschedule:read · Posture: read-onlySearchTagGET /v1/tags{
"type": "object",
"properties": {
"query": {
"type": [
"string",
"null"
]
},
"page": {
"type": "integer"
},
"page_size": {
"type": "integer"
},
"match_threshold": {
"type": [
"number",
"null"
]
}
},
"additionalProperties": false
}
Propose task changes — create, update or delete, one batch per request (at most 25). The proposal is STAGED: it waits for approval in eScheduleIt unless the account auto-approves that kind of change. Quote the returned request_id to the user so they can find it.
eschedule:write · Posture: staged for approval unless the account allows automatic approvalCreateTask, UpdateTask, DeleteTaskPOST /v1/tasks/changes{
"type": "object",
"properties": {
"change_reason": {
"type": "string"
},
"tasks_to_create": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
]
},
"on_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"expected_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"due_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"task_resources": {
"type": "array",
"items": {
"type": "object",
"properties": {
"resource_id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": [
"string",
"null"
]
},
"on_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
},
"tasks_to_update": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"task_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": [
"string",
"null"
]
},
"description": {
"type": [
"string",
"null"
]
},
"expected_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"due_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": false
}
},
"tasks_to_delete": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
}
}
},
"additionalProperties": false
}
Tasks in the account, optionally for one person, by text search, status (Not Started, In Progress, Completed, Blocked, Cancelled, Overdue, Pending Review, Reviewed) and a date window on the calendar, expected or due date. Paged, 1-based, at most 50 per page.
eschedule:read · Posture: read-onlySearchTaskGET /v1/tasks{
"type": "object",
"properties": {
"resource_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"query": {
"type": [
"string",
"null"
]
},
"date_range_type": {
"type": "string"
},
"start_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"end_utc": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"statuses": {
"type": "array",
"items": {
"type": "string"
}
},
"timezone": {
"type": [
"string",
"null"
]
},
"page": {
"type": "integer"
},
"page_size": {
"type": "integer"
},
"match_threshold": {
"type": [
"number",
"null"
]
}
},
"additionalProperties": false
}
| HTTP | title |
Meaning |
|---|---|---|
| 400 | validation_failed |
Field errors in errors[] |
| 400 | account_id_not_accepted |
The request named an account identifier |
| 400 | forbidden_parameter |
The arguments named an account identifier |
| 400 | malformed_json |
The body is not valid JSON |
| 401 | — | Missing, expired or revoked token; see WWW-Authenticate |
| 403 | insufficient_privileges |
The connected user lacks a permission in eScheduleIt |
| 403 | insufficient_scope |
Re-authorize with the scope in WWW-Authenticate |
| 403 | account_ineligible |
The account or membership cannot use connected AI apps |
| 404 | not_found |
Not in this account |
| 409 | conflict |
Domain conflict; the message is safe to show |
| 429 | rate_limited |
Honour Retry-After |
| 503 | dependency_unavailable |
Retry after Retry-After |
| 500 | internal_error |
Quote correlation_id to support |
Bodies are RFC 9457 problem details (application/problem+json). MCP tool calls report validation and domain errors as isError: true results with the same messages; authentication and scope errors are HTTP-level so standard OAuth step-up works.
Per connected user: 120 requests, refilling 2 per second. Per account: 600 per minute. Anonymous documentation endpoints: 300 per minute per address. tools/list and get_my_context do not count against the per-user budget, so a throttled client can always find out what it may do. Limits are per replica and therefore approximate.
Writes accept Idempotency-Key (REST header) or idempotency_key (MCP argument). A replay with the same key and body inside the same connection returns the original result.