Scheduling

Use the scheduling routes to read one or more days, to find conflict-free time for new work, and to undo a recent change. The server calculates the free slots for you.

The machine-readable spec of all public endpoints: openapi.json.

How scheduling works

  1. Read the days with GET /schedule. The response gives the events, the free slots, and the load by area, activity type, and project.
  2. Book work with POST /schedule/plan. Each request gives a name, a duration, and an exact start or a time window.
  3. A successful request books at once. An exact start books there when it is free; a window books its top-ranked free slot.
  4. Undo a change with POST /actions/undo and the undoToken of that change.
ItemLifetimeUse
undoToken30 minutes. The response gives the exact time in expiresAt.Send it to POST /actions/undo. You can use a token one time only.
requestId60 secondsA retry key for one request of POST /schedule/plan.

MCP clients use get_schedule to read free slots, then write_events to create an event. Refer to Schedule new work.

Scopes

RouteScope
GET /scheduleevents:read or events:write
POST /schedule/planevents:write
POST /actions/undoevents:write

All routes need a trial or Pro plan. Refer to Authentication.

Rows and status codes of the write routes

The two write routes return results, with one row for each item. Each row has index (0-based), status (ok, error, or skipped), and result or error. An error is { code, message }, with optional detail fields. Refer to Error format. A skipped row has a reason.

  • Plan is atomic by default. When one row fails, the server writes nothing. Each other row is skipped, and the call has no undoToken.
  • Send partial: true to plan to write the rows that succeed. The failed rows are errors.
  • Undo has no partial flag. Each token succeeds or fails alone.
  • When one or more rows are ok, the status is 200. The body has results. For plan, it also has timezone, and undoToken with expiresAt when the server recorded an undo receipt. For undo, it has results only.
  • When no row is ok, Reassign rejects the call. The body is the error envelope and results. The status follows error.code, as the Responses table of each route shows.
  • A body that is not valid gets 422 with the code validation and no results.
  • A plan row that replays an earlier call (refer to requestId) stays ok with replayed: true, also when another row fails. Thus the call is not rejected.
  • A missing or empty array (requests or tokens) returns 422. More than 20 items also returns 422.

For the error codes, refer to Errors.


GET/api/v1/schedule

Read a schedule

Read one day or a range of days. The response gives the events, the free slots, and the load of each day. It also gives your areas, activity types, projects, and preferences. Scope: events:read.

  • from and to are required. For one day, send the same date in both.
  • to must not be before from. The range is 366 days or less. Else the server returns 422.
  • Send each boolean parameter as true or false. Other values return 422.
  • includeBacklog=true adds the Inbox items in backlog. backlogQuery, backlogPlannedOn, backlogProjectId, backlogMinPriority, and backlogOffset work only with includeBacklog=true. Without it, they return 422. Refer to Backlog.
  • backlogProjectId keeps the Inbox items of one project. Send a project id, or none for the items with no project.
  • backlogMinPriority keeps the Inbox items with a priority of this value or more, from 0 to 4.
  • The Inbox filters work together. With one or more filters, the response also has backlogMatchedCount.
  • includeSeries=true adds the recurring series in series. Refer to Series rows.
  • includeLookups=false removes areas, activityTypes, projects, and integrations from the response. Use it when you have them from an earlier read. The default is true. userPreferences and timezone stay.
  • minDuration is an optional whole number from 1 to 1440, in minutes. For example, minDuration=90 returns only freeSlots of at least 90 minutes. It keeps the full span of each qualifying gap and does not filter events.

The MCP tool get_schedule has separate weather and energy options. For REST, read those reports through GET /weather and GET /energy. The optional energy field in the shared response schema is used by MCP only.

What the response contains

  • timezone is the IANA time zone of the account. All start and end values are local datetimes in this time zone.
  • now is the current local datetime, for example "2026-09-23T14:05".
  • days has one item for each date. Each day has events (the event model) and freeSlots (each a start and end). On today, the first free slot starts on the first 5-minute mark that is more than 5 minutes after now. A write accepts that start.
  • Each occurrence of a series has seriesId and originalDate. Refer to Ids of recurring events.
  • loadByArea and loadByActivityType give the time of the blocking events of the day. Each bucket is areaId (or activityTypeId), minutes, and eventCount. areaId is null for the events with no area.
  • loadByProject gives the same buckets by projectId. projectId is null for the events with no project. The buckets start with the most minutes.
  • A read of more than one day also has a top-level loadByProject: the sum of the loadByProject buckets of all days. An event on two days (across midnight) counts one time in eventCount.
  • projects lists your projects: id, name, and areaId (or null). An archived project also has archived: true. It keeps its links, but it refuses new links. Refer to Categories.
  • nonBlockingLoadByArea and nonBlockingLoadByActivityType give the same buckets for the events of the kind non_blocking. The reference events are not in them. A day with no non_blocking event does not have these fields.
  • A day that has a confirmed review also has review: reviewedAt (an ISO 8601 instant) and the adherence scores. A score can be null. Refer to Day reviews.
  • userPreferences.conflictPolicy is always propose. A write that overlaps a blocking event fails with conflict and gives nearestSlots. No setting changes this.
  • integrations is in the response when a calendar is connected. Every caller gets integrations.sources[].account, the account name at the provider. integrations.sources[].calendars[].timezone is the time zone of the calendar at the provider. It is for information only: all spans use the top-level timezone. integrations.defaultCalendarId is the default calendar of a new event, and the default Source of a new Inbox item. It is absent when the default calendar is not writable or its source is not connected. backlogCount is in the response when the Inbox is not empty. With includeBacklog=true, it is always there.
  • A writable event calendar in integrations.sources[].calendars[] also has copyStyle: full, private, or busy. It is the style of a copy on that calendar when the mirrorStyles of the event does not name the calendar. With copyStyle: "busy", busyCopyTitle is the title of the copy. null means "Busy". Refer to Copy styles.
  • integrations.aiRuleWarnings lists the problems in the AI rules of the user. Each item is an area or an activity type that the rules name. It does not exist, or its name matches more than one category. It has up to 20 items { code, field, name }. code is missing_taxonomy_reference or ambiguous_taxonomy_reference. field is area or activityType. The field is absent when there is no warning.

Series rows

With includeSeries=true, series has one row for each recurring series that obeys one of these conditions:

  • The series has an occurrence in the range from from to to.
  • The series has a nextOccurrence.
  • The series has no end yet. A series with an open rule never ends, also when its next date is more than 366 days ahead.

A series ends when its UNTIL or COUNT leaves no date on or after today. The response does not include a series that ended outside the range.

FieldValue
id, name, recurrenceThe series id, its name, and its RRULE
start, endThe anchor span of the series
nextOccurrenceThe first date from today to 366 days ahead with an occurrence that has not ended at now. A moved occurrence counts on its actual date, not the original date in its id. Else null.
overrides{ edited, deleted }: the occurrences that you changed or deleted
areaId, activityTypeIdThe id, or null
kind, sourceAs on an event
calendarId, mirrorCalendarIds, mirrorStyles, readOnlyAs on an event, when they apply

A series row has no notes. The events of the series have them.

