Calendar
Calendars, events, agenda, ICS export, event invitations and the public RSVP flow.
17 endpoints· 3 called live· verified against http://127.0.0.1:8741
17 endpoints
GET/api/v1/salesshift/calendar/agendaCalled liveFlat, sorted list of what is coming up — events and bookings together.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| days | integer | optional | Default 14. min 1. max 180. |
| q | string? | optional |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendar/agenda' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"items": [
{
"source": "...",
"id": "...",
"master_id": "...",
"calendar_id": "...",
"owner_id": "...",
"title": "...",
"description": "...",
"location": "...",
"meeting_url": "...",
"start_at": "...",
"end_at": "...",
"all_day": "...",
"timezone": "...",
"color": "...",
"status": "...",
"transparency": "...",
"recurrence_rule": "...",
"recurring_event_id": "...",
"original_start_at": "...",
"exdates": "...",
"attendees": "...",
"reminders": "...",
"contact_id": "...",
"deal_id": "...",
"is_recurring": "...",
"is_occurrence": "...",
"is_override": "...",
"occurrence_start": "...",
"sequence": "...",
"organizer_email": "...",
"organizer_name": "...",
"invites_sent_at": "...",
"created_at": "...",
"updated_at": "..."
},
"...x6"
],
"days": "int",
"window": {
"start": "str",
"end": "str"
}
}
}GET/api/v1/salesshift/calendar/eventsCalled liveEverything overlapping [start, end): recurring series expanded into occurrences, detached overrides applied, plus guest bookings.
Everything overlapping [start, end): recurring series expanded into occurrences, detached overrides applied, plus guest bookings.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| start | string? | optional | ISO-8601 window start |
| end | string? | optional | ISO-8601 window end |
| calendar_ids | string? | optional | comma-separated calendar ids |
| q | string? | optional | text search |
| include_bookings | boolean | optional | Default true. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendar/events' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"events": [
{
"source": "...",
"id": "...",
"master_id": "...",
"calendar_id": "...",
"owner_id": "...",
"title": "...",
"description": "...",
"location": "...",
"meeting_url": "...",
"start_at": "...",
"end_at": "...",
"all_day": "...",
"timezone": "...",
"color": "...",
"status": "...",
"transparency": "...",
"recurrence_rule": "...",
"recurring_event_id": "...",
"original_start_at": "...",
"exdates": "...",
"attendees": "...",
"reminders": "...",
"contact_id": "...",
"deal_id": "...",
"is_recurring": "...",
"is_occurrence": "...",
"is_override": "...",
"occurrence_start": "...",
"sequence": "...",
"organizer_email": "...",
"organizer_name": "...",
"invites_sent_at": "...",
"created_at": "...",
"updated_at": "..."
},
"...x15"
],
"bookings": [
"<empty list>"
],
"window": {
"start": "str",
"end": "str"
}
}
}Errors
| Status | detail |
|---|---|
| 400 | end must be after start |
| 400 | Window too wide (max {...} days) |
| 400 | Invalid calendar id {...} |
POST/api/v1/salesshift/calendar/eventsVerified in sessionCreate a calendar event, defaulting to the org's default calendar.
Request body (required) — EventCreate
| Field | Type | Required | Notes |
|---|---|---|---|
| title | string | required | ≤ 300 chars. |
| start_at | string(date-time) | required | |
| end_at | string(date-time) | required | |
| description | string? | optional | |
| location | string? | optional | |
| meeting_url | string? | optional | |
| all_day | boolean | optional | Default false. |
| timezone | string? | optional | |
| color | string | optional | Default "primary". ≤ 20 chars. |
| status | string | optional | Default "confirmed". ≤ 20 chars. |
| transparency | string | optional | Default "busy". ≤ 10 chars. |
| recurrence_rule | string? | optional | |
| attendees | object[]? | optional | |
| reminders | integer[]? | optional | |
| contact_id | string(uuid)? | optional | |
| deal_id | string(uuid)? | optional | |
| calendar_id | string(uuid)? | optional | |
| send_invites | boolean | optional | Default true. |
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/calendar/events' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "title": "<string>", "start_at": "<string(date-time)>", "end_at": "<string(date-time)>", "description": "<string>", "location": "<string>", "meeting_url": "<string>", "all_day": false, "timezone": "<string>", "color": "primary", "status": "confirmed", "transparency": "busy", "recurrence_rule": "<string>", "attendees": [ "<object>" ], "reminders": [ "<integer>" ], "contact_id": "<string(uuid)>", "deal_id": "<string(uuid)>", "calendar_id": "<string(uuid)>", "send_invites": true }'Response · 201
{success, data: <event>} plus `invitations` when invites were attempted.
GET/api/v1/salesshift/calendar/events/{event_id}Verified in sessionOne event plus the shape of the series it belongs to.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}PATCH/api/v1/salesshift/calendar/events/{event_id}Verified in sessionPartial update with Google's recurring-edit scopes.
Partial update with Google's recurring-edit scopes. * ``all`` — edit the master; every occurrence follows. * ``this`` — detach the clicked instance into its own row (RECURRENCE-ID) and EXDATE it out of the master. * ``following`` — end the master with UNTIL just before the instance and start a fresh series from it, carrying over the remaining COUNT, the later EXDATEs and the later exceptions.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| scope | string | optional | Default "all". Matches ^(this|following|all)$. |
| occurrence_start | string? | optional | ISO start of the clicked instance |
Request body (required) — EventPatch
| Field | Type | Required | Notes |
|---|---|---|---|
| title | string? | optional | |
| start_at | string(date-time)? | optional | |
| end_at | string(date-time)? | optional | |
| description | string? | optional | |
| location | string? | optional | |
| meeting_url | string? | optional | |
| all_day | boolean? | optional | |
| timezone | string? | optional | |
| color | string? | optional | |
| status | string? | optional | |
| transparency | string? | optional | |
| recurrence_rule | string? | optional | |
| attendees | object[]? | optional | |
| reminders | integer[]? | optional | |
| contact_id | string(uuid)? | optional | |
| deal_id | string(uuid)? | optional | |
| calendar_id | string(uuid)? | optional | |
| occurrence_start | string(date-time)? | optional | |
| send_invites | boolean? | optional |
Values in the request below are typed placeholders, not sample data.
Request
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "title": "<string>", "start_at": "<string(date-time)>", "end_at": "<string(date-time)>", "description": "<string>", "location": "<string>", "meeting_url": "<string>", "all_day": false, "timezone": "<string>", "color": "<string>", "status": "<string>", "transparency": "<string>", "recurrence_rule": "<string>", "attendees": [ "<object>" ], "reminders": [ "<integer>" ], "contact_id": "<string(uuid)>", "deal_id": "<string(uuid)>", "calendar_id": "<string(uuid)>", "occurrence_start": "<string(date-time)>", "send_invites": false }'Response · 200
{success, data: <event>} plus `invitations` when invites were attempted.
DELETE/api/v1/salesshift/calendar/events/{event_id}Verified in sessionDelete with the same three scopes as the update path.
Delete with the same three scopes as the update path. * ``all`` — drop the series (exceptions cascade through the self-FK). * ``this`` — EXDATE the instance and remove its exception row, if any. * ``following`` — UNTIL the master just before the instance and drop everything on the far side of the split.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| scope | string | optional | Default "all". Matches ^(this|following|all)$. |
| occurrence_start | string? | optional | ISO start of the clicked instance |
Request
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"deleted": "…",
"scope": "…",
"success": "…"
}POST/api/v1/salesshift/calendar/events/{event_id}/duplicateVerified in sessionCopy at the same time with a ' (copy)' suffix.
Copy at the same time with a ' (copy)' suffix. The copy is standalone — duplicating an exception must not graft a second row onto the series.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}/duplicate' \
-H "Authorization: Bearer $SS_TOKEN"Response · 201
{
"data": "…",
"success": "…"
}POST/api/v1/salesshift/calendar/events/{event_id}/inviteVerified in sessionSend or re-send the invitation.
Send or re-send the invitation. Reports per recipient — a bounce is not an error for the whole request, it is a fact about one address.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Request body (optional)
Accepts a JSON object; the source declares no field list.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}/invite' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"email_sent": "…",
"error": "…",
"failed": "…",
"method": "…",
"results": "…",
"sent": "…",
"success": "…"
}GET/api/v1/salesshift/calendar/events/{event_id}/invitesVerified in sessionWho was invited, what they answered, and the two deep links that let the organiser put the same event in their own external calendar.
Who was invited, what they answered, and the two deep links that let the organiser put the same event in their own external calendar.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}/invites' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}POST/api/v1/salesshift/calendar/events/{event_id}/invitesVerified in sessionSend or re-send the invitation.
Send or re-send the invitation. Reports per recipient — a bounce is not an error for the whole request, it is a fact about one address.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| event_id | string(uuid) | required |
Request body (optional)
Accepts a JSON object; the source declares no field list.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/calendar/events/{event_id}/invites' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"email_sent": "…",
"error": "…",
"failed": "…",
"method": "…",
"results": "…",
"sent": "…",
"success": "…"
}GET/api/v1/salesshift/calendar/export.icsin-handler-authVerified in sessionRFC-5545 calendar file.
RFC-5545 calendar file. Recurring series are exported as a single VEVENT carrying RRULE/EXDATE and their exceptions as sibling VEVENTs sharing the UID with a RECURRENCE-ID — that is the iCalendar model, so importers re-derive the same occurrences we render rather than receiving a flattened dump. ``token`` exists because this URL is opened directly by the browser (no Authorization header possible); the normal header credentials win when both are present.
NOT public. The handler calls get_org_user itself, accepting the normal Authorization / X-API-Key headers, plus a ?token=<jwt> query fallback because a browser opening the URL directly cannot set a header. Headers win when both are sent.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| start | string? | optional | |
| end | string? | optional | |
| token | string? | optional | JWT, for a plain browser download |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendar/export.ics' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
Response with the ICS calendar body (text/calendar).
Errors
| Status | detail |
|---|---|
| 400 | end must be after start |
GET/api/v1/salesshift/calendar/rsvp/{token}url-secret-onlyVerified in sessionThe page an attendee lands on from the invitation.
The page an attendee lands on from the invitation. ``?response=`` records the answer on the spot: Outlook and several mobile clients follow a mailed link with a GET only, and an RSVP that silently does nothing is worse than the prefetch risk of honouring it.
The invitation token is the credential and identifies the guest.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| token | string | required |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| response | string? | optional | accepted | declined | tentative |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendar/rsvp/{token}'Response · 200
Returns text/html (html).
POST/api/v1/salesshift/calendar/rsvp/{token}url-secret-onlyVerified in sessionRecord the reply.
Record the reply. Accepts the HTML form above and a JSON body equally — the same link is used by a browser and by API clients.
The invitation token is the credential and identifies the guest.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| token | string | required |
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/calendar/rsvp/{token}'Response · 200
Returns text/html (html).
GET/api/v1/salesshift/calendarsCalled liveThe organization's calendars, seeding a default one when none exist.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/calendars' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": [
{
"id": "str",
"name": "str",
"color": "str",
"is_visible": "bool",
"is_default": "bool",
"owner_id": "int",
"created_at": "str",
"updated_at": "str"
},
"...x1"
]
}POST/api/v1/salesshift/calendarsVerified in sessionCreate a calendar; the org's first calendar is always its default.
Request body (required) — CalendarCreate
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | ≤ 200 chars. |
| color | string | optional | Default "primary". ≤ 20 chars. |
| is_visible | boolean | optional | Default true. |
| is_default | boolean | optional | Default false. |
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/calendars' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "<string>", "color": "primary", "is_visible": true, "is_default": false }'Response · 201
{
"data": "…",
"success": "…"
}PATCH/api/v1/salesshift/calendars/{calendar_id}Verified in sessionUpdate a calendar's fields.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| calendar_id | string(uuid) | required |
Request body (required) — CalendarPatch
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string? | optional | |
| color | string? | optional | |
| is_visible | boolean? | optional | |
| is_default | boolean? | optional |
Values in the request below are typed placeholders, not sample data.
Request
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/calendars/{calendar_id}' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "<string>", "color": "<string>", "is_visible": false, "is_default": false }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Calendar not found |
DELETE/api/v1/salesshift/calendars/{calendar_id}Verified in sessionEvents survive — ss_calendar_events.calendar_id is ON DELETE SET NULL.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| calendar_id | string(uuid) | required |
Request
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/calendars/{calendar_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Calendar not found |
| 400 | The default calendar cannot be deleted — make another one default first |