Day reviews

A day review records how a past day went, compared to the plan. When you confirm a review, Reassign freezes the adherence scores of that day.

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

How a review works

  1. Mark each event of the past day with the reflect op of POST /events. Refer to Events.
  2. Confirm the day with POST /reviews/{date} and "action": "confirm". The server calculates the scores and freezes them.
  3. Read the review in GET /schedule. A confirmed day has a review block in days[].review. Refer to Scheduling.
  4. To start again, discard the review with "action": "discard".

There is no separate route to read a review. days[].review is the only public read. Its reviewedAt field shows that the day is confirmed.

You can confirm a day again. The server then calculates the scores again and replaces the snapshot. A day has one review or no review.

The reflect op

Send one reflect op for each event in the ops of POST /events.

The event's day must be before today in the account's time zone. An event on today or a future day fails with validation, even if today's event has already ended. MCP write_events follows the same rule.

statusMeaningActual times
keptThe event occurred as planned.Do not send them.
skippedThe event did not occur.Do not send them.
changedThe event occurred, but in a different way.Optional: actualStart and actualEnd together.
addedThe event was not in the plan, but it occurred.Optional: actualStart and actualEnd together. They become the time of the event.
  • actualStart and actualEnd are local datetimes "YYYY-MM-DDTHH:MM". actualEnd must be after actualStart.
  • For one occurrence of a series, use the occurrence id seriesId@YYYY-MM-DD from a read. A bare series id is an error.
  • The reflect op also works on a readOnly event.
  • A read shows the mark in the reflect field of the event.

Scores of each event

MarkScore
kept1
No mark1 (the same as kept)
skipped0
changed with no actual times, or with the planned times0.5
changed with actual times that differ from the planThe part of the planned time that the actual time covers, from 0 to 1
addedNot in the score

Events of the kind reference are not in the scores.

Adherence scores

The review block has reviewedAt (an ISO 8601 instant) and adherence. The server rounds the scores to 2 decimal places.

FieldMeaning
adherence.eventThe mean score of the planned events, weighted by duration. From 0 to 1, or null.
adherence.layerThe part of the planned time that has an area, where the actual time has the same area. From 0 to 1, or null.
adherence.plannedMinutesThe total duration of the planned events. The added events are not in this total.
adherence.unplannedMinutesThe total duration of the added events.
adherence.byAreaOne item for each area: areaId (null for the events with no area), adherence, and plannedMinutes.
adherence.byActivityTypeOne item for each activity type: activityTypeId, adherence, and plannedMinutes.
  • When the day has no planned time (plannedMinutes is 0), event and layer are null. layer is also null when no planned event has an area.
  • A snapshot that Reassign froze before this rule can have 1 in these cases. Treat a score as null when plannedMinutes is 0. Treat layer as null when no byArea item with an area has planned time.
  • A review that Reassign confirmed before it started to freeze the scores has no adherence.

Scopes

RouteScope
POST /reviews/{date}events:write
GET /schedule (to read days[].review)events:read or events:write

All routes need a trial or Pro plan. Refer to Authentication. All dates are "YYYY-MM-DD" in the time zone of the account. For the error format, refer to Errors.


POST/api/v1/reviews/{date}

Confirm or discard a review

Confirm or discard the review of one day. Send action: "confirm" or "discard". Scope: events:write.

  • A date in the path that is not a real date returns 422 with the message The path `date` must be a real ISO YYYY-MM-DD.
  • Both actions return an undoToken and its expiresAt, except a discard that changes nothing. Send the token to POST /actions/undo in 30 minutes or less to reverse the action. Refer to Scheduling.
  • If the server cannot write the undo record, the response has no undoToken. The change stays.

Confirm

confirm calculates the scores from all events of the day, except reference events, and freezes them. An event with no mark counts as kept.

  • The day must be before today, in the time zone of the account.
  • Today or a future day returns 422 validation with the message You can only reflect on a past day — pick a date before today.
  • There is no limit on how far back the day can be.
  • A day where no event has a mark also confirms. This is the same as "Looks right" in the app. The response then has a warning: No event on this day has a reflection mark. The score counts each unmarked event as kept. A day with no events gets the warning This day has no events, so the review has no score.
  • The response is date, the review block fields (reviewedAt and adherence), the warning when it applies, and the undo receipt.
  • An undo of a confirm puts back the review that the day had before, or removes the review.

Discard

discard resets the full reflection of the day:

  • It deletes the review.
  • It deletes the events that have the mark added. Their ids are in deletedIds.
  • It removes the marks and the actual times from the other marked events. These events are in updated, with their spans in timezone.

Other rules:

  • discard has no date check. It also works on today or a future day.
  • When the day has no review and no marked events, discard succeeds and changes nothing. It returns { date, timezone, updated: [], deletedIds: [], noop: true } with no undoToken.

Path parameters

  • Name
    date
    Type
    string, required
    Description

    The day, ISO "YYYY-MM-DD".

Request body

  • Name
    action
    Type
    "confirm" | "discard", required
    Description

    "confirm" freezes the adherence snapshot of the day; "discard" resets the whole reflection.

Response fields

  • One form: With reviewedAt
    • Name
      date
      Type
      string, required
      Description
    • 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
      warning
      Type
      string
      Description
    • Name
      undoToken
      Type
      string
      Description
    • Name
      expiresAt
      Type
      string
      Description
  • One form: With timezone, updated, deletedIds
    • Name
      date
      Type
      string, required
      Description
    • Name
      timezone
      Type
      string, required
      Description
    • Name
      updated
      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
      deletedIds
      Type
      string[], required
      Description
    • Name
      noop
      Type
      true
      Description
    • Name
      undoToken
      Type
      string
      Description
    • Name
      expiresAt
      Type
      string
      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: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."
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.

Request

POST
/api/v1/reviews/{date}
curl -X POST "https://reassign.app/api/v1/reviews/2026-08-14" \
  -H "Authorization: Bearer rsk_live_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "action": "confirm"
}'

Response

{
  "date": "2026-08-12",
  "reviewedAt": "2026-08-13T07:12:00.000Z",
  "adherence": {
    "event": 0.8,
    "layer": 0.74,
    "plannedMinutes": 450,
    "unplannedMinutes": 60,
    "byArea": [
      {
        "areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
        "adherence": 0.9,
        "plannedMinutes": 300
      }
    ],
    "byActivityType": [
      {
        "activityTypeId": null,
        "adherence": 0.8,
        "plannedMinutes": 450
      }
    ]
  },
  "undoToken": "00000000-0000-4000-8000-000000000001",
  "expiresAt": "2026-08-13T09:12:00.000Z"
}