These docs are for v1.0. Click to read the latest docs for v3-prod.
Fixed

OnSched 3.9.0 - reschedule controls, booking retention, and availability timezones

API

  • Silent reschedules: PUT /v3/appointment/{id}/reschedule now accepts skip_notifications: true in the request body. Use it for provider-only or other operational changes that should not send email or SMS to the customer, company, or assigned resources.
  • Integrations stay synchronized: Silent reschedules still emit the APPOINTMENT_RESCHEDULED webhook and refresh Google Calendar or Outlook events.
  • Backward compatible: Omitting the flag, or setting it to false, keeps existing reschedule notification behavior.

Appointment retention

  • Booked records cannot be permanently deleted: DELETE /v3/appointment/{id} rejects BK, CN, and RE appointments. Cancel booked appointments with PUT /v3/appointment/{id}/cancel so billing and lifecycle history remain available.
  • Hold cleanup remains available: Initial (IN) and reserved (RS) holds may still be permanently deleted.

Availability fix

  • Held slots stay out of availability: Holds created at a location without a booking timer were stored as already expired, so GET /v3/availability kept returning the held slot and a second hold or booking on that slot could succeed. Those holds now protect their slot.
  • No timer means no expiry: When a location has no positive expirationDelay, a hold does not expire on its own; book it or delete it to release the slot. Set a positive expirationDelay to keep automatic release for abandoned checkouts.

Availability timezones

  • Location wins for weekly hours: GET /v3/availability converts weekly schedule and allocation wall-clock times using the request location timezone (and resource timezone when applicable), not a frozen iana stamped when the schedule was saved under a different company or sibling location timezone.
  • Multi-location company-scoped services: An 08:00–20:00 weekly allocation at a Pacific location now opens at 15:00Z during PDT even when company timezone or saved schedule rows are Eastern.

Clearer errors

  • Resource problems say so: Booking, holding, reserving, rescheduling, or validating resources with a ResourceIds entry that is not one of your resources — or is not linked to the requested location and service — now returns 400 with a message naming that resource id. These requests previously reported the time slot as unavailable.
  • POST /v3/customer validates LocationId: An unknown location returns 400 naming the id instead of 500 Something went wrong.
  • Missing path ids are rejected as bad requests: DELETE /v3/customer/ with no id returns 400 Customer id is required.
  • 400 for payload ids, 404 for path ids: An unknown LocationId or ServiceId sent to the appointment create endpoints, and an unknown LocationId filter on GET /v3/customers, now return 400 instead of 404. 404 means the record addressed in the URL path does not exist. Update any integration branching on 404 for those payload errors.
  • Unmatched routes return JSON: A request to an unknown path returns the standard { "success": false, "message": ..., "errors": [] } body instead of an HTML page.
  • No 422 responses: The error reference previously listed 422 Unprocessable Entity for slot conflicts and unlinked resources. The API has always returned 400 for those; the documentation now matches. See Error Codes.