Documentation

Calendar Events

Reference for the calendar_events resource. Requests follow the conventions in Requests and Responses; fields you receive and may write are filtered by your user's permissions, so responses can contain a subset of the fields below.

Operations

Operation Request
List GET /{profile}/user/v4/calendar_events
Schedule a tech or sales appointment for a customer POST /{profile}/user/v4/calendar_events/schedule
Reschedule an appointment (new start time, optional audit record) POST /{profile}/user/v4/calendar_events/reschedule
Cancel (delete) an appointment POST /{profile}/user/v4/calendar_events/cancel
List users who can take an appointment, with optional occupancy POST /{profile}/user/v4/calendar_events/available_users
List configured tech time slots that are open for a customer POST /{profile}/user/v4/calendar_events/available_slots

Not available as a standard REST operation for this resource: create, update, delete — such requests return 402 feature_not_enabled or 403 permission_denied (see the actions above for this resource's write path).

How it works

calendar_events are appointments — one table holding both tech appointments (calendar_category: tech_schedule: installs, service visits, removals) and sales appointments (calendar_category: sale_schedule). The table has a composite key (id, calendar_category), so records are not addressed at /{id}; instead, appointments of both kinds are managed through collection actions. schedule, reschedule, and cancel take the appointment id (or, for schedule, the calendar_category) in the body. available_users and available_slots are read-only lookups (HTTP 200) for who can take a job and, when the company uses time-slot scheduling, which configured slots are open. Resolve calendar_event_type_id from calendar event types before scheduling. Record a confirmation through calendar event confirmations.

Permissions follow the SecurityTrax scheduler:

  • Tech appointments need the Scheduler permission at the customer's location (create / modify / delete for schedule / reschedule / cancel). Your own appointments are always visible.
  • Sales appointments need the Sale Scheduler permission, or Assign Sale Schedule To Self — in which case you may only schedule appointments assigned to yourself.

Scheduling a tech appointment

curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/schedule" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"customer_id":1001,"user_id":42,"calendar_event_type_id":1,"customer_note_id":5005,"start_time":1767290400,"duration":7200,"notes":"Bring the replacement panel"}}}'

calendar_category defaults to tech_schedule.

Field Required Notes
customer_id Yes The customer. Leads are rejected for tech appointments — leads use the sales scheduler.
calendar_event_type_id Yes An active tech service type from calendar event types (install / service / removal as configured by your company). Time Off cannot be scheduled through the API.
start_time Yes Unix timestamp or a date-time string (e.g. 2026-08-03 10:00:00).
duration Yes Seconds; must be a multiple of 1800 (30-minute increments) and may not run past 11:30 PM.
user_id No The tech to assign; the user must hold the tech role. Omit to leave unassigned.
calendar_event_detail_type_id No Service detail type (must belong to the tech scheduler).
customer_note_id No* The work order to link — must be a work order belonging to this customer. *Required when the company setting "appointments require a work order" is on.
notes, user_notes No Appointment notes / notes for the assigned tech.

Scheduling a sales appointment

Pass calendar_category: sale_schedule:

curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/schedule" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"calendar_category":"sale_schedule","customer_id":1001,"user_id":42,"calendar_event_type_id":1,"start_time":1767290400,"duration":3600}}}'
Field Required Notes
customer_id Yes A lead always, or a customer when your company shows the sales scheduler on customers.
calendar_event_type_id Yes An active sale visit type from calendar event types.
start_time, duration Yes Same rules as tech appointments.
user_id No The sales rep to assign. With only Assign Sale Schedule To Self, this must be your own user id (and an unassigned appointment is not allowed).
notes, user_notes No Appointment notes / notes for the assigned rep.

Sales appointments cannot link a work order (customer_note_id is rejected).

Scheduling through the API runs the same platform side effects as scheduling in SecurityTrax (appointment notifications, remote system sync where configured).

Note. schedule and reschedule perform no double-booking check — like the other integration surfaces, they will happily schedule someone into an occupied window. Use available_users with a time window (or GET /calendar_events?user_id=42&start_from=...&start_to=...) if overlap matters to your flow.

Rescheduling

curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/reschedule" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"id":314,"start_time":1767376800,"initiated_by":"c","reschedule_reason_id":2}}}'

Works for both tech and sales appointments (the id resolves the kind). start_time is required (unix timestamp or date-time string); pass duration only to change the length. initiated_by (c = customer, d = dealer/company) is optional — when provided and the company tracks reschedules, a reschedule audit record (old time, new time, reason, who initiated) is written alongside the move, exactly as the SecurityTrax scheduler does.

Canceling

curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/cancel" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"id":314}}}'

Deletes the appointment from the schedule. A linked work order is not closed or unlinked — it simply no longer has this appointment.

Listing appointments

Filters: customer_id, user_id (the assigned tech/rep), calendar_category (tech_schedule / sale_schedule), calendar_event_type_id, customer_note_id (work order), and a start-time window via start_from / start_to (unix timestamps). Sort by id, customer_id, user_id, start_time, duration, or created_at (default start_time, newest first); ?count_only=true for the total.

# A tech's appointments for one day
curl "https://portal.securitytrax.com/acme/user/v4/calendar_events?user_id=42&start_from=1767250800&start_to=1767337199" \
  -H "Authorization: Bearer stx_acme_..."

Who can take the job

POST /calendar_events/available_users returns the techs or sales reps who can be assigned for this customer (the same lists the SecurityTrax scheduler uses), as a slim { user_id, name, fname, lname, eligible } row — not a full users resource. name is Last, First (the same as a user's display name in SecurityTrax). This is a query, not a create: HTTP 200, and the payload is in data (same envelope as a fetch, not meta.data).

# Eligible techs at the customer's office location
curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/available_users" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"customer_id":1001}}}'
{
  "ok": true,
  "data": {
    "users": [
      {"user_id": 42, "name": "Doe, Jane", "fname": "Jane", "lname": "Doe", "eligible": true}
    ],
    "list_mode": "location"
  },
  "summary": null,
  "breadcrumbs": [],
  "meta": {"surface": "api", "action": "available_users"},
  "errors": []
}
# Specific users, with occupancy for a day
curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/available_users" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"customer_id":1001,"user_ids":[42,87],"list_mode":"in_coverage_area","start_from":1767250800,"start_to":1767337199}}}'
Field Required Notes
customer_id Yes The customer. For sales (sale_schedule), a lead always, or a customer when your company shows the sales scheduler on customers. A customer you cannot see is 404.
calendar_category No tech_schedule (default) or sale_schedule. Tech + lead is rejected.
user_ids No Array of user ids. Omit or send [] for the full eligible list. When present, only those ids are returned, each with eligible true/false. Unknown / deleted ids are 422. Max 100.
list_mode No Tech only. location, in_coverage_area, or out_coverage_area (v3 aliases all / coverage_radius / max_coverage_radius also accepted). Omit for the company default. Coverage modes require coverage-area views and a geocoded customer — otherwise 422 (not silently coerced). Ignored for sales.
start_from + start_to No Occupancy window (unix or date-time string). Both required if either is sent. Max 31 days.
start_time + duration No Alternative occupancy window: start (unix or date-time string) plus length in seconds. Both required if either is sent. Same 31-day cap.

When a window is sent, each user also has busy, includes_time_off, and conflicts (id, category, start, duration, type — no customer_id). Occupancy looks at the assignee's whole calendar, including time off. No window → those keys are omitted. The response echoes the resolved list_mode (tech only) and the window when one was sent. Timestamps out are unix ints.

Permissions match scheduling: Scheduler create at the customer for tech; Sale Scheduler or Assign Sale Schedule To Self for sales. With only self-assign, omitted user_ids returns you alone; a foreign id is 422.

Open time slots (time-slot scheduling only)

POST /calendar_events/available_slots lists the company's configured tech windows that are open for this customer — the same capacity math as one page of the slot picker. A start_from + start_to window is required and may not be longer than the company's days-to-show-per-page setting (hard-capped at 31). Companies that do not use time-slot scheduling get 422 slot_scheduler_not_enabled (this does not invent 30-minute slots). Sales appointments do not use slots.

curl -X POST "https://portal.securitytrax.com/acme/user/v4/calendar_events/available_slots" \
  -H "Authorization: Bearer stx_acme_..." \
  -H "Content-Type: application/json" \
  -d '{"data":{"attributes":{"customer_id":1001,"start_from":1767250800,"start_to":1767855600}}}'
Field Required Notes
customer_id Yes A geocoded customer (not a lead). Hidden → 404; ungeocoded → 422.
calendar_category No Must be tech_schedule (default). sale_schedule is 422.
include_unavailable No Default false (available-only). true also returns configured slots that are already full, each with available: false.
start_from + start_to Yes Slice of the bookable horizon (unix or date-time string). End must be after start. May not exceed this company's days to show per page (total_days_to_show, hard-capped at 31). Capacity is checked only for configured windows that overlap this range. Days past the booking horizon still return no slots. The response echoes the window.

Response data is { slots: [{ start_time, end_time, available }] } (HTTP 200, same query envelope as available_users). Same-day-disabled windows and days past the booking horizon are omitted entirely. Needs Scheduler create at the customer.

Fields

Fields are grouped by the permission that gates them. A group you may not view is absent from responses; a group you may not write is rejected with 422 when sent in a write.

Tech Appointment

View: customers — the standard canViewTechSchedule rules; leads — Lead Scheduler. Create: customers — Scheduler at the record's location. Update: customers — Scheduler at the record's location.

Field Type Writable Validation
calendar_category string (nullable) Create only one of: tech_schedule, sale_schedule
user_id integer (nullable) Create, update min 0
customer_note_id integer (nullable) Create, update min 0
customer_id integer (nullable) Create only min 0
calendar_event_type_id integer (nullable) Create, update min 0
calendar_event_detail_type_id integer (nullable) Create, update min 0
recurring_id integer (nullable) Create, update min 0
start_time string (nullable) Create, update min length 0
duration integer (nullable) Create, update min 0
notes string (nullable) Create, update
user_notes string (nullable) Create, update
remote_unique_id string (nullable) Create, update max length 255
work_order_number string (nullable) Create, update max length 255
dry_run_reason_id integer (nullable) Create, update min 0
interactive_services_id integer (nullable) Create, update max 255
status string (nullable) Read-only one of: active, deleted
created_at string (nullable) Read-only
created_by integer (nullable) Read-only
updated_at string (nullable) Read-only
updated_by integer (nullable) Read-only

Sales Appointment

View: any of: Sale Scheduler; Assign Sale Schedule To Self. Create: any of: Sale Scheduler; Assign Sale Schedule To Self. Update: the standard canModifySaleSchedulerAppointment rules.

Field Type Writable Validation
calendar_category string (nullable) Create only one of: tech_schedule, sale_schedule
user_id integer (nullable) Create, update min 0
customer_note_id integer (nullable) Create, update min 0
customer_id integer (nullable) Create only min 0
calendar_event_type_id integer (nullable) Create, update min 0
calendar_event_detail_type_id integer (nullable) Create, update min 0
recurring_id integer (nullable) Create, update min 0
start_time string (nullable) Create, update min length 0
duration integer (nullable) Create, update min 0
notes string (nullable) Create, update
user_notes string (nullable) Create, update
remote_unique_id string (nullable) Create, update max length 255
work_order_number string (nullable) Create, update max length 255
dry_run_reason_id integer (nullable) Create, update min 0
interactive_services_id integer (nullable) Create, update max 255
status string (nullable) Read-only one of: active, deleted
created_at string (nullable) Read-only
created_by integer (nullable) Read-only
updated_at string (nullable) Read-only
updated_by integer (nullable) Read-only

Pagination

The list endpoint uses client-controlled offset pagination: ?page= (1-based) and ?per_page= (default 25, max 100). The response mirrors meta.pagination (page, per_page, total, last_page) and sends an RFC5988 Link header; follow rel="next" to walk pages. See Pagination.

Filters

The list endpoint accepts these query-param filters: customer_id, user_id, calendar_category, calendar_event_type_id, customer_note_id, start_from, start_to. An unsupported filter parameter returns 422. See Filtering collections for matching semantics.

Sorting

GET .../calendar_events?sort= orders the list by: id, customer_id, user_id, start_time, duration, created_at. Prefix a field with - for descending; comma-separate for tie-breakers. An unsupported field returns 422. See Sorting collections.

Related

Ask about the docs
Ask about the docs
Answers from the SecurityTrax documentation

Ask about a feature, setting, or workflow.

Answers come from the documentation. Double-check anything important. AI features are subject to the AI Terms.