API v1 beta
Build on Sync My Cal
List connected calendars, inspect sync activity, and manage directional sync rules over JSON.
Authentication
Create a personal bearer key in Settings, store it like a password, and send it in the Authorization header. The secret is shown only once.
curl https://syncmycal.app/api/v1/calendars \
--header "Authorization: Bearer $SYNC_MYCAL_API_KEY"These curl examples use a shell environment variable. Keep the key in a server-side secret store, never a browser bundle or URL. Connect provider accounts in the app first; this API manages calendars already connected to the key owner.
Available resources
GET /api/v1/me: account and entitlement;account:readGET /api/v1/calendars: connected calendars;calendars:readGET /api/v1/sync-rulesandGET /api/v1/sync-rules/:id: list or read rules;rules:readPOST /api/v1/sync-rules: create a rule;rules:writePATCH, DELETE /api/v1/sync-rules/:id: update or delete a rule;rules:writeGET /api/v1/activity: recent sync results;activity:read
Give each key only the scopes its integration needs. A write scope does not grant read access automatically. Normal account entitlement, calendar ownership, and writable-destination requirements still apply.
Create a paused busy-block rule
First list calendars and replace the two placeholder IDs below with their returned id values. They are Sync My Cal calendar IDs, not email addresses or provider event IDs. This request creates a rule with enabled: false, so you can review it before enabling sync.
curl https://syncmycal.app/api/v1/sync-rules \
--header "Authorization: Bearer $SYNC_MYCAL_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"sourceCalendarId": "SOURCE_ID_FROM_CALENDARS",
"targetCalendarId": "DESTINATION_ID_FROM_CALENDARS",
"copyMode": "BUSY",
"busyLabel": "Busy",
"enabled": false,
"skipAllDay": true,
"skipDeclined": true,
"syncWindowDays": 30
}'A successful create returns HTTP 201 with the rule under data. Use PATCH /api/v1/sync-rules/:id with the settings you want to change. Review the rule and run its preview in the app before sending { "enabled": true }. The public API does not expose the app's dry-run control.
Each rule represents one direction. For two-way sync, create the reverse direction separately. Keep editing original events; managed copies are excluded as sources. For the behavior to expect, see the Google–Outlook setup guide.
Pagination and rate limits
Rules and activity accept limit from 1 to 100 (default 25) and an opaque cursor. Pass meta.nextCursor from one response as the next request's cursor, URL-encoded. Stop when it is null. The calendar inventory is not paginated.
curl "https://syncmycal.app/api/v1/sync-rules?limit=25" \
--header "Authorization: Bearer $SYNC_MYCAL_API_KEY"
# Shape of a paginated response:
{ "data": [], "meta": { "nextCursor": null } }Per key, read requests are limited to 120 per minute and writes to 30 per minute. Read the x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset headers. On HTTP 429, wait for the retry-after duration before retrying.
Errors and safe retries
- 401: the key is missing, invalid, expired, or revoked. Replace it through Settings.
- 403: check the error code for a missing scope, entitlement, or access restriction.
- 404: the requested rule is unavailable to this account.
- 409: a source-to-destination rule already exists. Inspect it instead of repeatedly creating another.
- 422: correct the invalid fields identified in the response. Use JSON with the appropriate field types.
- 429 or 500: respect retry headers and use bounded backoff. After an uncertain write result, read the rules to confirm what happened before retrying.
Errors contain error.code, error.message, and error.requestId, sometimes with error.details. Responses also include x-request-id. Send that identifier to support instead of sending a bearer key.
Delete a rule and handle remaining copies
DELETE /api/v1/sync-rules/:id defaults to leaving existing copies. Add ?removeCopies=true to request cleanup while the provider connection still has access.
Check the response body even when HTTP is 200. It reports deleted, copiesRemoved, and copyRemovalFailures. If cleanup fails, deleted is false and the rule stays tracked. Restore access and retry deletion with removeCopies=true; don't treat the HTTP status alone as successful cleanup.
Buffers before and after copies
Send bufferBeforeMins and bufferAfterMins as integers from 0 to 1440. For example, {"bufferBeforeMins":15,"bufferAfterMins":30} reserves preparation and recovery time around timed copies. Originals and all-day events stay unchanged. Each sync direction has independent values. Zero clears a side; omitting it from a PATCH or an existing-rule review preserves its current value.
Legacy bufferMins writes still set both sides; null clears both. Send the legacy field or the independent fields in a request, never both (mixed requests return 422). Responses include both effective values. The legacy response field is null when the sides differ or no buffer was set, so use the independent fields to read exact timing. Unrelated edits made by older clients preserve both sides.
bufferMins is deprecated for new clients but remains supported throughout API v1. Removal would require a new major API version and a migration notice; no removal date is set. Saving settings does not rewrite existing copies immediately. Use review and apply below to reconcile existing events and inspect the resulting times.
Review and apply changes · limited beta
Rule POST and PATCH requests save settings. Those settings can affect later changed events; they do not start a full check of existing copies. Accounts enabled for reviewed sync can use the separate flow below with an explicitly selected sync:apply key permission. This permission exposes calendar event examples and can save rules and change their copies. Existing keys keep their permissions. Use rules:read to read operation results.
POST /api/v1/sync-reviewswith adirectionsarray. For an existing rule, send itsruleId, exactexpectedUpdatedAtfrom GET sync-rules, and an optional partialsettingsobject. For a new rule, sendsourceCalendarId,targetCalendarIdand optional settings. A review expires after 15 minutes.POST /api/v1/sync-reviews/:id/scanwith{}untildata.review.statusisREADY. Inspect cumulative counts and each batch's event examples. Scans are read-only. Incomplete or expired reviews need a new review; a null cursor does not establish complete coverage.POST /api/v1/sync-reviews/:id/applywith{}and a uniqueIdempotency-Keyheader of 16–128 letters, digits, dots, underscores or hyphens. Retry an uncertain submission with the same review and key. Reusing the key for another review returns 409.- A
202response means saved and queued. Poll theLocationURL no more often than every ten seconds. Check each direction's status and actual counts; partial or blocked work is unfinished. Calendar changes discovered during application may require a new review. - Request a bounded attempt with
POST /api/v1/sync-operations/:id/continueand{}, or retry selected due failures withPOST /api/v1/sync-operations/:id/retryand{"directionIds":["operation-direction-uuid"]}. Completed work is retained. The fifteen-minute scheduler continues accepted work even after the client closes.
A missing beta entitlement returns 403; stale reviews return 409. Honor 429 and Retry-After. Limits apply both per key and per account, so rotating keys does not create a new scan budget. Responses are private and uncached. Keep event examples out of application logs.
Event examples are fetched for the request. We retain encrypted rule settings, review identities and verification evidence, and application counts and outcomes, without fetched event titles, descriptions or locations. Unsubmitted reviews expire after 15 minutes and are removed by daily maintenance. Resolved receipts are kept for 30 days after completion; unresolved work retains the evidence needed for recovery. Rule history keeps up to 50 revisions for 90 days, except revisions needed by unresolved work. Rule or account deletion removes the associated records; normal backup retention still applies.
Machine-readable contract
The repository-owned OpenAPI 3.1 document is the source of truth for request fields, scopes, and responses.
Open the OpenAPI document →