Class: Basecamp::Services::SchedulesService

Inherits:
BaseService
  • Object
show all
Defined in:
lib/basecamp/generated/services/schedules_service.rb

Overview

Service for Schedules operations

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from Basecamp::Services::BaseService

Instance Method Details

#create_entry(schedule_id:, summary:, starts_at:, ends_at:, description: nil, participant_ids: nil, all_day: nil, notify: nil, url: nil, highlighted: nil, status: nil, subscriptions: nil, visible_to_clients: nil) ⇒ Hash

Create a new schedule entry

Parameters:

  • schedule_id (Integer)

    schedule id ID

  • summary (String)

    summary

  • starts_at (String)

    The entry's start, as a bare date ("2026-06-01") for an all-day entry or a full timestamp ("2026-06-01T09:00:00Z") otherwise — the same two forms the response renders, and the same two ReplaceScheduleEntry accepts.

    Create and replace share one permit list: Schedules::Entries::BaseController#base_schedule_entry_params is what both new_schedule_entry_params and update_schedule_entry_params call, and Schedule::Entry does no format-specific parsing of either bound, so whatever one operation takes the other takes too.

    Treat the value as opaque and send it verbatim. Parsing it into a date-time type and re-rendering rewrites an all-day entry's bounds into midnight timestamps, which is why every SDK models it as a string.

  • ends_at (String)

    The entry's end. See starts_at for the date-vs-timestamp rule.

  • description (String, nil) (defaults to: nil)

    description

  • participant_ids (Array, nil) (defaults to: nil)

    participant ids

  • all_day (Boolean, nil) (defaults to: nil)

    all day

  • notify (Boolean, nil) (defaults to: nil)

    notify

  • url (String, nil) (defaults to: nil)

    The entry's join link — a video-call URL or similar, up to 2500 characters, validated as a URL when present. A scheme-less value is normalized to https://.

    Spell it url on the way in and read it back as join_url: the response key url is the entry's own Basecamp API URL, written by a partial that renders before this field, so BC3 emits the join link under a non-colliding name. Sending join_url instead is silently dropped by strong parameters — the create succeeds with no join link.

    Accepted on create since long before it was documented: Schedules::Entries::BaseController#base_schedule_entry_params permits it and new_schedule_entry_params passes it through unchanged for API requests. Modeling it only on ReplaceScheduleEntry forced callers into a three-request read-modify-write for a field the create already took — and create is the notifying write, so participants learned about a video call before its link existed.

  • highlighted (Boolean, nil) (defaults to: nil)

    Whether the entry is highlighted on the schedule. Defaults to false.

    Do not send an explicit null: schedule_entries.highlighted is NOT NULL, so BC3 raises rather than falling back to the default. Omit it instead — every SDK's request compactor already drops unset members.

  • status (String, nil) (defaults to: nil)

    Publication state at creation — active|drafted, defaulting to active for an API create.

    A top-level parameter, not part of the entry's attributes: status is a Recording column, so wrap_parameters leaves it outside the schedule_entry envelope and Recording::StatusParam#status_param reads it directly. On create it accepts drafted, active, archived or trashed and raises ActionController::BadRequest — a 400, not a 422 — for anything else; the two documented values are the two worth sending.

    Unlike messages and documents, schedule-entry drafts are not listed by GetMyDrafts.

  • subscriptions (Array, nil) (defaults to: nil)

    subscriptions

  • visible_to_clients (Boolean, nil) (defaults to: nil)

    visible to clients

Returns:

  • (Hash)

    response data



169
170
171
172
173
# File 'lib/basecamp/generated/services/schedules_service.rb', line 169

def create_entry(schedule_id:, summary:, starts_at:, ends_at:, description: nil, participant_ids: nil, all_day: nil, notify: nil, url: nil, highlighted: nil, status: nil, subscriptions: nil, visible_to_clients: nil)
  with_operation(service: "schedules", operation: "create_entry", is_mutation: true, resource_id: schedule_id) do
    http_post("/schedules/#{schedule_id}/entries.json", body: compact_params(summary: summary, starts_at: starts_at, ends_at: ends_at, description: description, participant_ids: participant_ids, all_day: all_day, notify: notify, url: url, highlighted: highlighted, status: status, subscriptions: subscriptions, visible_to_clients: visible_to_clients)).json
  end
end

#get(schedule_id:) ⇒ Hash

Get a schedule

Parameters:

  • schedule_id (Integer)

    schedule id ID

Returns:

  • (Hash)

    response data



82
83
84
85
86
# File 'lib/basecamp/generated/services/schedules_service.rb', line 82

def get(schedule_id:)
  with_operation(service: "schedules", operation: "get", is_mutation: false, resource_id: schedule_id) do
    http_get("/schedules/#{schedule_id}", operation: "GetSchedule").json
  end
end

#get_entry(entry_id:) ⇒ Hash

Get a single schedule entry by id.

Parameters:

  • entry_id (Integer)

    entry id ID

Returns:

  • (Hash)

    response data



13
14
15
16
17
# File 'lib/basecamp/generated/services/schedules_service.rb', line 13

def get_entry(entry_id:)
  with_operation(service: "schedules", operation: "get_entry", is_mutation: false, resource_id: entry_id) do
    http_get("/schedule_entries/#{entry_id}", operation: "GetScheduleEntry").json
  end
end

#get_entry_occurrence(entry_id:, date:) ⇒ Hash

Get a specific occurrence of a recurring schedule entry