Query parameters

  • Name
    from
    Type
    string, required
    Description

    First day of the range, inclusive.

  • Name
    to
    Type
    string, required
    Description

    Last day of the range, inclusive.

  • Name
    includeSeries
    Type
    "true" | "false"
    Description

    Also return the recurring masters as series.

  • Name
    includeLookups
    Type
    "true" | "false"
    Description

    Default true. Pass false to leave out areas, activityTypes, projects and integrations when you already have them from an earlier read.

  • Name
    minDuration
    Type
    string
    Description

    Return only the freeSlots of at least this many minutes.

  • Name
    includeBacklog
    Type
    "true" | "false"
    Description

    Include the Inbox items (the backlog array), not just backlogCount. Pass true when the user wants to see, schedule, or manage their Inbox.

  • Name
    backlogQuery
    Type
    string
    Description

    Filter the Inbox blocks by name (fuzzy, case/accent-insensitive), e.g. "dentist". Needs includeBacklog: true.

  • Name
    backlogPlannedOn
    Type
    string
    Description

    Filter the Inbox blocks to those planned for this day (a planned day, or a planned window that covers it). Needs includeBacklog: true; composes with backlogQuery.

  • Name
    backlogProjectId
    Type
    string
    Description

    Filter the Inbox blocks to one project id, or "none" for the blocks with no project. Needs includeBacklog: true; composes with the other filters.

  • Name
    backlogMinPriority
    Type
    string
    Description

    Filter the Inbox blocks to a priority of at least this value (0 none, 1 low, 2 medium, 3 high, 4 urgent). Needs includeBacklog: true; composes with the other filters.

  • Name
    backlogOffset
    Type
    string
    Description

    Inbox page offset from nextBacklogOffset; keep the same filters. Needs includeBacklog: true.

