
The Coursedog connector ingests campus room usage from Coursedog into the Mapped graph. It imports your Coursedog buildings as Buildings (or Sub-Buildings) and your rooms as Spaces, then continuously syncs room bookings and materializes them as Calendar Events on each room's booking calendar.
Coursedog exposes room usage through two unrelated products, and this connector reads both:
This gives the Mapped Graph a live, structured view of when and where campus rooms are in use — data that can be forwarded downstream (for example, to the Willow Events Destination Connector) to drive energy optimization and space-utilization use cases.
The connector authenticates with an integration user's email and password, which it exchanges for a session token on every run. A read-only Coursedog API account is sufficient — the connector never writes.
| Field | Required | Description |
|---|---|---|
| Environment | Yes | Production (app.coursedog.com) or Staging (staging.coursedog.com). Coursedog tenants are provisioned per environment, so pick the one your account exists on. |
| School ID | Yes | Your Coursedog school identifier, e.g. tcu_peoplesoft. It appears in the path of nearly every API call. |
| Integration User Email | Yes | The email of the API user your Coursedog administrator created for Mapped. |
| Password | Yes | That user's password. |
Saving this step verifies both the credentials and the school ID before storing anything: a valid login against the wrong school authenticates fine but would return no data.
Note: Coursedog invalidates a session token whenever a new session is created with the same credentials — including someone signing in through the browser. The connector therefore mints a fresh token per run rather than caching one, which is what makes a shared service account safe to use.
Coursedog stores class and event times as local wall-clock with no timezone attached. Set the campus timezone here so bookings land at the right instant; without it every event would be off by hours.
Institutions spanning multiple timezones can add per-campus overrides via the campusTimezones config field, keyed by the room's Coursedog campus code (e.g. TCUMAIN). A room whose campus has no override falls back to the connector-level timezone.
This connector uses the Mapped entities framework (not legacy place mappings). Places are imported top-down in three steps, each its own step in the configuration UI. Read more on setting merge rules for updating entities in bulk.
Load your Coursedog buildings and select which to import. Coursedog has no Site concept, so you choose how each building links into the org graph by filling in one of two parent columns:
If both are filled in, the Parent Building wins. A postal address is composed from the Coursedog address fields. The sub-building code defaults to Coursedog's building id, which is the registrar's building code (e.g. NEEL) — the same code your authoritative place source is likely to publish, making it the cross-connector anchor.
Coursedog does not record floors at all, so these are derived from room numbering: "NEEL 1219" implies floor 1, "RIC 035" implies the ground floor (level 0). The step collapses the rooms of the buildings you selected into the distinct floors they imply, showing how many rooms are behind each one so you can tell a real floor from a stray room number.
Review the levels, correct any that are wrong, and save. Levels are zero-based, matching Mapped: the ground floor is 0.
Note: the derivation reads only the leading digit, so it does not try to guess for buildings taller than nine floors — "1001" could be floor 1 or floor 10. Fix those in the grid.
Each floor carries a building-scoped level identity, which is what resolves it onto the floor you already have in Mapped at that level rather than creating a parallel one.
Load rooms as Spaces for the buildings you selected. Each room is pre-wired to the floor its number implies, when that floor was merged in the previous step. Rooms that are named rather than numbered ("ATRIUM1", "Arnold Hall Demo Room") imply no floor and fall back to their building — on a live tenant that is about a quarter of them, which is why the Floor column is optional and the Building column is required.
The space code defaults to the room number with the building prefix stripped (BAI 101 in building BAI → 101), since that bare number is what a CMMS/CAFM typically publishes. Named rooms are left intact rather than mangled.
Note: A space code is only written as an identity when the room's parent is a Floor (codes are scoped to a floor). A room that fell back to its building merges without the space-code anchor.
Saving a room is what creates its booking calendar. Only imported rooms get one, and only rooms with a calendar receive events — see Booking calendars below.
| Option | Default | Description |
|---|---|---|
| Data Sources | All three | Which Coursedog data to sync: Class schedule (course sections), Event bookings (event management), Final exams (exam meetings declared on sections). |
| Lookahead (days) | 30 | How far ahead the daily sync materializes bookings. Class meeting patterns are expanded one event per meeting day, so raising this multiplies the events written per run. |
Additional config-only options:
| Field | Default | Description |
|---|---|---|
| currentWindowDays | 7 | Days either side of now that the 30-minute poll refreshes event bookings. |
| includeSetupTeardown | true | Whether to sync the setup/teardown blocks Coursedog books around an event. They occupy the room, so they are included by default. |
| minRequestIntervalMs | 250 | Minimum spacing between API requests. |
| maxRetries | 6 | Retry attempts on a 429 or transient upstream error, with exponential backoff honoring Retry-After. |
| Function | Interval | What it syncs |
|---|---|---|
| Current Events | Every 30 minutes | Event bookings only, for a window of now ± 7 days. |
| Future Events | Once per day | The full sync: class schedule, event bookings and exams, from yesterday through the lookahead window. |
The 30-minute poll deliberately skips the class schedule. Coursedog's sections endpoint has no modified-since filter, so including it would mean re-downloading an entire term (tens of megabytes) every half hour. Classes change on registrar timescales, so the daily poll owns them, while event bookings — which are date-windowed and field-narrowable — stay fresh at 30-minute resolution.
The Backfill section imports historical room bookings for a specific date range on demand, pulling both sources so the range comes back complete. Only one backfill runs at a time. A long range covers more academic terms, and each term is a full download of its course sections, so expect a multi-minute run for a range spanning a year. Progress is reported in the connector logs.
| Coursedog API Model | Mapped Entity | exactType | Notes |
|---|---|---|---|
| Building | Building or Sub_Building | Building / Sub_Building | Named from the Coursedog display name. Imported as a Building isPartOf a user-selected org Site, or (when a Parent Building is chosen) as a Sub_Building isPartOf that Building. Carries a postal address when one is provided. |
| Room | Space | Space | isPartOf a user-selected Floor when set, otherwise isPartOf its Building/Sub_Building. |
| (per room, automatic) | SpaceBookingCalendar | Space_Booking_Calendar | One booking calendar per imported room, linked via hasCalendar. |
| Section meeting pattern (per meeting day) | CalendarEvent | Calendar_Event | One event per date the pattern meets. |
| Section exam meeting | CalendarEvent | Calendar_Event | Single-date, often in a different room than the class. |
| Event meeting | CalendarEvent | Calendar_Event | Already one record per occurrence in Coursedog. |
Relationships:
| GraphQL Field | Class occurrence | Event booking |
|---|---|---|
| name | ACCT20353-080 Fundamentals of Accounting | The parent event's name, prefixed **Setup: ** / **Teardown: ** for those blocks |
| description | Section type, delivery mode, topic, enrollment | Event type, organization, department, expected attendance, notes |
| startTime / endTime | The occurrence in UTC, converted from campus-local | The occurrence in UTC, converted from campus-local |
| callInfo | The section's status (Active, …) | The booking's status (Confirmed, Pending, …) |
| mappingKey | calendar_event/section/{sectionId}/{timeId}/{date} | calendar_event/meeting/{meetingId} |
| identities | urn:coursedog:section:id:{sectionId}/{timeId}/{date} (scope: ORG) | urn:coursedog:meeting:id:{meetingId} (scope: ORG) |
Query rooms with their calendars and events
Request ResponseCopy1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25{ spaces { id name exactType mappingKey hasCalendar { ... on SpaceBookingCalendar { id name exactType mappingKey hasCalendarEvent { id name exactType mappingKey description startTime endTime } } } } }
Query calendar events with location and identity
Request ResponseCopy1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24{ calendarEvents { id name startTime endTime mappingKey hasLocation { ... on Space { id name exactType mappingKey } } identities { ... on ExternalIdentity { __typename value scope } } } }
