Skip to content
Go to app

Calendars

Open in ChatGPT

A calendar is a subscribe calendar with its own feed, subscribe page and button. Many websites need exactly one; you can also create one per category or venue.

FieldTypeRulesDefault
namestringRequired on create, 1 to 100 characters
timezonestringRequired on create, IANA name such as America/New_York
descriptionstring or nullup to 1,000 charactersnull
site_urlstring or nullhttps:// URL, up to 2,000 charactersnull
languagede or enLanguage of the subscribe pageen
default_durationstringISO 8601 duration up to PT24H, e.g. PT1H, PT90M, PT1H30M. Used for events without end.PT1H
brand_colorstring or nullHex color #rrggbb, stored in lower casenull
organizerobject or nullname (required, up to 100 characters), url (https://, optional), email (optional). Public on the subscribe page.null
show_eventsbooleanShow upcoming events on the subscribe pagetrue

Unknown fields are refused with 400 invalid_request.

Terminal window
curl https://api.kalender-sync.de/v1/publisher/calendars \
-H "Authorization: Bearer $KS_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 3b0f6a52-6a1e-4c55-9d1b-0a7f2c9e1d44" \
-d '{
"name": "Riverside Yoga",
"timezone": "America/New_York",
"language": "en",
"site_url": "https://example.org",
"default_duration": "PT1H",
"brand_color": "#0f766e",
"organizer": { "name": "Riverside Yoga", "url": "https://example.org", "email": "info@example.org" },
"show_events": true
}'

Response 201 Created with the full calendar (see below). The mode (live or test) follows from the key.

With an Idempotency-Key, a retry after a network error does not create a second calendar. → Idempotency

Possible errors: calendar_limit_reached (your plan’s limit, or 3 sandbox calendars), plan_required (live calendar on the Free plan), insufficient_scope (the key is limited to selected calendars).

Every calendar endpoint returns the same shape:

{
"id": "cal_XXXXXXXXXXXX",
"mode": "live",
"name": "Riverside Yoga",
"description": null,
"timezone": "America/New_York",
"site_url": "https://example.org/",
"language": "en",
"default_duration": "PT1H",
"brand_color": "#0f766e",
"organizer": { "name": "Riverside Yoga", "url": "https://example.org/", "email": "info@example.org" },
"show_events": true,
"blocked": false,
"logo_url": null,
"banner_url": null,
"subscribe_page_url": "https://app.kalender-sync.de/subscribe/cal_XXXXXXXXXXXX",
"feed_url": "https://feeds.kalender-sync.de/f_….ics",
"subscribe_links": {
"google": "https://calendar.google.com/calendar/r?cid=webcal%3A%2F%2Ffeeds.kalender-sync.de%2Ff_….ics",
"outlook": "https://outlook.live.com/calendar/0/addfromweb?url=…&name=Riverside%20Yoga",
"office365": "https://outlook.office.com/calendar/0/addfromweb?url=…&name=Riverside%20Yoga",
"apple": "webcal://feeds.kalender-sync.de/f_….ics"
},
"event_count": 0,
"created_at": "2026-11-03T14:02:11.000Z",
"updated_at": "2026-11-03T14:02:11.000Z"
}
FieldMeaning
subscribe_page_urlThe hosted subscribe page. Link to it or embed the button.
feed_urlThe general ICS feed. It never changes while the calendar exists.
subscribe_linksDirect subscribe links per app. They work but are not counted in the statistics. The subscribe page and the button are counted.
logo_url, banner_urlPublic image URLs or null. → Images
event_countNumber of stored events; a series counts as one.
blockedtrue if we blocked the calendar for a breach of our terms. → calendar_blocked

We store URLs in normalized form, so a trailing slash may be added, for example.

Terminal window
curl https://api.kalender-sync.de/v1/publisher/calendars -H "Authorization: Bearer $KS_KEY"
curl https://api.kalender-sync.de/v1/publisher/calendars/$KS_CAL -H "Authorization: Bearer $KS_KEY"

The list is under data, sorted by creation date, and only contains calendars in the key’s mode.

PATCH only changes the fields you send. null clears a field that allows null (for example "organizer": null).

Terminal window
curl -X PATCH https://api.kalender-sync.de/v1/publisher/calendars/$KS_CAL \
-H "Authorization: Bearer $KS_KEY" \
-H "Content-Type: application/json" \
-d '{ "description": "Classes, workshops and retreats.", "show_events": false }'

organizer is always replaced as a whole: if you only send name, url and email are empty afterwards.

When a calendar’s timezone changes, the new zone applies to events stored without their own timezone the next time those events are written.

Terminal window
curl -X DELETE https://api.kalender-sync.de/v1/publisher/calendars/$KS_CAL -H "Authorization: Bearer $KS_KEY"

Response 204 No Content. The events are deleted with it. So that they also disappear for existing subscribers, the feed keeps serving an empty calendar with a note for 30 days, then 410 Gone. The subscribe page goes offline at the same time.