Release Candidate — the API is undergoing final validation before general availability, and minor changes may still occur.
Hellomateo API Documentation
Recipes

Recurring blocked times

Create a recurring blocked-time master and replace individual occurrences.

A recurring blocked time has one master record and optional exception records. There is no separate series resource: create the master with recurrence_rule, then use the returned Mateo id as series_id for each exception.

A master has no series_id. Each exception belongs to one master, while one master can have multiple exceptions.

Before you begin, identify the Mateo calendar ID and create an API token with calendar.write permission.

Create the recurring master

Create the master through POST /v1/calendars/{calendar_id}/blocked-times. The start_at and end_at define its first occurrence and duration.

For RRULE syntax background, see RFC 5545. The API stores recurrence_rule without server-side validation or normalization, so validate the exact rule in your integration. This example creates ten Monday occurrences:

curl https://api.getmateo.com/v1/calendars/<calendar_id>/blocked-times \
  --request POST \
  --header "Authorization: Bearer $MATEO_API_TOKEN" \
  --header "hellomateo-version: 2026-07-01" \
  --header "Content-Type: application/json" \
  --data '{
    "external_id": "availability-weekly-team-meeting",
    "name": "Weekly team meeting",
    "is_all_day": false,
    "start_at": "2026-09-07T09:00:00.000Z",
    "end_at": "2026-09-07T09:30:00.000Z",
    "recurrence_rule": "FREQ=WEEKLY;BYDAY=MO;COUNT=10"
  }'

The successful 201 Created response includes the Mateo ID needed for exceptions. The following response is abbreviated:

{
  "id": "7f65b8b7-7b4c-4c3a-9ca1-2df34556f8ad",
  "calendar_id": "<calendar_id>",
  "source": "manual",
  "external_id": "availability-weekly-team-meeting",
  "start_at": "2026-09-07T09:00:00.000Z",
  "end_at": "2026-09-07T09:30:00.000Z",
  "recurrence_rule": "FREQ=WEEKLY;BYDAY=MO;COUNT=10",
  "series_id": null,
  "replaces_occurrence_at": null
}

Store the returned id, not external_id, as the master ID:

export MASTER_ID="7f65b8b7-7b4c-4c3a-9ca1-2df34556f8ad"

Replace one occurrence

Create a separate blocked-time record for a changed occurrence. Set series_id to the master ID and replaces_occurrence_at to the original occurrence start. Its own start_at and end_at are the replacement interval.

Example: a weekly meeting moves once

A weekly team meeting normally blocks Mondays from 09:00 to 09:30 UTC. When the 14 September meeting moves to 11:00, create this exception. The 09:00 slot is bookable that day, the 11:00 slot is blocked, and the master still applies to all other Mondays:

curl https://api.getmateo.com/v1/calendars/<calendar_id>/blocked-times \
  --request POST \
  --header "Authorization: Bearer $MATEO_API_TOKEN" \
  --header "hellomateo-version: 2026-07-01" \
  --header "Content-Type: application/json" \
  --data "{
    \"external_id\": \"availability-weekly-team-meeting-2026-09-14\",
    \"name\": \"Weekly team meeting — moved\",
    \"is_all_day\": false,
    \"start_at\": \"2026-09-14T11:00:00.000Z\",
    \"end_at\": \"2026-09-14T11:30:00.000Z\",
    \"series_id\": \"$MASTER_ID\",
    \"replaces_occurrence_at\": \"2026-09-14T09:00:00.000Z\"
  }"

Do not set recurrence_rule on an exception. Give the master and every exception a distinct external_id so each record can be reconciled later. replaces_occurrence_at must be the original generated occurrence start, not the moved start. In daylight-saving time zones, calculate that original instant for the relevant date instead of reusing the first occurrence's UTC clock time.

Recover after an uncertain create

A create request is not an upsert. If a request times out or its response is lost, look up the record by its external_id before retrying the POST:

curl --get https://api.getmateo.com/v1/blocked-times/by \
  --data-urlencode "external_id=availability-weekly-team-meeting" \
  --header "Authorization: Bearer $MATEO_API_TOKEN" \
  --header "hellomateo-version: 2026-07-01"

The locator response returns the master record and its Mateo id. A duplicate external_id create returns 409 Conflict.

A successful response confirms that Mateo created the blocked-time record. It does not confirm that an asynchronous provider-calendar synchronization has finished.

See Create Calendar Blocked Time and Get Calendar Blocked Time by External ID for the complete request and response schemas.

On this page