Calendars
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.
Fields
Section titled “Fields”| Field | Type | Rules | Default |
|---|---|---|---|
name | string | Required on create, 1 to 100 characters | |
timezone | string | Required on create, IANA name such as America/New_York | |
description | string or null | up to 1,000 characters | null |
site_url | string or null | https:// URL, up to 2,000 characters | null |
language | de or en | Language of the subscribe page | en |
default_duration | string | ISO 8601 duration up to PT24H, e.g. PT1H, PT90M, PT1H30M. Used for events without end. | PT1H |
brand_color | string or null | Hex color #rrggbb, stored in lower case | null |
organizer | object or null | name (required, up to 100 characters), url (https://, optional), email (optional). Public on the subscribe page. | null |
show_events | boolean | Show upcoming events on the subscribe page | true |
Unknown fields are refused with 400 invalid_request.
Create a calendar
Section titled “Create a calendar”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).
The response
Section titled “The response”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"}| Field | Meaning |
|---|---|
subscribe_page_url | The hosted subscribe page. Link to it or embed the button. |
feed_url | The general ICS feed. It never changes while the calendar exists. |
subscribe_links | Direct subscribe links per app. They work but are not counted in the statistics. The subscribe page and the button are counted. |
logo_url, banner_url | Public image URLs or null. → Images |
event_count | Number of stored events; a series counts as one. |
blocked | true 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.
List and get calendars
Section titled “List and get calendars”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.
Update a calendar
Section titled “Update a calendar”PATCH only changes the fields you send. null clears a field that allows null (for example "organizer": null).
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.
Delete a calendar
Section titled “Delete a calendar”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.