advancedmd_get_updated_visits, the change-driven appointment polling tool exposed through the Agents Platform.
Authentication
AdvancedMD tools use the existing AdvancedMD connector. Users configure:office_codeusernamepassword
advancedmd_get_updated_visits
Polls AdvancedMD’s getupdatedvisits API for appointments created, modified or cancelled since a cursor timestamp. This is a read-only tool.
When to use this instead of advancedmd_list_appointments
Use
get_updated_visits for intake and onboarding automations that must react to new bookings. Use list_appointments for schedule read-outs.
Inputs
All inputs are optional — a bare call bootstraps with the default lookback.cursor_key: Durable cursor name, e.g. the office code. When set, the poll position is loaded from the agent data store and advanced after each successful poll — see Durable cursor below. Recommended for scheduled polling; use one key per office.changed_since: The cursor from the previous call’snext_cursor. Accepts AdvancedMD format (MM/DD/YYYY H:MM:SS AM/PM), RFC3339, orYYYY-MM-DD HH:MM:SS. Values with no offset are read as office-local time; an RFC3339 offset is converted intotimezonefirst, so2026-07-27T16:00:00Zis sent as07/27/2026 9:00:00 AMfor a Pacific office. An explicit value here overrides acursor_keyread.lookback_minutes: Bootstrap window used only whenchanged_sinceis absent. Defaults to60.timezone: IANA timezone of the AdvancedMD office. Used to build the bootstrap window, and to convert achanged_sincethat carries an offset. Defaults toAmerica/Los_Angeles— set it explicitly for a non-Pacific office, or the bootstrap window is shifted by that offset (eastward offices over-read, which dedup absorbs; the default is not safe to rely on).update_status: Keep only these change kinds —added,modified,deleted. Defaults to all. Filtering is lossy across polls: the cursor advances past the kinds you exclude, so they can never be fetched again for those windows. The excluded count comes back asfiltered_out.limit: Maximum visits to accept. Defaults to200. More changes than this is an error, not a clipped result — see Notes.
The cursor contract
next_cursor is AdvancedMD’s own server clock, read from the response’s servertime. Always round-trip it into the next poll rather than computing a timestamp locally.
Note the two ends of the round trip use different formats. AdvancedMD returns
servertime as ISO with milliseconds (2026-01-07T04:14:01.753) but accepts
@datechanged only as MM/DD/YYYY H:MM:SS AM/PM. The tool parses both and
converts, so a returned next_cursor can be fed straight back in — but a caller
comparing the two strings will see them differ.
Two failure modes this avoids:
- Clock skew drops visits. AdvancedMD interprets
@datechangedin office-local time. A worker running in UTC that computes “now minus 5 minutes” sends a timestamp 7–8 hours in the future for a US Pacific office, and the poll silently returns nothing. This is why the bootstrap path takes atimezonerather than using UTC. - Restarting from “now” skips the gap. If a response carries no
servertime, the tool returns the input cursor (or the bootstrap window start) asnext_cursorinstead, so the next poll re-reads the window rather than skipping everything that changed during it. The input cursor string is kept verbatim — re-formatting would drop its millisecond precision.
Durable cursor (cursor_key)
Without cursor_key, the agent must carry next_cursor between polls itself — impossible
for a scheduled agent whose runs are separate tasks, which is why every run would otherwise
bootstrap from lookback_minutes and lean on downstream dedup. With cursor_key:
- The position is stored in the agent data store under the reserved record type
system/advancedmd-visit-cursor(created automatically on first use), scoped to the agent group so different agents keep independent positions. - When
changed_sinceis omitted, the stored position drives the window; only the very first run bootstraps vialookback_minutes. - After a successful poll the stored position advances under a monotonic guard: a retried
or out-of-order poll can never move it backwards. When a newer position already stands
(another run advanced past this window), the result reports
cursor_persisted: false, returns the standing position asnext_cursor, and warns that the window was likely already handled. - If the cursor cannot be persisted, the call fails rather than returning visits — an unpersisted cursor means the next run re-reads the window, and the caller’s CRM writes are not idempotent.
- An explicit
changed_sincethat starts after the stored position polls normally but does not advance the stored cursor (cursor_persisted: falsewith an explanatory note) — advancing would permanently skip the visits between the stored position and the override. An explicitchanged_sinceat or before the stored position (a re-read) advances as usual. - Known DST limitation. The stored position compares as an office-local wall-clock
string with no UTC offset. Around a fall-back transition the repeated hour can make two
real-time-ordered
servertimevalues compare out of order, so an advance inside that hour may be refused and the window re-polled next run. The guard errs toward re-reading (dedup absorbs it) — it never skips forward.
cursor_key, cursor_source (store, argument or bootstrap) and
cursor_persisted when cursor_key is used.
Output
Structured content includes:changed_since: the window start actually sent to AdvancedMDnext_cursor: cursor for the next pollbootstrapped:truewhen the lookback path was used instead of a supplied cursortotal_changed: how many visits AdvancedMD reported changed, beforeupdate_statusfiltering — this is whatlimitis checked againstcount: number of visits returnedfiltered_out: present only whenupdate_statusexcluded some, since those fall behind the cursorvisits: array of visit records
update_status — added, modified or deleted, normalised from the A/M/D codes AdvancedMD puts on the wire, so it matches the vocabulary the update_status filter takes — plus scheduling fields, facility_code, created_by, and a nested patient_list.patient with chart number, name, phones, email and insurance list.
created_by identifies the booking user, which is how a self-scheduling source is attributed — e.g. a zoc… username for Zocdoc bookings versus nex… for NextPatient. The attribute itself resolves: it came back populated on every visit of a live getupdatedvisits payload (2026-08-03). The zoc…/nex… prefix convention, however, is taken from the AdvancedMD UI and has not been confirmed against a real self-scheduled booking — treat a prefix match as a heuristic until it has.
Example shape:
Notes
- Field selection is fixed by the tool: AdvancedMD only returns attributes named in the request, and the tool asks for the scheduling, patient-contact and insurance fields an intake flow needs.
- Over-
limitis an error, not a clipped result.getupdatedvisitstakes no offset, so a clipped window cannot be paged: returning part of it would either lose the remainder (if the caller advances the cursor) or re-read the same window forever (if it holds). Instead the tool fails with the actual count and leaves the cursor unadvanced, so an unattended poller surfaces the problem rather than stalling on a billed no-op loop. Raiselimitabove the reported count, or poll a narrower window. - Deduplication is the caller’s responsibility. A visit modified twice between polls appears once, but a visit that stays modified across successive windows can appear in more than one poll.
- Silent capping is rejected.
Results/@visitcountis compared against the number of visit elements returned; a shortfall means AdvancedMD capped the set without raising a fault, so the tool errors rather than advancing the cursor past visits it never saw. Verified on a live office that the two agree at 0, 4 and 95 visits. servertimeclock. Measured on a live office as office-local (01:36:11againstAmerica/Los_Angeles01:36:09), not a UTC or Mountain server clock. Round-tripping it is therefore consistent for a Pacific office. A single office cannot prove the value is derived from the office rather than a fixed AdvancedMD clock that happens to be Pacific — worth re-checking against a non-Pacific office before relying on the cursor there.- Only-IDs mode. When a window matches too many visits, AdvancedMD returns a fault (wording varies — “only IDs”, “too many”, “truncated”) and omits the visit attributes. The tool surfaces this as a tool error rather than an empty success, so the caller must not advance its cursor; retry with a narrower window. Bootstrapping with a very large
lookback_minutesis the usual way to trip this. - Timezone data is embedded. The package imports
time/tzdata, so named zones resolve without OS tzdata. The worker runtime image isalpine+ca-certificatesonly, wheretime.LoadLocationwould otherwise fail with “unknown timezone” on the defaultAmerica/Los_Angeles. - Multi-office tenants. One call covers one office code, since credentials are per office. A tenant with several office keys needs one call per office and a cursor per office; taking the max
servertimeacross offices will skip visits in whichever office lags. - Do not advance a stored cursor when the call errors or returns no
servertime— the window was never observed, and advancing past it drops those visits permanently.