Response fields

  • Name
    timezone
    Type
    string, required
    Description
  • Name
    now
    Type
    string, required
    Description
  • Name
    weather
    Type
    string
    Description
  • Name
    energy
    Type
    string
    Description
  • Name
    days
    Type
    object[], required
    Description
    9 fields
    • Name
      date
      Type
      string, required
      Description
    • Name
      events
      Type
      object[], required
      Description
      26 fields
      • Name
        start
        Type
        string, required
        Description
      • Name
        end
        Type
        string, required
        Description
      • Name
        id
        Type
        string, required
        Description
      • Name
        seriesId
        Type
        string
        Description
      • Name
        originalDate
        Type
        string
        Description
      • Name
        kind
        Type
        "blocking" | "non_blocking" | "reference", required
        Description
      • Name
        name
        Type
        string, required
        Description
      • Name
        notes
        Type
        string
        Description
      • Name
        source
        Type
        "google" | "google_tasks" | "linear" | "microsoft" | "microsoft_todo" | "ticktick" | "todoist" | "reassign", required
        Description
      • Name
        sourceUrl
        Type
        string
        Description
      • Name
        meeting
        Type
        object
        Description
        2 fields
        • Name
          url
          Type
          string, required
          Description
        • Name
          label
          Type
          string, required
          Description
      • Name
        location
        Type
        object
        Description
        2 fields
        • Name
          text
          Type
          string, required
          Description
        • Name
          url
          Type
          string
          Description
      • Name
        recurrence
        Type
        string
        Description
      • Name
        warning
        Type
        string
        Description
      • Name
        areaId
        Type
        string | null, required
        Description
      • Name
        activityTypeId
        Type
        string | null, required
        Description
      • Name
        projectId
        Type
        string | null, required
        Description
      • Name
        priority
        Type
        integer, required
        Description
      • Name
        calendarId
        Type
        string | null
        Description
      • Name
        mirrorCalendarIds
        Type
        string[]
        Description
      • Name
        mirrorStyles
        Type
        map of "full" | "private" | "busy"
        Description
      • Name
        readOnly
        Type
        true
        Description
      • Name
        focusIntervals
        Type
        object
        Description
        2 fields
        • Name
          focusMin
          Type
          integer, required
          Description
        • Name
          breakMin
          Type
          integer, required
          Description
      • Name
        completedFocusIntervals
        Type
        integer
        Description
      • Name
        checklist
        Type
        object
        Description
        1 fields
        • Name
          items
          Type
          object[], required
          Description
          3 fields
          • Name
            id
            Type
            string, required
            Description
          • Name
            text
            Type
            string, required
            Description
          • Name
            done
            Type
            boolean, required
            Description
      • Name
        reflect
        Type
        object
        Description
        2 forms
        • One form: Without actualStart, actualEnd
          • Name
            status
            Type
            "kept" | "skipped" | "changed" | "added", required
            Description
        • One form: With actualStart, actualEnd
          • Name
            status
            Type
            "changed", required
            Description
          • Name
            actualStart
            Type
            string, required
            Description
          • Name
            actualEnd
            Type
            string, required
            Description
    • Name
      freeSlots
      Type
      object[], required
      Description
      2 fields
      • Name
        start
        Type
        string, required
        Description
      • Name
        end
        Type
        string, required
        Description
    • Name
      loadByArea
      Type
      object[], required
      Description
      3 fields
      • Name
        areaId
        Type
        string | null, required
        Description
      • Name
        minutes
        Type
        integer, required
        Description
      • Name
        eventCount
        Type
        integer, required
        Description
    • Name
      loadByActivityType
      Type
      object[], required
      Description
      3 fields
      • Name
        activityTypeId
        Type
        string | null, required
        Description
      • Name
        minutes
        Type
        integer, required
        Description
      • Name
        eventCount
        Type
        integer, required
        Description
    • Name
      loadByProject
      Type
      object[], required
      Description
      3 fields
      • Name
        projectId
        Type
        string | null, required
        Description
      • Name
        minutes
        Type
        integer, required
        Description
      • Name
        eventCount
        Type
        integer, required
        Description
    • Name
      nonBlockingLoadByArea
      Type
      object[]
      Description
      3 fields
      • Name
        areaId
        Type
        string | null, required
        Description
      • Name
        minutes
        Type
        integer, required
        Description
      • Name
        eventCount
        Type
        integer, required
        Description
    • Name
      nonBlockingLoadByActivityType
      Type
      object[]
      Description
      3 fields
      • Name
        activityTypeId
        Type
        string | null, required
        Description
      • Name
        minutes
        Type
        integer, required
        Description
      • Name
        eventCount
        Type
        integer, required
        Description
    • Name
      review
      Type
      object
      Description
      2 fields
      • Name
        reviewedAt
        Type
        string, required
        Description
      • Name
        adherence
        Type
        object
        Description
        6 fields
        • Name
          event
          Type
          number | null, required
          Description
        • Name
          layer
          Type
          number | null, required
          Description
        • Name
          plannedMinutes
          Type
          integer, required
          Description
        • Name
          unplannedMinutes
          Type
          integer, required
          Description
        • Name
          byArea
          Type
          object[], required
          Description
          3 fields
          • Name
            areaId
            Type
            string | null, required
            Description
          • Name
            adherence
            Type
            number, required
            Description
          • Name
            plannedMinutes
            Type
            integer, required
            Description
        • Name
          byActivityType
          Type
          object[], required
          Description
          3 fields
          • Name
            activityTypeId
            Type
            string | null, required
            Description
          • Name
            adherence
            Type
            number, required
            Description
          • Name
            plannedMinutes
            Type
            integer, required
            Description
  • Name
    loadByProject
    Type
    object[]
    Description
    3 fields
    • Name
      projectId
      Type
      string | null, required
      Description
    • Name
      minutes
      Type
      integer, required
      Description
    • Name
      eventCount
      Type
      integer, required
      Description
  • Name
    areas
    Type
    object[]
    Description
    3 fields
    • Name
      id
      Type
      string, required
      Description
    • Name
      name
      Type
      string, required
      Description
    • Name
      color
      Type
      string, required
      Description
  • Name
    activityTypes
    Type
    object[]
    Description
    3 fields
    • Name
      id
      Type
      string, required
      Description
    • Name
      name
      Type
      string, required
      Description
    • Name
      pattern
      Type
      "solid" | "hatch_r" | "hatch_l" | "cross" | "horizontal" | "vertical" | "grid" | "dots" | "waves" | "chevron", required
      Description
  • Name
    projects
    Type
    object[]
    Description
    4 fields
    • Name
      id
      Type
      string, required
      Description
    • Name
      name
      Type
      string, required
      Description
    • Name
      areaId
      Type
      string | null, required
      Description
    • Name
      archived
      Type
      true
      Description

      Present on an archived project: it refuses new links, and an update with archived: false restores it.

  • Name
    userPreferences
    Type
    object, required
    Description
    1 fields
    • Name
      conflictPolicy
      Type
      "propose", required
      Description

      Always propose: a write that collides is refused with free slots.

  • Name
    integrations
    Type
    object
    Description
    5 fields
    • Name
      aiClassify
      Type
      boolean, required
      Description
    • Name
      aiRules
      Type
      string
      Description
    • Name
      aiRuleWarnings
      Type
      object[]
      Description
      3 fields
      • Name
        code
        Type
        "missing_taxonomy_reference" | "ambiguous_taxonomy_reference", required
        Description
      • Name
        field
        Type
        "area" | "activityType", required
        Description
      • Name
        name
        Type
        string, required
        Description
    • Name
      defaultCalendarId
      Type
      string
      Description
    • Name
      sources
      Type
      object[], required
      Description
      4 fields
      • Name
        provider
        Type
        "google" | "google_tasks" | "linear" | "microsoft" | "microsoft_todo" | "ticktick" | "todoist", required
        Description
      • Name
        account
        Type
        string
        Description
      • Name
        status
        Type
        "connected" | "disconnected" | "error" | "pending" | "revoked", required
        Description
      • Name
        calendars
        Type
        object[], required
        Description
        9 fields
        • Name
          id
          Type
          string, required
          Description
        • Name
          name
          Type
          string, required
          Description
        • Name
          writable
          Type
          boolean, required
          Description
        • Name
          area
          Type
          object, required
          Description
          2 forms
          • One form: mode: "automatic"
            • One form: mode: "fixed"
              • Name
                areaId
                Type
                string, required
                Description
          • Name
            activityType
            Type
            object, required
            Description
            3 forms
            • One form: mode: "automatic"
              • One form: mode: "fixed"
                • Name
                  activityTypeId
                  Type
                  string, required
                  Description
              • One form: mode: "none"
              • Name
                kind
                Type
                object, required
                Description
                2 forms
                • One form: mode: "automatic"
                  • One form: mode: "fixed"
                    • Name
                      kind
                      Type
                      "blocking" | "non_blocking" | "reference", required
                      Description
                • Name
                  timezone
                  Type
                  string
                  Description
                • Name
                  copyStyle
                  Type
                  "full" | "private" | "busy"
                  Description
                • Name
                  busyCopyTitle
                  Type
                  string | null
                  Description
          • Name
            series
            Type
            object[]
            Description
            15 fields
            • Name
              start
              Type
              string, required
              Description
            • Name
              end
              Type
              string, required
              Description
            • Name
              id
              Type
              string, required
              Description
            • Name
              name
              Type
              string, required
              Description
            • Name
              recurrence
              Type
              string, required
              Description
            • Name
              nextOccurrence
              Type
              string | null, required
              Description
            • Name
              overrides
              Type
              object, required
              Description
              2 fields
              • Name
                edited
                Type
                integer, required
                Description
              • Name
                deleted
                Type
                integer, required
                Description
            • Name
              areaId
              Type
              string | null, required
              Description
            • Name
              activityTypeId
              Type
              string | null, required
              Description
            • Name
              kind
              Type
              "blocking" | "non_blocking" | "reference", required
              Description
            • Name
              source
              Type
              "google" | "google_tasks" | "linear" | "microsoft" | "microsoft_todo" | "ticktick" | "todoist" | "reassign", required
              Description
            • Name
              calendarId
              Type
              string | null
              Description
            • Name
              mirrorCalendarIds
              Type
              string[]
              Description
            • Name
              mirrorStyles
              Type
              map of "full" | "private" | "busy"
              Description
            • Name
              readOnly
              Type
              true
              Description
          • Name
            backlogCount
            Type
            integer
            Description
          • Name
            backlogMatchedCount
            Type
            integer
            Description
          • Name
            nextBacklogOffset
            Type
            integer | null
            Description
          • Name
            backlog
            Type
            object[]
            Description
            13 fields
            • Name
              id
              Type
              string, required
              Description
            • Name
              name
              Type
              string, required
              Description
            • Name
              notes
              Type
              string
              Description
            • Name
              sourceUrl
              Type
              string
              Description
            • Name
              kind
              Type
              "blocking" | "non_blocking" | "reference", required
              Description
            • Name
              durationMinutes
              Type
              integer
              Description
            • Name
              areaId
              Type
              string | null, required
              Description
            • Name
              activityTypeId
              Type
              string | null, required
              Description
            • Name
              projectId
              Type
              string | null, required
              Description
            • Name
              priority
              Type
              integer, required
              Description
            • Name
              plannedDate
              Type
              string
              Description
            • Name
              plannedUntil
              Type
              string
              Description
            • Name
              checklist
              Type
              object
              Description
              1 fields
              • Name
                items
                Type
                object[], required
                Description
                2 fields
                • Name
                  id
                  Type
                  string, required
                  Description
                • Name
                  text
                  Type
                  string, required
                  Description

          Responses

          StatusCodesMeaning
          200—Success.
          401unauthorizedNo Bearer token and no session cookie, or the token is invalid, expired, or revoked. The response carries a WWW-Authenticate challenge that points at the protected-resource metadata.
          403permissionscopeA token without events:read or events:write gets scope "This token is not authorized to read events (requires events:read or events:write scope)." An account without Reassign Pro access gets permission "Reassign needs an active subscription." The 7-day free trial includes Reassign Pro. A cookie session from another site gets permission "Cross-origin request."
          422validationA query parameter is not valid. The message names the first bad field by its path. A repeated or unknown query parameter is also a 422.
          429rate_limitedToo many requests. The edge firewall limits each IP to 2000 requests per minute across /api/v1; that 429 comes from the edge and can have a body that is not this JSON and no Retry-After header. When an edge 429 has no Retry-After, retry after 60 seconds. The app also limits each Bearer credential to 600 requests per minute, and some routes limit each user. These limits return this body. This app 429 always has Retry-After: retry after that number of seconds.
          503internalA fault on our side. The request is safe to retry.

          Request

          GET
          /api/v1/schedule
          curl "https://reassign.app/api/v1/schedule?from=2026-08-14&to=2026-08-14" \
            -H "Authorization: Bearer rsk_live_YOUR_TOKEN"

          Response

          {
            "timezone": "Europe/Ljubljana",
            "now": "2026-08-14T10:42",
            "days": [
              {
                "date": "2026-08-14",
                "events": [
                  {
                    "id": "b7f1c2a0-1d2e-4f3a-9b8c-5d6e7f801234",
                    "start": "2026-08-14T09:00",
                    "end": "2026-08-14T10:30",
                    "kind": "blocking",
                    "name": "Team sync",
                    "source": "google",
                    "meeting": {
                      "url": "https://us02web.zoom.us/j/1234567890",
                      "label": "Zoom"
                    },
                    "location": {
                      "text": "Room 4, 2nd floor",
                      "url": "https://www.google.com/maps/search/?api=1&query=Room%204%2C%202nd%20floor"
                    },
                    "areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
                    "activityTypeId": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
                    "projectId": null,
                    "priority": 0,
                    "calendarId": "8a1f0c2e-3b4d-4e5f-9a0b-1c2d3e4f5061",
                    "mirrorCalendarIds": [
                      "a1b2c3d4-5e6f-4071-8293-a4b5c6d7e8f9"
                    ]
                  }
                ],
                "freeSlots": [
                  {
                    "start": "2026-08-14T10:45",
                    "end": "2026-08-15T00:00"
                  }
                ],
                "loadByArea": [
                  {
                    "areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
                    "minutes": 90,
                    "eventCount": 1
                  }
                ],
                "loadByActivityType": [
                  {
                    "activityTypeId": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
                    "minutes": 90,
                    "eventCount": 1
                  }
                ],
                "loadByProject": [
                  {
                    "projectId": null,
                    "minutes": 90,
                    "eventCount": 1
                  }
                ]
              }
            ],
            "areas": [
              {
                "id": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
                "name": "Work",
                "color": "#3b82f6"
              }
            ],
            "activityTypes": [
              {
                "id": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
                "name": "Focus",
                "pattern": "solid"
              }
            ],
            "projects": [],
            "userPreferences": {
              "conflictPolicy": "propose"
            },
            "integrations": {
              "aiClassify": true,
              "defaultCalendarId": "8a1f0c2e-3b4d-4e5f-9a0b-1c2d3e4f5061",
              "sources": [
                {
                  "provider": "google",
                  "account": "user@example.com",
                  "status": "connected",
                  "calendars": [
                    {
                      "id": "8a1f0c2e-3b4d-4e5f-9a0b-1c2d3e4f5061",
                      "name": "Work",
                      "writable": true,
                      "area": {
                        "mode": "automatic"
                      },
                      "activityType": {
                        "mode": "automatic"
                      },
                      "kind": {
                        "mode": "automatic"
                      }
                    },
                    {
                      "id": "a1b2c3d4-5e6f-4071-8293-a4b5c6d7e8f9",
                      "name": "Team",
                      "writable": true,
                      "area": {
                        "mode": "automatic"
                      },
                      "activityType": {
                        "mode": "automatic"
                      },
                      "kind": {
                        "mode": "automatic"
                      }
                    }
                  ]
                }
              ]
            },
            "backlogCount": 1
          }

          POST/api/v1/schedule/plan

          Plan work into free time

          Place one or more events into free time. You do not calculate the slots. Send 1 to 20 requests. Scope: events:write.

          The requests run in their order. A later request does not overlap an event that an earlier request booked.

          The call is atomic by default. When one request fails, the server books nothing. Send partial: true to book the requests that succeed.

          Two forms of a request

          Each request has name (1 to 200 characters) and durationMinutes (a whole number from 5 to 1440). It also has one of these two forms:

          FormFieldsWhat the server does
          Fixed startstartWhen the time is free, the server books the event. When the time overlaps a blocking event, or a request before it in the same call, the row fails with conflict. The row gives conflicts and up to 5 nearestSlots in the next 7 days. The server does not move an exact start to another time.
          Windowearliest and latestThe server searches the window. The window is at most 24 hours, and it can go past midnight. The server books the top-ranked free slot immediately. When no slot fits, the row fails with conflict.
          • All times are local datetimes "YYYY-MM-DDTHH:MM".
          • autoCommitBest is deprecated. A window accepts true or an omitted field, with the same behavior. false fails with validation.
          • A request with start and also earliest, latest, or autoCommitBest is an error.
          • A request can also have kind and recurrence, as on an event create. A fixed-start request with kind: "non_blocking" or kind: "reference" does not fail with conflict. A blocking fixed-start request with recurrence fails with conflict when an occurrence overlaps a blocking event.
          • A start or a window in the past is an error. On today, the start must be more than 5 minutes after now. A window with no room for a 5-minute slot after that point fails with validation, not conflict.
          • A window slot starts on a 30-minute mark. When no 30-minute mark fits, it starts at the start of a free gap (a 5-minute mark).
          • A nearest slot can start at one of these times: a 15-minute mark, the start of a free gap, or the latest start that fits in a free gap. It can also start at the free minute nearest to the requested start. It keeps the exact durationMinutes. This rule applies to each nearestSlots list, also in POST /events and POST /backlog.
          • An unknown key fails the row with validation: Unrecognized key(s): <keys>. When the key belongs to the other form, the message names that form.
          • calendarId, mirrorCalendarIds, and mirrorStyles work as on an event create. null keeps the event on the dial only. When you omit calendarId, the event goes to the default calendar if there is one. Else it stays on the dial only. A request with recurrence and mirrorCalendarIds needs a home calendar. Refer to Rules of the fields.
          • mirrorStyles sets the style of each copy. Each key must be in the mirrorCalendarIds of the request. {} is the same as no map. Refer to Copy styles.
          • areaId and activityTypeId take an id. null and an omitted key are the same. An id that does not exist, or that you cannot see, fails the row with not_found.
          • projectId takes the id of a live project. null and an omitted key are the same. An empty string fails the row with validation. An archived or unknown id fails the row with not_found. In result.event, projectId is the stored form of the id, also when you send it braced or in upper case.
          • With no areaId, the event takes the area of the project. An areaId in the request wins. When the area of the project is hidden, the event gets no area. Refer to Rules of the fields.
          • priority is a whole number: 0 none, 1 low, 2 medium, 3 high, 4 urgent. An omitted value is 0. null, a number that is not whole, or a value out of the range fails the row with validation.
          • The server checks areaId and activityTypeId before projectId. When a request has an unknown area and an unknown project, the row error names the area.

          Results

          Each successful row has event, the booked event, in result.

          • An exact-start conflict row gives nearestSlots. To take one, send its start as a new request.
          • When the call books one or more events and records an undo receipt, the body has one undoToken and its expiresAt. This token undoes all bookings of the call. If the server cannot record the undo, the bookings stay and the response has no undoToken.

          Row errors

          A request that is not valid has status: "error" and the code validation. In the default atomic mode, the other rows are skipped, and the server rejects the call. With partial: true, the other requests still run, and the call returns 200 when one or more rows are ok.

          A validation row from a schema check also has error.issues. Later checks, such as a start in the past or a series with copies and no home calendar, can return validation without issues. Refer to Validation errors.

          A body that is not valid returns 422 with no results, for example when requests is empty or has more than 20 items.

          Some row errors:

          Causeerror.messageerror.code
          A name of spaces onlyEvent name cannot be blank.validation
          A window longer than 24 hoursThe window from `earliest` to `latest` can be at most 24 hours.validation
          A window where latest is not after earliest`latest` must be a local datetime after `earliest`.validation
          A request with recurrence and mirrorCalendarIds, and no home calendarCopies of a series need a home calendar. Give the series a calendarId, or remove its mirrorCalendarIds.validation
          A mirrorStyles key that is not in mirrorCalendarIdsmirrorStyles has calendar "<id>", which is not in the event's mirrorCalendarIds. Add it to mirrorCalendarIds, or remove it from mirrorStyles.validation
          A fixed start in the past<start> is in the past. Pick a later time.validation
          A fixed start today, 5 minutes or less after now<start> is too soon: a start today must be more than 5 minutes after now. Pick a later time.validation
          A window in the past, or with no room after nowThe window <earliest> to <latest> is in the past or starts too soon: a start today must be more than 5 minutes after now. Pick a later window.validation
          A taken fixed start<start> is taken. Pick another time or one of the nearest free slots.conflict
          A taken fixed start with no free slot in the next 7 days<start> is taken and no free <n>-minute slot fits through <date> (the next 7 days).conflict
          An unknown areaIdArea "<id>" not found or not accessible.not_found
          An unknown activityTypeIdActivity type "<id>" not found or not accessible.not_found
          An unknown or archived projectIdNo live project with id "<id>".not_found

          When all rows fail with not_found, the status is 404.

          A window schema error does not repeat the values that you sent. When earliest or latest has a bad format, its issue has expected: "YYYY-MM-DDTHH:MM"; the schema skips the window-order and length checks until both values have valid formats. Later errors, such as a window in the past or a window with no free slot, include the window's times.

          Retries with requestId

          Give each request a requestId. When you send the same requestId again in 60 seconds, the server does not book a second event. It returns the first result with replayed: true, and it writes nothing new.

          • The retry must send the same content. A request with different content is a new request.
          • mirrorStyles is content. The order of the keys in mirrorStyles does not change the match. {} and no map match. The order of mirrorCalendarIds changes the match.
          • projectId and priority are content. A retry with another priority is a new request.
          • priority: 0, projectId: null, areaId: null, and activityTypeId: null match an omitted key. priority: null is not valid.
          • The server compares the ids as you sent them. Send each id in the same form in a retry.
          • Only a booked result can replay. The server does not replay a result that you undid.
          • Omitting autoCommitBest or sending true does not change retry matching. Clients can drop the deprecated field while keeping the same requestId.
          • Only a requestId replays a result. A request with no requestId is always a new request.
          • When one call sends the same requestId in more than one request, the server replays an earlier result for one request only. The other requests run as new requests.

          Request body

          • Name
            requests
            Type
            object[], required
            Description
            2 forms
            • One form: With start

              An exact request: book at start.

              • Name
                name
                Type
                string, required
                Description

                Event title, e.g. "Deep work", "Gym".

              • Name
                durationMinutes
                Type
                integer, required
                Description

                How long, in whole minutes, e.g. 90.

              • Name
                areaId
                Type
                string | null
                Description

                Area id to attach (from the schedule read's areas); null or omitted leaves it unset.

              • Name
                activityTypeId
                Type
                string | null
                Description

                Activity-type id to attach (from the schedule read's activityTypes); null or omitted leaves it unset.

              • Name
                projectId
                Type
                string | null
                Description

                A live project id from get_schedule projects. When the project changes and the op sets no areaId, the event takes the area of the project. null or omitted leaves it unset.

              • Name
                priority
                Type
                integer
                Description

                0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit for 0.

              • Name
                recurrence
                Type
                string
                Description

                Repeat rule as an RRULE, e.g. "FREQ=WEEKLY;BYDAY=MO"; omit for a one-off.

              • Name
                kind
                Type
                "blocking" | "non_blocking" | "reference"
                Description

                "blocking" (default) cannot overlap others; "non_blocking" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; "reference" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.

              • Name
                notes
                Type
                string
                Description
              • Name
                sourceUrl
                Type
                string
                Description

                Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.

              • Name
                calendarId
                Type
                string | null
                Description

                The home calendar: a calendar id (from the calendars list or the schedule's integrations). Omit it to use the account's default calendar if one is set, else the event stays on the dial only. null keeps the event on the dial only. A calendar id requires Reassign Pro; whole-series only.

              • Name
                mirrorCalendarIds
                Type
                string[]
                Description

                The one-way copy calendars, as calendar ids. It must not contain the home calendarId. On update it REPLACES the set; [] clears it. An id already on the event may stay even if its calendar is read-only now; only an added id is checked. Adding an id requires Reassign Pro; whole-series only.

              • Name
                mirrorStyles
                Type
                map of "full" | "private" | "busy"
                Description

                How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else "Busy"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.

              • Name
                requestId
                Type
                string
                Description

                Idempotency key; reuse on retry to avoid double-booking. Only this key replays: a request without it is always booked as new.

              • Name
                start
                Type
                string, required
                Description

                Exact local start "YYYY-MM-DDTHH:MM"; place there. A taken start is a conflict error with nearestSlots.

            • One form: With earliest, latest

              A window request: search from earliest to latest, at most 24 hours.

              • Name
                name
                Type
                string, required
                Description

                Event title, e.g. "Deep work", "Gym".

              • Name
                durationMinutes
                Type
                integer, required
                Description

                How long, in whole minutes, e.g. 90.

              • Name
                areaId
                Type
                string | null
                Description

                Area id to attach (from the schedule read's areas); null or omitted leaves it unset.

              • Name
                activityTypeId
                Type
                string | null
                Description

                Activity-type id to attach (from the schedule read's activityTypes); null or omitted leaves it unset.

              • Name
                projectId
                Type
                string | null
                Description

                A live project id from get_schedule projects. When the project changes and the op sets no areaId, the event takes the area of the project. null or omitted leaves it unset.

              • Name
                priority
                Type
                integer
                Description

                0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit for 0.

              • Name
                recurrence
                Type
                string
                Description

                Repeat rule as an RRULE, e.g. "FREQ=WEEKLY;BYDAY=MO"; omit for a one-off.

              • Name
                kind
                Type
                "blocking" | "non_blocking" | "reference"
                Description

                "blocking" (default) cannot overlap others; "non_blocking" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; "reference" is something the user wants to SEE but is not doing — non-blocking, and don't move, delete, or schedule work into it unless asked. Note a non-blocking request still SEARCHES for a free slot like any other; it simply does not occupy one once placed.

              • Name
                notes
                Type
                string
                Description
              • Name
                sourceUrl
                Type
                string
                Description

                Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.

              • Name
                calendarId
                Type
                string | null
                Description

                The home calendar: a calendar id (from the calendars list or the schedule's integrations). Omit it to use the account's default calendar if one is set, else the event stays on the dial only. null keeps the event on the dial only. A calendar id requires Reassign Pro; whole-series only.

              • Name
                mirrorCalendarIds
                Type
                string[]
                Description

                The one-way copy calendars, as calendar ids. It must not contain the home calendarId. On update it REPLACES the set; [] clears it. An id already on the event may stay even if its calendar is read-only now; only an added id is checked. Adding an id requires Reassign Pro; whole-series only.

              • Name
                mirrorStyles
                Type
                map of "full" | "private" | "busy"
                Description

                How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else "Busy"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.

              • Name
                requestId
                Type
                string
                Description

                Idempotency key; reuse on retry to avoid double-booking. Only this key replays: a request without it is always booked as new.

              • Name
                earliest
                Type
                string, required
                Description

                Start of the local "YYYY-MM-DDTHH:MM" window to search.

              • Name
                latest
                Type
                string, required
                Description

                End of the search window: after earliest and at most 24 hours later; it may be on the next day.

              • Name
                autoCommitBest
                Type
                true
                Description

                Deprecated: a window always books its top-ranked free slot. Accepted so that older clients still work.

          • Name
            partial
            Type
            boolean
            Description

            Best-effort mode: apply the rows that succeed and report the rest as errors, instead of the default all-or-nothing.

          Response fields

          • Name
            timezone
            Type
            string
            Description
          • Name
            undoToken
            Type
            string
            Description
          • Name
            expiresAt
            Type
            string
            Description
          • Name
            results
            Type
            object[], required
            Description
            3 forms
            • One form: status: "ok"
              • Name
                index
                Type
                integer, required
                Description
              • Name
                result
                Type
                object, required
                Description
                2 fields
                • Name
                  event
                  Type
                  object, required
                  Description
                  26 fields
                  • Name
                    start
                    Type
                    string, required
                    Description
                  • Name
                    end
                    Type
                    string, required
                    Description
                  • Name
                    id
                    Type
                    string, required
                    Description
                  • Name
                    seriesId
                    Type
                    string
                    Description
                  • Name
                    originalDate
                    Type
                    string
                    Description
                  • Name
                    kind
                    Type
                    "blocking" | "non_blocking" | "reference", required
                    Description
                  • Name
                    name
                    Type
                    string, required
                    Description
                  • Name
                    notes
                    Type
                    string
                    Description
                  • Name
                    source
                    Type
                    "google" | "google_tasks" | "linear" | "microsoft" | "microsoft_todo" | "ticktick" | "todoist" | "reassign", required
                    Description
                  • Name
                    sourceUrl
                    Type
                    string
                    Description
                  • Name
                    meeting
                    Type
                    object
                    Description
                    2 fields
                    • Name
                      url
                      Type
                      string, required
                      Description
                    • Name
                      label
                      Type
                      string, required
                      Description
                  • Name
                    location
                    Type
                    object
                    Description
                    2 fields
                    • Name
                      text
                      Type
                      string, required
                      Description
                    • Name
                      url
                      Type
                      string
                      Description
                  • Name
                    recurrence
                    Type
                    string
                    Description
                  • Name
                    warning
                    Type
                    string
                    Description
                  • Name
                    areaId
                    Type
                    string | null, required
                    Description
                  • Name
                    activityTypeId
                    Type
                    string | null, required
                    Description
                  • Name
                    projectId
                    Type
                    string | null, required
                    Description
                  • Name
                    priority
                    Type
                    integer, required
                    Description
                  • Name
                    calendarId
                    Type
                    string | null
                    Description
                  • Name
                    mirrorCalendarIds
                    Type
                    string[]
                    Description
                  • Name
                    mirrorStyles
                    Type
                    map of "full" | "private" | "busy"
                    Description
                  • Name
                    readOnly
                    Type
                    true
                    Description
                  • Name
                    focusIntervals
                    Type
                    object
                    Description
                    2 fields
                    • Name
                      focusMin
                      Type
                      integer, required
                      Description
                    • Name
                      breakMin
                      Type
                      integer, required
                      Description
                  • Name
                    completedFocusIntervals
                    Type
                    integer
                    Description
                  • Name
                    checklist
                    Type
                    object
                    Description
                    1 fields
                    • Name
                      items
                      Type
                      object[], required
                      Description
                      3 fields
                      • Name
                        id
                        Type
                        string, required
                        Description
                      • Name
                        text
                        Type
                        string, required
                        Description
                      • Name
                        done
                        Type
                        boolean, required
                        Description
                  • Name
                    reflect
                    Type
                    object
                    Description
                    2 forms
                    • One form: Without actualStart, actualEnd
                      • Name
                        status
                        Type
                        "kept" | "skipped" | "changed" | "added", required
                        Description
                    • One form: With actualStart, actualEnd
                      • Name
                        status
                        Type
                        "changed", required
                        Description
                      • Name
                        actualStart
                        Type
                        string, required
                        Description
                      • Name
                        actualEnd
                        Type
                        string, required
                        Description
                • Name
                  replayed
                  Type
                  true
                  Description
              • Name
                warnings
                Type
                "classification_pending"[]
                Description
            • One form: status: "error"
              • Name
                index
                Type
                integer, required
                Description
              • Name
                error
                Type
                object, required
                Description
                11 fields
                • Name
                  code
                  Type
                  "conflict" | "not_found" | "validation" | "permission" | "scope" | "stale" | "read_only" | "rate_limited" | "internal", required
                  Description
                • Name
                  message
                  Type
                  string, required
                  Description
                • Name
                  issues
                  Type
                  object[]
                  Description
                  3 fields
                  • Name
                    path
                    Type
                    string | integer[], required
                    Description
                  • Name
                    message
                    Type
                    string, required
                    Description
                  • Name
                    expected
                    Type
                    string
                    Description
                • Name
                  feature
                  Type
                  string
                  Description
                • Name
                  conflictingRows
                  Type
                  object[]
                  Description
                  3 fields
                  • Name
                    entity
                    Type
                    string, required
                    Description
                  • Name
                    id
                    Type
                    string, required
                    Description
                  • Name
                    reason
                    Type
                    "changed" | "deleted" | "newly_present", required
                    Description
                • Name
                  conflictingRowsTruncated
                  Type
                  true
                  Description
                • Name
                  usage
                  Type
                  object
                  Description
                  5 fields
                  • Name
                    events
                    Type
                    integer, required
                    Description
                  • Name
                    inboxItems
                    Type
                    integer, required
                    Description
                  • Name
                    trackers
                    Type
                    integer, required
                    Description
                  • Name
                    calendars
                    Type
                    integer, required
                    Description
                  • Name
                    projects
                    Type
                    integer
                    Description
                • Name
                  reassignTargets
                  Type
                  object[]
                  Description
                  2 fields
                  • Name
                    id
                    Type
                    string, required
                    Description
                  • Name
                    name
                    Type
                    string, required
                    Description
                • Name
                  unlinkedCheckout
                  Type
                  object
                  Description
                  3 fields
                  • Name
                    sessionId
                    Type
                    string, required
                    Description
                  • Name
                    paymentReceived
                    Type
                    boolean, required
                    Description
                  • Name
                    supportUrl
                    Type
                    string, required
                    Description
                • Name
                  conflicts
                  Type
                  object[]
                  Description
                  2 forms
                  • One form: With id
                    • Name
                      start
                      Type
                      string, required
                      Description
                    • Name
                      end
                      Type
                      string, required
                      Description
                    • Name
                      id
                      Type
                      string, required
                      Description
                    • Name
                      name
                      Type
                      string, required
                      Description
                  • One form: With batchIndex
                    • Name
                      start
                      Type
                      string, required
                      Description
                    • Name
                      end
                      Type
                      string, required
                      Description
                    • Name
                      batchIndex
                      Type
                      integer, required
                      Description
                    • Name
                      name
                      Type
                      string, required
                      Description
                • Name
                  nearestSlots
                  Type
                  object[]
                  Description
                  4 fields
                  • Name
                    start
                    Type
                    string, required
                    Description
                  • Name
                    end
                    Type
                    string, required
                    Description
                  • Name
                    score
                    Type
                    number
                    Description
                  • Name
                    reason
                    Type
                    string
                    Description
            • One form: status: "skipped"
              • Name
                index
                Type
                integer, required
                Description
              • Name
                reason
                Type
                string, required
                Description

          Responses

          StatusCodesMeaning
          200—Success.
          400batch_rejectedEvery op failed, and the failed ops have different codes. The code is batch_rejected.
          401unauthorizedNo Bearer token and no session cookie, or the token is invalid, expired, or revoked. The response carries a WWW-Authenticate challenge that points at the protected-resource metadata.
          403permissionscopeA token without events:write gets scope "This token is not authorized to modify events (missing events:write scope)." An account without Reassign Pro access gets permission "Reassign needs an active subscription." The 7-day free trial includes Reassign Pro. A cookie session from another site gets permission "Cross-origin request."
          404not_foundEvery request failed with the code not_found. The areaId or activityTypeId of each request names an area or an activity type that does not exist or that the caller cannot see, or its projectId names no live project of the caller.
          409conflictAn op conflicts with the current state.
          422validationThe request body is not valid. The message names the first bad field by its path. A repeated or unknown query parameter is also a 422.
          429rate_limitedToo many requests. The edge firewall limits each IP to 2000 requests per minute across /api/v1; that 429 comes from the edge and can have a body that is not this JSON and no Retry-After header. When an edge 429 has no Retry-After, retry after 60 seconds. The app also limits each Bearer credential to 600 requests per minute, and some routes limit each user. These limits return this body. This app 429 always has Retry-After: retry after that number of seconds.
          503internalA fault on our side. The request is safe to retry.

          Most error responses: When no op of the batch applied, the body also has the results rows, so the caller sees which op failed.

          Request

          POST
          /api/v1/schedule/plan
          curl -X POST "https://reassign.app/api/v1/schedule/plan" \
            -H "Authorization: Bearer rsk_live_YOUR_TOKEN" \
            -H "Content-Type: application/json" \
            -d '{
            "requests": [
              {
                "name": "Write the launch post",
                "durationMinutes": 90,
                "earliest": "2026-08-14T09:00",
                "latest": "2026-08-14T18:00",
                "areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
                "projectId": "f3a4b5c6-d7e8-4f90-a1b2-c3d4e5f60718",
                "priority": 3,
                "requestId": "launch-post-0814"
              }
            ]
          }'

          Response

          {
            "timezone": "Europe/Ljubljana",
            "undoToken": "00000000-0000-4000-8000-000000000001",
            "expiresAt": "2026-08-13T09:12:00.000Z",
            "results": [
              {
                "index": 0,
                "status": "ok",
                "result": {
                  "event": {
                    "id": "b7f1c2a0-1d2e-4f3a-9b8c-5d6e7f801234",
                    "start": "2026-08-14T11:00",
                    "end": "2026-08-14T12:30",
                    "kind": "blocking",
                    "name": "Write the launch post",
                    "source": "reassign",
                    "areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
                    "activityTypeId": null,
                    "projectId": "f3a4b5c6-d7e8-4f90-a1b2-c3d4e5f60718",
                    "priority": 3
                  }
                }
              }
            ]
          }

          POST/api/v1/actions/undo

          Undo a change

          Reverse one or more recent writes. Send 1 to 20 tokens. Each token is the undoToken of a write that recorded an undo receipt. Scope: events:write.

          • A token is valid until its expiresAt, 30 minutes after the write.
          • You can use a token one time only.
          • The results rows are in the order of tokens. The server undoes the newest write first. Thus two tokens that change one row work in any order.
          • The undo stops when a row that the write changed has a newer change. Refer to Stale tokens.
          • The response has only results. An undo does not return a new undoToken. You cannot undo an undo.

          These routes can return an undoToken when the server records an undo receipt: POST /events, POST /schedule/plan, POST /reviews/{date}, POST /backlog, POST /categories, and POST /command. The tracker and moment routes return no undoToken. Refer to Moments & trackers.

          Row results

          Each ok row has one shape: { reverted, restored, removed, voided, occurrenceRestored? }. The counts count the rows that the undo changed.

          FieldValue
          revertedThe total: restored + removed + voided
          restoredThe rows that the undo put back
          removedThe rows that the undo deleted or marked as deleted
          voidedThe open proposals that the undo cancelled; current plan calls create none, so their undo returns 0
          occurrenceRestoredThe occurrences of a series that the undo put back. It is a part of restored. The field is there only when it is more than 0.

          The four counts reverted, restored, removed, and voided are always there. A count is 0 when nothing of that kind changed. A calendar link or a task link is not a counted row.

          Write that you undoCounts that can be more than 0
          A planremoved (the booked events)
          An event write, a day review, a command, a category write, or an Inbox writerestored and removed

          The undo of an Inbox capture to a task list cancels the task create when the server did not send it yet. When the task exists, the undo deletes it in its app. Linear cannot delete an issue, so the undo closes it.

          Stale tokens

          The server stores a stamp of each row that a write changed. The undo compares each row with its stamp. A sync that changes only the bookkeeping fields of a row does not change the stamp. The stamp of an event or an Inbox item includes its project and its priority. A token from before projects stays valid while the row has no project and the priority 0.

          The undo fails the token row with stale in these cases:

          • A row that the write changed has a newer change.
          • A row is gone, or a row that the write did not delete is now deleted.
          • The token is from before the stamps.
          • A category undo would delete a category that the write made, and an event, an Inbox item, a tracker, or a calendar default now uses it.
          • A user changed the area, the activity type, the project, or the priority of an event or an Inbox item by hand. An AI classification after the write does not make the token stale.
          • A category undo would show a shared default again, and a category of the same type now has its name.

          A stale row changes nothing. A token that an undo already used is validation, not stale.

          A stale row from a stamp check has error.conflictingRows: up to 50 items { entity, id, reason }. error.conflictingRowsTruncated: true shows that more rows block the undo. A token from before the stamps, and a category refusal, have no conflictingRows.

          FieldValue
          entityThe stored type of the row: sections (events), backlog_blocks (Inbox items), source_links (calendar and task links), day_reviews, moment_entries (moments), moments (trackers), source_calendars (calendars), source_projects (Linear projects), areas, activity_types, or projects
          idThe id of the row
          reasonchanged: the row changed after the write. deleted: the row is gone. newly_present: a row that the write removed is there again.

          Item errors

          Causeerror.messageerror.code
          The token is not a UUIDUnknown token "<token>".validation
          An unknown tokenUnknown token "<token>".not_found
          A token that you already usedNothing to undo for this token (status: <status>).validation
          The token expiredThe 30-minute undo window has passed; the change stays.validation
          A calendar sync sends the change nowA calendar sync is sending this change now. Try the undo again in a moment.conflict
          A row has a newer change. The row also has conflictingRows.A row that this write changed has a newer change. The undo stops, so that it does not overwrite it. Nothing changed.stale
          The token has no stampsThis undo token is from an older version and cannot be checked. Undo is not available for it.stale
          A category that the write created now has a linkAn event, an Inbox item, a tracker or a calendar now uses a category that this write created. The undo stops, so that it does not clear that link. Nothing changed.stale
          A category of the same type now has the name of a hidden shared defaultA category named "<name>" now exists. The undo stops, so that the list does not show two of them. Nothing changed.stale
          A project that the write created now has a linkAn event, an Inbox item, a calendar or a Linear project now uses a project that this write created. The undo stops, so that it does not clear that link. Nothing changed.stale
          The undo gives a project the name of a different live projectA project named <name> now exists in <area>. The undo stops, so that the list does not show two of them. Nothing changed.stale
          The Linear project of a relink now feeds a different project, or the old project is gone or archivedThe Linear project that this write linked now feeds another project, or the old project is gone or archived. The undo stops. Nothing changed.stale
          The list or the Linear project of a split now feeds a different project, or the old project is gone or archivedThe list or Linear project that this write split now feeds another project, or the old project is gone or archived. The undo stops. Nothing changed.stale
          The token has a damaged category entryThis undo token has a malformed taxonomy relink entry. Undo is not available for it.validation

          A sync race changes nothing. Send the undo again after a short time. Do not send a stale token again: it fails again. When all the rows of the call fail with conflict, or all fail with stale, the status is 409. A mix of codes gives 400 with batch_rejected.

          Request body

          • Name
            tokens
            Type
            string[], required
            Description

            The undoToken from an earlier write’s successfully recorded undo receipt.

          Response fields

          • Name
            results
            Type
            object[], required
            Description
            3 forms
            • One form: status: "ok"
              • Name
                index
                Type
                integer, required
                Description
              • Name
                result
                Type
                object, required
                Description
                5 fields
                • Name
                  reverted
                  Type
                  integer, required
                  Description
                • Name
                  restored
                  Type
                  integer, required
                  Description
                • Name
                  removed
                  Type
                  integer, required
                  Description
                • Name
                  voided
                  Type
                  integer, required
                  Description
                • Name
                  occurrenceRestored
                  Type
                  integer
                  Description
              • Name
                warnings
                Type
                "classification_pending"[]
                Description
            • One form: status: "error"
              • Name
                index
                Type
                integer, required
                Description
              • Name
                error
                Type
                object, required
                Description
                11 fields
                • Name
                  code
                  Type
                  "conflict" | "not_found" | "validation" | "permission" | "scope" | "stale" | "read_only" | "rate_limited" | "internal", required
                  Description
                • Name
                  message
                  Type
                  string, required
                  Description
                • Name
                  issues
                  Type
                  object[]
                  Description
                  3 fields
                  • Name
                    path
                    Type
                    string | integer[], required
                    Description
                  • Name
                    message
                    Type
                    string, required
                    Description
                  • Name
                    expected
                    Type
                    string
                    Description
                • Name
                  feature
                  Type
                  string
                  Description
                • Name
                  conflictingRows
                  Type
                  object[]
                  Description
                  3 fields
                  • Name
                    entity
                    Type
                    string, required
                    Description
                  • Name
                    id
                    Type
                    string, required
                    Description
                  • Name
                    reason
                    Type
                    "changed" | "deleted" | "newly_present", required
                    Description
                • Name
                  conflictingRowsTruncated
                  Type
                  true
                  Description
                • Name
                  usage
                  Type
                  object
                  Description
                  5 fields
                  • Name
                    events
                    Type
                    integer, required
                    Description
                  • Name
                    inboxItems
                    Type
                    integer, required
                    Description
                  • Name
                    trackers
                    Type
                    integer, required
                    Description
                  • Name
                    calendars
                    Type
                    integer, required
                    Description
                  • Name
                    projects
                    Type
                    integer
                    Description
                • Name
                  reassignTargets
                  Type
                  object[]
                  Description
                  2 fields
                  • Name
                    id
                    Type
                    string, required
                    Description
                  • Name
                    name
                    Type
                    string, required
                    Description
                • Name
                  unlinkedCheckout
                  Type
                  object
                  Description
                  3 fields
                  • Name
                    sessionId
                    Type
                    string, required
                    Description
                  • Name
                    paymentReceived
                    Type
                    boolean, required
                    Description
                  • Name
                    supportUrl
                    Type
                    string, required
                    Description
                • Name
                  conflicts
                  Type
                  object[]
                  Description
                  2 forms
                  • One form: With id
                    • Name
                      start
                      Type
                      string, required
                      Description
                    • Name
                      end
                      Type
                      string, required
                      Description
                    • Name
                      id
                      Type
                      string, required
                      Description
                    • Name
                      name
                      Type
                      string, required
                      Description
                  • One form: With batchIndex
                    • Name
                      start
                      Type
                      string, required
                      Description
                    • Name
                      end
                      Type
                      string, required
                      Description
                    • Name
                      batchIndex
                      Type
                      integer, required
                      Description
                    • Name
                      name
                      Type
                      string, required
                      Description
                • Name
                  nearestSlots
                  Type
                  object[]
                  Description
                  4 fields
                  • Name
                    start
                    Type
                    string, required
                    Description
                  • Name
                    end
                    Type
                    string, required
                    Description
                  • Name
                    score
                    Type
                    number
                    Description
                  • Name
                    reason
                    Type
                    string
                    Description
            • One form: status: "skipped"
              • Name
                index
                Type
                integer, required
                Description
              • Name
                reason
                Type
                string, required
                Description

          Responses

          StatusCodesMeaning
          200—Success.
          400batch_rejectedEvery op failed, and the failed ops have different codes. The code is batch_rejected.
          401unauthorizedNo Bearer token and no session cookie, or the token is invalid, expired, or revoked. The response carries a WWW-Authenticate challenge that points at the protected-resource metadata.
          403permissionscopeA token without events:write gets scope "This token is not authorized to modify events (missing events:write scope)." An account without Reassign Pro access gets permission "Reassign needs an active subscription." The 7-day free trial includes Reassign Pro. A cookie session from another site gets permission "Cross-origin request."
          404not_foundAn op names an item that does not exist.
          409conflictThe request conflicts with the current state: conflict "A calendar sync is sending this change now. Try the undo again in a moment." or stale "A row that this write changed has a newer change. The undo stops, so that it does not overwrite it. Nothing changed." or stale "This undo token is from an older version and cannot be checked. Undo is not available for it."
          422validationThe request body is not valid. The message names the first bad field by its path. A repeated or unknown query parameter is also a 422.
          429rate_limitedToo many requests. The edge firewall limits each IP to 2000 requests per minute across /api/v1; that 429 comes from the edge and can have a body that is not this JSON and no Retry-After header. When an edge 429 has no Retry-After, retry after 60 seconds. The app also limits each Bearer credential to 600 requests per minute, and some routes limit each user. These limits return this body. This app 429 always has Retry-After: retry after that number of seconds.
          503internalA fault on our side. The request is safe to retry.

          Most error responses: When no op of the batch applied, the body also has the results rows, so the caller sees which op failed.

          Request

          POST
          /api/v1/actions/undo
          curl -X POST "https://reassign.app/api/v1/actions/undo" \
            -H "Authorization: Bearer rsk_live_YOUR_TOKEN" \
            -H "Content-Type: application/json" \
            -d '{
            "tokens": [
              "00000000-0000-4000-8000-000000000001"
            ]
          }'

          Response

          {
            "results": [
              {
                "index": 0,
                "status": "ok",
                "result": {
                  "reverted": 1,
                  "restored": 1,
                  "removed": 0,
                  "voided": 0
                }
              }
            ]
          }