Events
An event is one block of time on the Reassign 24-hour planner. Use these routes to poll for changes, to read and search events, and to write events.
The machine-readable spec of all public endpoints: openapi.json.
| Route | Scope |
|---|---|
GET /events, GET /events/{id}, GET /events/search | events:read or events:write |
POST /events | events:write |
The events:write scope also gives read access. Each route needs a trial or Pro plan. Refer to Authentication and Errors.
- On
POST /events, Reassign checks the scope before it reads the body. A token withoutevents:writegets403with the codescope, also when the body is not valid. - The old event routes are removed:
POST /events/batch,PATCH /events/{id},DELETE /events/{id}, andGET /reviews/{date}. A call to one of them gets401without valid auth. Else it gets404with the codenot_found. UsePOST /eventsin their place.
To read the events of one or more days, use GET /schedule. Refer to Scheduling.
The event model
The API uses one event object in all reads and all write echoes. Refer to Concepts for the full planner model.
Time spans
- A span is
startandend. Each value is a local datetime"YYYY-MM-DDTHH:MM", with no seconds and no offset. - The times are in the time zone of the account. Each response that has a span gives the time zone one time, in the top-level
timezonefield. endmust be afterstart. An overnight event ends on the next date, for examplestart"2026-09-23T22:00"andend"2026-09-24T01:00".- An event that ends at midnight ends at
"<next day>T00:00", for example"2026-09-24T00:00". - The day of the event is the date part of
start. POST /eventsrefuses an event shorter than 5 minutes or longer than 168 hours (7 days).
Ids of recurring events
- A bare series id addresses the full series.
seriesId@YYYY-MM-DDaddresses one occurrence. Reads give each occurrence this id.- Each occurrence of a series has the fields
seriesIdandoriginalDate. They are the two parts of its id, also on a moved occurrence. A one-off event and a series echo by its bare id do not have them. - A changed occurrence keeps the id
seriesId@<original date>, also after a move to another day. Thus the date part can be different from the date ofstart. scope: "future"is the only scope value. Use it only with an occurrence id. It addresses that occurrence and all later occurrences.- An occurrence id on an event that does not repeat is an error. A date that is not an occurrence of the rule is also an error.
- When you change one occurrence, its id does not change. The reads,
GET /events/search,GET /events/{id}, and the write result giveseriesId@<original date>. - An
updateon the occurrence id of a deleted occurrence puts the occurrence back, with the fields that you send. An undo deletes it again. - A changed occurrence carries the series'
recurrence. It also inherits the series'calendarId,mirrorCalendarIds, andmirrorStylesunless it chose its own calendar. - Older write results gave a changed occurrence a separate stored id. That id still works as a write address. No read gives it now.
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
- An optional value that is empty is not in the object. For example, an event with no notes has no
notesfield. areaId,activityTypeId, andprojectIdare always in the object. The value isnullwhen the event has no area, no activity type, or no project.priorityis always in the object:0none,1low,2medium,3high, or4urgent.- An event that you schedule from the Inbox takes the project of its Inbox item.
- The API refers to areas, activity types, and projects by id only.
GET /schedulegives theareas,activityTypes, andprojectslists with the names. readOnly: trueshows an event on a calendar that the user does not own. The API refusesupdate,shift, anddeleteon it withread_only(403). The message isThis event is read-only here. Make this change in its source calendar ("<calendar>"). Nothing changed.The part in parentheses is there only when Reassign knows the calendar name. Thereflectandchecklistops work on it.- One
updateworks on a read-only event:calendarId: nullon the bare series id. The edits that the op carries also apply, because the event is local after the op.
Writable and output-only fields
You can copy the writable fields of a read into a write without a change. The server calculates the output-only fields. A write op that sends an output-only field fails with validation.
| Field | On a write |
|---|---|
id | update: the address. An occurrence id from a read works. create: optional, and it must be a UUID. The server makes a UUID when you do not send one. |
start, end, kind, name, notes, sourceUrl, recurrence, areaId, activityTypeId, projectId, priority, calendarId, mirrorCalendarIds, mirrorStyles, focusIntervals | Writable on create and update. |
checklist | Writable on create. After that, use the checklist op. Its items have the shape of checklist.items in a read. |
source, meeting, location, warning, readOnly, completedFocusIntervals, reflect, seriesId, originalDate | Output-only. To write reflect, use the reflect op. |
The warning field shows a start time that a daylight saving change skips on that date.
Search results also have an output-only score for the name match. Leave it out when building a write from a search result.
Poll for changes (Beta)
This route is in Beta. The response can change.
Get the stored events that changed after a cursor, oldest first. Use it to keep a copy of the events in sync. Scope: events:read.
- On the first poll, do not send
cursor. - Each response has a
cursor. Send it ascursoron the next poll. Do not change or parse it. - A cursor that this API did not write returns 422
validation. limitis 1 to 500. The default is 100. Other values return 422.- When
hasMoreistrue, more rows wait. Send the next poll at once. - The cursor holds the exact position of the last row. A page boundary does not skip or repeat a row.
- When no event changed, the response has no rows and a
cursorthat you can send again.
The rows are different from the event model:
- The response has one row for each stored event. It does not expand a recurring event into its occurrences.
- A changed occurrence is a separate stored event. Its row has the stored id of that event, not
seriesId@<original date>. No other read gives this id.GET /events/{id}with it returns the occurrence with the idseriesId@<original date>. - The response does not show deleted events.
- A row has only
id,name,start,end,recurrence(for a series),areaId,activityTypeId, andupdatedAt.updatedAtis an ISO 8601 instant. - An event with no name has the name
"(untitled)".
To read a day, use GET /schedule.
Query parameters
- Name
cursor- Type
- string
- Description
The opaque
cursorof the last poll. The rows that changed after it return. Omit it on the first poll.
- Name
limit- Type
- string
- Description
The page size, 1 to 500 (default 100).
Response fields
- Name
events- Type
- object[], required
- Description
8 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
- Description
- Name
areaId- Type
- string | null, required
- Description
- Name
activityTypeId- Type
- string | null, required
- Description
- Name
updatedAt- Type
- string, required
- Description
- Name
cursor- Type
- string, required
- Description
- Name
hasMore- Type
- boolean, required
- Description
- Name
timezone- Type
- string, required
- Description
Responses
| Status | Codes | Meaning |
|---|---|---|
200 | — | Success. |
401 | unauthorized | No 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. |
403 | permissionscope | A 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." |
422 | validation | A 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. |
429 | rate_limited | Too 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. |
503 | internal | A fault on our side. The request is safe to retry. |
Request
curl "https://reassign.app/api/v1/events" \
-H "Authorization: Bearer rsk_live_YOUR_TOKEN"Response
{
"events": [
{
"id": "b7f1c2a0-1d2e-4f3a-9b8c-5d6e7f801234",
"name": "Team sync",
"start": "2026-08-13T09:00",
"end": "2026-08-13T10:30",
"areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
"activityTypeId": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
"updatedAt": "2026-08-13T08:40:00.000Z"
}
],
"cursor": "MjAyNi0wOC0xM1QwODo0MDowMC4xMjM0NTZafGI3ZjFjMmEwLTFkMmUtNGYzYS05YjhjLTVkNmU3ZjgwMTIzNA",
"hasMore": false,
"timezone": "Europe/Ljubljana"
}Write events
Create, change, move, reflect, and delete events. This route is the one event write of the API. Send 1 to 50 ops, and an optional partial. Scope: events:write.
Ops
Each op has an op field with its name.
op | What it does |
|---|---|
create | Makes an event. Send start, end, and name. Add recurrence (an RRULE) for a series. |
update | Changes an event. Send id and only the fields to change. A new start or end moves the event, also to another day. A start with no end keeps the duration. An end with no start keeps the start. |
shift | Moves an event by byMinutes (a whole number, not 0, from -1440 to 1440). A negative value moves it earlier. The duration and the exact minute stay. |
reflect | Records how a past event went: status is kept, skipped, changed, or added. Refer to Day reviews. |
checklist | Changes the checklist. items replaces the full list (100 items or less). check and uncheck take item ids (100 or less). |
delete | Deletes an event, a series, one occurrence, or (with scope: "future") an occurrence and all later ones. |
clear | Deletes all events from from to to, both dates included. The range is 31 days or less. |
Examples of tasks
| Task | Op to send |
|---|---|
| Add a meeting tomorrow from 09:00 to 10:00 | create with start "2026-09-24T09:00", end "2026-09-24T10:00", and name |
| Add an event from 22:00 to 01:00 | create with an end on the next date |
| Move an event to tomorrow at 09:00 | update with id and start "2026-09-24T09:00" |
| Make an event end at 18:00 | update with id and end only |
| Move an event 30 minutes later | shift with byMinutes 30 |
| Remove the area of an event | update with areaId null |
| Put an event in a project | update with projectId |
| Mark an event as urgent | update with priority 4 |
| Change one occurrence of a series | update with the id seriesId@2026-09-24 |
| Change an occurrence and all later ones | update with the id seriesId@2026-09-24 and scope "future" |
| Stop a series | update with the bare series id and recurrence null |
| End a series before a date | delete with the id seriesId@2026-09-24 and scope "future" |
| Mark a past event as done | reflect with status "kept" |
| Record the real time of a past event | reflect with status "changed", actualStart, and actualEnd |
| Tick off a checklist item | checklist with check and the item id |
| Delete all events of a week | clear with from and to |
Rules of the fields
areaIdandactivityTypeIdtake an id ornull. Onupdate,nullremoves the link, and an omitted key keeps the link. Oncreate,nulland an omitted key are the same.- On
create,kindis a manual choice, also the defaultblocking. AI classification does not change it. - On
create, anareaIdor anactivityTypeIdthat you send is a manual choice. A field with no id stays open for AI classification. - On
update,areaId: nulloractivityTypeId: nullis a manual choice of no link. AI classification does not fill that field again, also when it was already empty. projectIdtakes the id of a live project from theprojectslist ofGET /schedule. Onupdate,nullremoves the project and keeps the area. An omitted key keeps the project. Oncreate,nulland an omitted key are the same.- When an op sets a new project and no
areaId, the event takes the area of the project. This also replaces an area that you set before. It also applies to an op on an occurrence id. - An unknown project, or an archived project, fails the row with
not_found:No live project with id "<id>".An archived project that the event already has can stay. - On an event from a task of a task app, a new
projectIdthat needs a move of the task fails withread_only:A scheduled task keeps the project of its list. Change the project in the Inbox.Change the project in the Inbox. priorityis a whole number from 0 to 4. Oncreate, an omittedpriorityis0. Onupdate, an omittedprioritykeeps the value.- An undo puts back the project, the priority, and the area of the event.
- On an event that came from a task of a task app, a
prioritychange can also go to the task in its app. Reassign sends it only after a pull of the task records its priority. Refer to Backlog. calendarIdis the home calendar. Oncreate, sendnullto keep the event only on the dial. When you omit it, the event goes to the default calendar of the account, if one is set. Otherwise it stays on the dial only.mirrorCalendarIdslists the calendars that get a one-way copy. Onupdate,[]removes all copies.- On
update, an omittedcalendarIdkeeps the home calendar.mirrorCalendarIdschecks only the ids that the op adds. An id that is already on the event can stay, also when its calendar is now read-only or disconnected. - On
update,calendarId: nullremoves the event from its home calendar. It also deletes all the copies inmirrorCalendarIds. The event then stays on the dial only.- Send it with the bare series id and no
scope. An occurrence id or ascopeis avalidationerror. - It can carry
start,end,name,notes,areaId,activityTypeId,projectId,priority, andkind. These edits apply first, in the same write. - With
mirrorCalendarIds,mirrorStyles,recurrence,recurrenceEnd,sourceUrl, orfocusIntervals, it is avalidationerror. Send that change in a separate op. - On an event that is already on the dial only,
calendarId: nullis not a change. The copies stay. To remove them, sendmirrorCalendarIds: [].
- Send it with the bare series id and no
- A one-off event on the dial only can have copies. On
create, sendcalendarId: nullwithmirrorCalendarIds. - A series with copies needs a home calendar. These ops fail with
validationand the messageCopies of a series need a home calendar. Give the series a calendarId, or remove its mirrorCalendarIds.:- A
createwithrecurrence,mirrorCalendarIds, andcalendarId: null. An omittedcalendarIdalso fails when the account has no default calendar. - An
updatethat addsrecurrenceto a dial-only event with copies. - An
updatethat addsmirrorCalendarIdsto a dial-only series.
- A
- A series that came from a connected calendar is an exception. After
calendarId: null, Reassign keeps the identity of the calendar series. Anupdatecan then addmirrorCalendarIds. A read does not show this identity. mirrorStylessets how much each copy shows. Refer to Copy styles.- On
update,sourceUrl: nullremoves the link,recurrence: nullstops the repeat, andfocusIntervals: nullremoves the focus rhythm. recurrenceEndneedsrecurrence.focusIntervalsis valid only on a blocking event.recurrence,calendarId,mirrorCalendarIds,mirrorStyles, andsourceUrlbelong to the full series. On one occurrence, the same value as now is not a change. A new value is an error.- An update that moves a series to another day needs a rule that occurs on that day.
- The API rejects a key that it does not know, and a key that has no effect.
Copy styles
mirrorStyles maps a copy calendar id to a style. A read gives it only when the event has a style. Use busy to block the time on a second calendar and hide the details.
| Style | Title of the copy | Notes of the copy | At the provider |
|---|---|---|---|
full | The event title | The event notes | A normal event |
private | The event title | The event notes | A private event |
busy | The busy title of the copy calendar, or "Busy" | None | A private event with no reminders |
- Each key must be in the
mirrorCalendarIdsof the op. When anupdatehas nomirrorCalendarIds, the current copies apply. Else the op fails withvalidation:mirrorStyles has calendar "<id>", which is not in the event's mirrorCalendarIds. Add it to mirrorCalendarIds, or remove it from mirrorStyles. - A value that is not
full,private, orbusyfails the schema check withvalidation. The row haserror.issueswith a path of["mirrorStyles", "<id>"]. Refer to Validation errors. - On
create,{}is the same as no map. Onupdate,mirrorStylesreplaces the map.{}removes all styles. - A calendar that is not in the map uses the default style of that calendar. Without a default, the style is
full.GET /schedulegives the default asintegrations.sources[].calendars[].copyStyle. - A
privateorbusycopy of anon_blockingorreferenceevent shows as free. - The style belongs to the full series. On an occurrence id or with
scope, a new value fails withvalidation. - A changed occurrence inherits the styles of its series.
The reflect op
- The occurrence must be on a past day in the account's time zone. Today and future days fail with
validation, even when today's event has already ended. actualStartandactualEndgo together. Send them only withchangedoradded.- With
added, the actual times become the time of the event.actualStartmust be on the day of the event. - To mark one occurrence of a series, send its occurrence id. A bare series id is an error.
- The actual span must be from 5 minutes to 168 hours. Else the row fails with
Event is too short (minimum 5 minutes).orEvent is too long (maximum 168 hours).
Order and batch rules
- The API applies the ops in their order. An op sees the result of the ops before it. For example, a
deletefrees the time for a latercreate. - The API reads the result rows after all ops commit. Thus a later op can change the row of an earlier op, for example a
scope: "future"split. - An op can target an event id one time only in each call. A second op on the same id is an error row.
- A call can have one
scope: "future"op for each series. It cannot also have an op on the bare series id. The later op is avalidationerror row. - A
scope: "future"update also changes an overridden occurrence on the split date. With a newstartorend, it replaces that override with the new series occurrence. With other fields, it applies those fields to the override, keeps its own time, and returns that occurrence. Later overrides keep their individual fields. - A
scope: "future"split of a dial-only series with copies gives the new series no copies and nomirrorStyles. The old series keeps its copies. - A blocking event that overlaps another blocking event fails with
conflict. The error row hasconflicts. It can also have up to 3nearestSlots. - A
non_blockingorreferenceevent can overlap other events. It does not cause a conflict.
Atomic and partial batches
By default, the batch is atomic. When one op fails, the API applies no op. Each valid op then has status: "skipped" and a reason.
With partial: true, the API applies each op that it can. The failed ops are error rows.
- When one or more ops apply, the status is
200. The body hasresults, andundoTokenwithexpiresAtwhen the server recorded an undo receipt. - Reassign does not reject a batch after its writes land. When the read of a written op fails after the write, that op is an
errorrow with the codeinternaland the messageThe change was saved, but the read-back failed. Read it again.The body keeps any recordedundoToken. - When no op applies, the body is the error envelope and
results. The status followserror.code, as the Responses table shows.
The top-level timezone is there only when a row has a span: a created or updated event, conflicts, or nearestSlots. For example, a batch of only delete or clear ops has no timezone.
A batch where no op applies is a rejected batch. This is also true for partial: true when all ops fail. The error.message of a rejected batch is the message of the one failed op. When more ops fail, it tells you to look in results. A rejected batch has no undoToken.
Rows
Each item of results has index (0-based), status (ok, error, or skipped), and one of result, error, or reason.
An ok row can also have warnings: ["classification_pending"]. The write succeeded and queued AI classification. AI classification can fill eligible fields after the reply, for example an area that you did not set. It does not change the kind of a create, or an areaId or activityTypeId that a create sent. This warning appears only when the account and plan allow classification. Read the event again if you need its latest classification.
| Op | result |
|---|---|
create | created: the new event. Also firstOccurrence when the series does not occur on the day of start. |
update, shift, reflect, checklist | updated: the event after the change. Also firstOccurrence when a new rule does not occur on the stored first day. |
delete | deletedIds. A scope: "future" delete also gives updated: the series that now ends earlier. |
clear | breakdown (counts of one-off events, occurrences, and changed occurrences), items (up to 50 names and dates), and truncated. Also skippedReadOnly (a count) when it kept events of a read-only calendar. |
An op that the API cannot read does not fail the full request. It becomes an error row with the code validation. The message names the problem, for example an unknown op or a bad field. The full request fails with 422 only when the body is not valid, for example when ops is empty or has more than 50 items. These items are also error rows:
| Item | error.message |
|---|---|
Not an object (also null or an array) | Each op must be an object. |
An unknown op | Unknown op "<op>". Use one of: create, update, shift, reflect, checklist, delete, clear. |
An object with no op | Unknown op undefined. Use one of: create, update, shift, reflect, checklist, delete, clear. |
| A bad field | Invalid "<op>" op. `<path>`: <reason>, for example Invalid "create" op. `start`: … |
A create id that is not a UUID | Invalid "create" op. `id`: id must be a UUID; omit it to let the server generate one. |
Each of these rows also has error.issues. Refer to Validation errors.
Undo
A write that records an undo receipt returns one undoToken and its expiresAt (30 minutes) at the top level. Send the token to POST /actions/undo to reverse the full write. Refer to Scheduling. A write that changes nothing has no undoToken. If the server cannot record the undo, the response also has no undoToken, and the change stays. Thus, a response with no undoToken does not prove that nothing changed.
Request body
- Name
ops- Type
- object[], required
- Description
7 forms
One form:
op: "create"- Name
id- Type
- string
- Description
Optional client-minted UUID event id, so the caller can read the new event back by a known id. Omit it and the server mints one.
- Name
start- Type
- string, required
- Description
Local datetime "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Its day is the event's day.
- Name
end- Type
- string, required
- Description
Local datetime "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day.
- Name
name- Type
- string, required
- Description
- 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
checklist- Type
- object
- Description
Starter microtasks written to the new event's checklist.
1 fields
- Name
items- Type
- object[], required
- Description
3 fields
- Name
id- Type
- string
- Description
Keep an existing item's id; omit for a new item.
- Name
text- Type
- string, required
- Description
- Name
done- Type
- boolean
- Description
true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).
- Name
areaId- Type
- string | null
- Description
The area id (from the schedule read). null or omitted leaves it unset.
- Name
activityTypeId- Type
- string | null
- Description
The activity type id (from the schedule read). 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
How the event repeats, as an RRULE (e.g. "FREQ=WEEKLY;BYDAY=MO,WE,FR"). Omit for a one-off.
- Name
recurrenceEnd- Type
- string
- Description
Inclusive last day of the repeat, "YYYY-MM-DD". Needs
recurrence.
- 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 isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.
- Name
focusIntervals- Type
- object
- Description
Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it.
2 fields
- Name
focusMin- Type
- integer, required
- Description
- Name
breakMin- Type
- integer, required
- Description
- 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.
One form:
op: "update"- Name
id- Type
- string, required
- Description
The event id from a read. A bare series id addresses the whole series;
seriesId@YYYY-MM-DDaddresses one occurrence by its ORIGINAL date (the read'soriginalDate), also after the occurrence moved.
- Name
scope- Type
- "future"
- Description
Only with a
seriesId@YYYY-MM-DDid: "future" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.
- Name
start- Type
- string
- Description
Local datetime "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A new start moves the event, also to another day (on an occurrence id, that occurrence only). A lone start keeps the duration.
- Name
end- Type
- string
- Description
Local datetime "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A lone end keeps the start.
- Name
name- Type
- string
- Description
- Name
notes- Type
- string
- Description
- Name
sourceUrl- Type
- string | null
- 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
areaId- Type
- string | null
- Description
The area id (from the schedule read). null clears the link; omit to keep it.
- Name
activityTypeId- Type
- string | null
- Description
The activity type id (from the schedule read). null clears the link; omit to keep it.
- 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 clears the project and keeps the area; omit to keep it.
- Name
priority- Type
- integer
- Description
0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit to keep it.
- Name
recurrence- Type
- string | null
- Description
A new RRULE for the series; null stops the repeat.
- Name
recurrenceEnd- Type
- string
- Description
Inclusive last day of the repeat, "YYYY-MM-DD". Needs
recurrence.
- Name
kind- Type
- "blocking" | "non_blocking" | "reference"
- Description
Change the event kind: "blocking", "non_blocking", or "reference" (see-only — non-blocking, don't schedule work into it).
- Name
calendarId- Type
- string | null
- Description
Re-home the event: a calendar id (from the calendars list or the schedule's
integrations) moves it to that calendar; null unlinks it and deletes its mirror copies (keeps the dial block). An unlink may carry start, end, name, notes, areaId, activityTypeId and kind, applied first in the same write. Omit to keep the current home. 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
focusIntervals- Type
- object | null
- Description
Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it. Pass null to remove an existing rhythm.
2 fields
- Name
focusMin- Type
- integer, required
- Description
- Name
breakMin- Type
- integer, required
- Description
One form:
op: "shift"- Name
id- Type
- string, required
- Description
The event id from a read. A bare series id addresses the whole series;
seriesId@YYYY-MM-DDaddresses one occurrence by its ORIGINAL date (the read'soriginalDate), also after the occurrence moved.
- Name
byMinutes- Type
- integer, required
- Description
Minutes to shift by; negative is earlier.
- Name
scope- Type
- "future"
- Description
Only with a
seriesId@YYYY-MM-DDid: "future" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.
One form:
op: "reflect"- Name
id- Type
- string, required
- Description
The event id, echoed verbatim from a schedule or search read. To mark one occurrence of a recurring event, pass the
seriesId@YYYY-MM-DDid the read returned for that day — don't fabricate the @date yourself.
- Name
status- Type
- "kept" | "skipped" | "changed" | "added", required
- Description
How a past planned event actually went. "kept" = happened as planned; "skipped" = didn't happen; "changed" = happened but differently (pass actualStart + actualEnd to record the real time); "added" = unplanned but happened (its actualStart + actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.
- Name
actualStart- Type
- string
- Description
When it actually started. Local datetime "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualEnd, only for "changed" or "added".
- Name
actualEnd- Type
- string
- Description
When it actually ended. Local datetime "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualStart, only for "changed" or "added".
One form:
op: "checklist"- Name
id- Type
- string, required
- Description
The event id, echoed verbatim from a schedule or search read. A bare series id edits the template of the whole series; the
seriesId@YYYY-MM-DDid edits or ticks off that one occurrence.
- Name
items- Type
- object[]
- Description
REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.
3 fields
- Name
id- Type
- string
- Description
Keep an existing item's id; omit for a new item.
- Name
text- Type
- string, required
- Description
- Name
done- Type
- boolean
- Description
true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).
- Name
check- Type
- string[]
- Description
Item ids to mark DONE for the occurrence. On a recurring event this ticks off that occurrence only.
- Name
uncheck- Type
- string[]
- Description
Item ids to mark NOT-done for the occurrence.
One form:
op: "delete"- Name
id- Type
- string, required
- Description
The event id from a read. A bare series id addresses the whole series;
seriesId@YYYY-MM-DDaddresses one occurrence by its ORIGINAL date (the read'soriginalDate), also after the occurrence moved.
- Name
scope- Type
- "future"
- Description
Only with a
seriesId@YYYY-MM-DDid: "future" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.
One form:
op: "clear"- Name
from- Type
- string, required
- Description
First day to clear, ISO "YYYY-MM-DD".
- Name
to- Type
- string, required
- Description
Last day to clear (inclusive), ISO "YYYY-MM-DD". Equal to
fromfor one day.
- Name
partial- Type
- boolean
- Description
Apply the ops that succeed instead of 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
4 forms
One form: With
created- Name
created- 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
firstOccurrence- Type
- string
- Description
One form: With
updated- 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
firstOccurrence- Type
- string
- Description
One form: With
deletedIds- Name
deletedIds- Type
- string[], required
- Description
- Name
updated- Type
- object
- 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
One form: With
breakdown,items,truncated- Name
breakdown- Type
- object, required
- Description
3 fields
- Name
oneOff- Type
- integer, required
- Description
- Name
recurringOccurrence- Type
- integer, required
- Description
- Name
override- Type
- integer, required
- Description
- Name
items- Type
- object[], required
- Description
2 fields
- Name
date- Type
- string, required
- Description
- Name
name- Type
- string, required
- Description
- Name
truncated- Type
- boolean, required
- 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
| Status | Codes | Meaning |
|---|---|---|
200 | — | Success. |
400 | batch_rejected | Every op failed, and the failed ops have different codes. The code is batch_rejected. |
401 | unauthorized | No 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. |
403 | permissionscoperead_only | A 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." A rejected batch also answers 403 when every failed op has the same code: read_only (the event or the target calendar is not writable, or the op changes the kind of an all-day calendar event) or permission (a calendar sync needs Reassign Pro). |
404 | not_found | An op names an item that does not exist. |
409 | conflict | The request conflicts with the current state: conflict "The time overlaps an existing event." or conflict "The time overlaps an earlier op in this batch." or conflict "An event with this ID already exists." |
422 | validation | The 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. |
429 | rate_limited | Too 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. |
503 | internal | A 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
curl -X POST "https://reassign.app/api/v1/events" \
-H "Authorization: Bearer rsk_live_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ops": [
{
"op": "create",
"name": "Deep work",
"start": "2026-08-14T09:00",
"end": "2026-08-14T10:30",
"areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
"activityTypeId": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
"notes": "Draft the launch post.",
"calendarId": "8a1f0c2e-3b4d-4e5f-9a0b-1c2d3e4f5061"
},
{
"op": "update",
"id": "c4d5e6f7-0819-4a2b-8c3d-4e5f60718293@2026-08-15",
"start": "2026-08-15T16:00"
},
{
"op": "delete",
"id": "c4d5e6f7-0819-4a2b-8c3d-4e5f60718293@2026-08-16"
}
]
}'Response
{
"timezone": "Europe/Ljubljana",
"undoToken": "00000000-0000-4000-8000-000000000001",
"expiresAt": "2026-08-13T09:12:00.000Z",
"results": [
{
"index": 0,
"status": "ok",
"result": {
"created": {
"id": "b7f1c2a0-1d2e-4f3a-9b8c-5d6e7f801234",
"start": "2026-08-14T09:00",
"end": "2026-08-14T10:30",
"kind": "blocking",
"name": "Deep work",
"notes": "Draft the launch post.",
"source": "reassign",
"areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
"activityTypeId": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
"projectId": null,
"priority": 0,
"calendarId": "8a1f0c2e-3b4d-4e5f-9a0b-1c2d3e4f5061"
}
}
},
{
"index": 1,
"status": "ok",
"result": {
"updated": {
"id": "c4d5e6f7-0819-4a2b-8c3d-4e5f60718293@2026-08-15",
"seriesId": "c4d5e6f7-0819-4a2b-8c3d-4e5f60718293",
"originalDate": "2026-08-15",
"start": "2026-08-15T16:00",
"end": "2026-08-15T17:30",
"kind": "blocking",
"name": "Deep work",
"recurrence": "FREQ=DAILY",
"source": "reassign",
"areaId": "3c9d2a41-6b7e-4f80-9a1b-2c3d4e5f6071",
"activityTypeId": "5e6f7081-92a3-4b4c-8d5e-6f708192a3b4",
"projectId": null,
"priority": 0
}
}
},
{
"index": 2,
"status": "ok",
"result": {
"deletedIds": [
"c4d5e6f7-0819-4a2b-8c3d-4e5f60718293@2026-08-16"
]
}
}
]
}Get an event
Get one event and the timezone of its span. Scope: events:read.
- A one-off event: send its id.
- One occurrence of a series: send the occurrence id
seriesId@YYYY-MM-DD. - A bare series id returns 404
not_found. The API looks for the id in the events of the first day of the series, and there each occurrence has an occurrence id. - A changed occurrence keeps its id
seriesId@<original date>. This id finds the occurrence also after a move to another day. - A stored id of a changed occurrence from an older write result also works. The response then gives
event.idasseriesId@<original date>. - An unknown id returns 404 with the message
Event not found.
Path parameters
- Name
id- Type
- string, required
- Description
The event id, or
seriesId@YYYY-MM-DDfor one occurrence.
Response 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
timezone- Type
- string, required
- Description
Responses
| Status | Codes | Meaning |
|---|---|---|
200 | — | Success. |
401 | unauthorized | No 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. |
403 | permissionscope | A 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." |
404 | not_found | The resource that the request names does not exist. |
422 | validation | The request has a query parameter; this operation takes none. |
429 | rate_limited | Too 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. |
503 | internal | A fault on our side. The request is safe to retry. |
Request
curl "https://reassign.app/api/v1/events/EVENT_ID" \
-H "Authorization: Bearer rsk_live_YOUR_TOKEN"Response
{
"event": {
"id": "b7f1c2a0-1d2e-4f3a-9b8c-5d6e7f801234",
"start": "2026-08-13T09:00",
"end": "2026-08-13T10: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"
]
},
"timezone": "Europe/Ljubljana"
}Search events
Find events by name. The search does not look in the notes. Scope: events:read.
-
queryis required. An empty value returns 422validation. -
The default window is from 7 days before today to 30 days after
from(or after today). -
With only
to, the window starts 7 days before today. Iftois less than 30 days after that start, the window starts 30 days beforeto. If the window is then more than 92 days, it starts 91 days beforeto. -
A
tobeforefromreturns 422 with the message`to` must be on or after `from`. -
The window is 92 days or less. A wider window returns 422 with the message
Range too wide (max 92 days). -
The window includes each event that overlaps a day of the window. This includes an overnight event that started the day before. An event that ends exactly at
00:00of the first day is not in the window.timeOfDaystill uses the start time of the event. -
timeOfDaykeeps the events that start in that part of the day:timeOfDayStart time morning05:00 to 12:00 afternoon12:00 to 17:00 evening17:00 to 21:00 nightAll other times -
Each event in
eventshas the full event model and ascorefrom 0 to 1 for its name match. A series shows one time, as the occurrence that matches best, with its occurrence id. Thus a query that names a renamed occurrence gets that occurrence. When more occurrences match equally well, the search gives the one nearest to today: the first on or after today, else the last before today. -
A
scoreof1is an exact match,0.9is a prefix, and0.75is a substring. Matches below0.34are omitted. Results are best match first. -
ambiguousistruewhen more than one event matches equally well.
Query parameters
- Name
query- Type
- string, required
- Description
Text to match against event names, e.g. "standup", "gym".
- Name
from- Type
- string
- Description
Range start, ISO date, e.g. "2026-06-01". Defaults to 7 days ago.
- Name
to- Type
- string
- Description
Range end, ISO date, e.g. "2026-07-01". Defaults to +30 days.
- Name
areaId- Type
- string
- Description
Only match events linked to this area id.
- Name
activityTypeId- Type
- string
- Description
Only match events linked to this activity-type id.
- Name
timeOfDay- Type
- "morning" | "afternoon" | "evening" | "night"
- Description
Only match events that start in this part of the day.
Response fields
- Name
events- Type
- object[], required
- Description
27 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
score- Type
- number, required
- Description
- Name
ambiguous- Type
- boolean, required
- Description
- Name
timezone- Type
- string, required
- Description
Responses
| Status | Codes | Meaning |
|---|---|---|
200 | — | Success. |
401 | unauthorized | No 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. |
403 | permissionscope | A 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." |
422 | validation | A 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. |
429 | rate_limited | Too 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. |
503 | internal | A fault on our side. The request is safe to retry. |
Request
curl "https://reassign.app/api/v1/events/search?query=SEARCH_ID" \
-H "Authorization: Bearer rsk_live_YOUR_TOKEN"Response
{
"events": [],
"ambiguous": false,
"timezone": "Europe/Ljubljana"
}