Parameters:

  • entry_id (Integer)

    entry id ID

  • date (String)

    date ID

Returns:

  • (Hash)

    response data



73
74
75
76
77
# File 'lib/basecamp/generated/services/schedules_service.rb', line 73

def get_entry_occurrence(entry_id:, date:)
  with_operation(service: "schedules", operation: "get_entry_occurrence", is_mutation: false, resource_id: entry_id) do
    http_get("/schedule_entries/#{entry_id}/occurrences/#{date}", operation: "GetScheduleEntryOccurrence").json
  end
end

#list_entries(schedule_id:, status: nil, page: nil, max_items: nil) ⇒ ListEnumerator<Hash>

List entries on a schedule

Parameters:

  • schedule_id (Integer)

    schedule id ID

  • status (String, nil) (defaults to: nil)

    active|archived|trashed

  • page (Integer, nil) (defaults to: nil)

    Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8.

  • max_items (Integer, nil) (defaults to: nil)

    cap on items yielded across pages; nil or non-positive means no cap

Returns:

  • (ListEnumerator<Hash>)

    lazily paginated results (#meta carries pagination metadata)



104
105
106
107
108
109
# File 'lib/basecamp/generated/services/schedules_service.rb', line 104

def list_entries(schedule_id:, status: nil, page: nil, max_items: nil)
  wrap_paginated(service: "schedules", operation: "list_entries", is_mutation: false, resource_id: schedule_id) do
    params = compact_query_params(status: status, page: page)
    paginate("/schedules/#{schedule_id}/entries.json", params: params, operation: "ListScheduleEntries", max_items: max_items)
  end
end

#replace_entry(entry_id:, starts_at:, ends_at:, summary: nil, description: nil, participant_ids: nil, all_day: nil, notify: nil, url: nil, highlighted: nil) ⇒ Hash

Replace a schedule entry with a new complete representation.

Parameters:

  • entry_id (Integer)

    entry id ID

  • summary (String, nil) (defaults to: nil)

    summary

  • starts_at (String)

    The entry's start, as a bare date ("2026-06-01") for an all-day entry or a full timestamp otherwise. Same rule as CreateScheduleEntry: send it verbatim, never parsed and re-rendered.

  • ends_at (String)

    The entry's end. See starts_at for the date-vs-timestamp rule.

  • description (String, nil) (defaults to: nil)

    description

  • participant_ids (Array, nil) (defaults to: nil)

    Replaces the entry's participants.

    Omitting this member preserves the current participants; sending an empty array clears them. That guarantee is BC3-side and recent: until basecamp/bc3#12425, Schedules::EntriesController#update called replace_participants unconditionally, so any update omitting the key — including the shape in BC3's own "Update a schedule entry" doc example — silently removed every participant and notified each one. The controller now guards on the request actually addressing participants.

  • all_day (Boolean, nil) (defaults to: nil)

    Whether the entry occupies whole days rather than a time range.

    Not carved out, and the carve-out list is what makes that dangerous to forget: schedule_entries.all_day is NOT NULL with a false default, so omitting this member on a replace resets it — silently converting an all-day entry into a midnight-to-midnight timed one. The SDK's merge-safe update and edit resend it from the read-back for exactly this reason.

    Sending an explicit null is worse than omitting it: the column rejects NULL, so BC3 raises rather than falling back to the default. The same is true of highlighted.

  • notify (Boolean, nil) (defaults to: nil)

    notify

  • url (String, nil) (defaults to: nil)

    The entry's join link — a video-call URL or similar, up to 2500 characters, validated as a URL when present.

    Omitting this member preserves the current join link; sending an empty string clears it. Read it back as join_url, never as url: the entry's url is its own Basecamp API URL, written by a partial that renders before this one, so BC3 emits the join link under a non-colliding key. Echoing the response's url into this member would write the API URL into the join link.

  • highlighted (Boolean, nil) (defaults to: nil)

    Whether the entry is highlighted on the schedule.

    Omitting this member preserves the current highlight; sending false removes it. Preserved on omission because until basecamp/bc3#12502 the field was writable but never returned, so no caller could resend it.

Returns:

  • (Hash)

    response data



63
64
65
66
67
# File 'lib/basecamp/generated/services/schedules_service.rb', line 63

def replace_entry(entry_id:, starts_at:, ends_at:, summary: nil, description: nil, participant_ids: nil, all_day: nil, notify: nil, url: nil, highlighted: nil)
  with_operation(service: "schedules", operation: "replace_entry", is_mutation: true, resource_id: entry_id) do
    http_put("/schedule_entries/#{entry_id}", body: compact_params(summary: summary, starts_at: starts_at, ends_at: ends_at, description: description, participant_ids: participant_ids, all_day: all_day, notify: notify, url: url, highlighted: highlighted)).json
  end
end

#update_settings(schedule_id:, include_due_assignments:) ⇒ Hash

Update schedule settings

Parameters:

  • schedule_id (Integer)

    schedule id ID

  • include_due_assignments (Boolean)

    include due assignments

Returns:

  • (Hash)

    response data



92
93
94
95
96
# File 'lib/basecamp/generated/services/schedules_service.rb', line 92

def update_settings(schedule_id:, include_due_assignments:)
  with_operation(service: "schedules", operation: "update_settings", is_mutation: true, resource_id: schedule_id) do
    http_put("/schedules/#{schedule_id}", body: compact_params(include_due_assignments: include_due_assignments)).json
  end
end