Push a calendar calfeed cannot reach
Some calendars cannot be polled: a work account behind single sign-on, an internal tool, a script's output. A push source turns that around — your side uploads a JSON dump, calfeed stores it under the source's sharing settings, and it shows up in views and feeds like any other source.
- Create the source. + Add source → in the account picker choose Push (curl a JSON dump). Name it, set a short id and a timezone (the fallback for times in the dump that carry none), pick what it shares, and click Create push source.
- Copy the URL. The source card shows it with a ready curl line. The URL is the credential: whoever holds it can write this source. Lost it? show URL on the card brings it back; new push URL replaces it and kills the old one.
- Optionally lock it down. edit the
source → Required headers on upload, e.g.
X-Push-Key=secret123, and/or Allowed IPs/CIDRs for the machine that uploads. From then on the URL alone gets 403; the card's curl line includes the-Hflag. - Upload.
curl -H 'X-Push-Key: secret123' -T dump.json https://calfeed.io/v1/push/<token>
Each upload replaces the previous one. The reply says what happened:{"stored": 41, "dropped": {"outside_window": 2, "cancelled": 1}}. A rejected event fails the whole upload and names the offending ids, so a bad dump never half-replaces a good one. - Add it to a view. Tick the source (or its tag) in the views that should show it; sources never join views on their own.
The dump
Google Calendar's event shape, so most exporters already speak it:
{
"source_timezone": "America/Los_Angeles",
"events": [
{
"id": "abc_20260911T173500Z",
"start": {"dateTime": "2026-09-11T10:35:00-07:00", "timeZone": "America/Los_Angeles"},
"end": {"dateTime": "2026-09-11T11:30:00-07:00", "timeZone": "America/Los_Angeles"},
"summary": "Informal discussion",
"x-responseStatus": "accepted",
"x-attendeeCount": 13,
"x-conferencing": {"video": true, "type": "zoom"}
},
{"id": "holiday", "summary": "Company holiday",
"start": {"date": "2026-09-14"}, "end": {"date": "2026-09-15"}}
]
}
Only id, start and end are
required; everything else is optional and unknown keys are ignored.
All-day events use date (end exclusive), timed ones
dateTime with an offset or a timeZone.
status: "cancelled" drops an event. Send
x-responseStatus and views hide what you declined. Add
window_start/window_end to replace only that
span, so a daily 7-day dump never wipes what a wider one stored.
Limits: 5,000 events, 2 MB. The full contract with every corner case
lives in the repo's test/fixtures/calendar-sample.json.
Privacy
Two layers: what your exporter puts in the dump, then the source's sharing settings. A dump with only titles, times and attendee counts, stored under a grant of the same, means nothing more ever lands in calfeed.