Install
openclaw skills install microsoft-to-doMicrosoft To Do API integration with managed OAuth. Manage task lists, tasks, checklist items, and linked resources. Use this skill when users want to create, read, update, or delete tasks and task lists in Microsoft To Do. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.
openclaw skills install microsoft-to-doAccess the Microsoft To Do API with managed OAuth authentication. Manage task lists, tasks, checklist items, and linked resources with full CRUD operations.
# List all task lists
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/microsoft-to-do/v1.0/me/todo/lists')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/microsoft-to-do/{native-api-path}
Maton proxies requests to graph.microsoft.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Microsoft To Do OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=microsoft-to-do&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'microsoft-to-do'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "microsoft-to-do",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Microsoft To Do connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/microsoft-to-do/v1.0/me/todo/lists')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
GET /microsoft-to-do/v1.0/me/todo/lists
Response:
{
"value": [
{
"id": "AAMkADIyAAAhrbPWAAA=",
"displayName": "Tasks",
"isOwner": true,
"isShared": false,
"wellknownListName": "defaultList"
}
]
}
GET /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}
POST /microsoft-to-do/v1.0/me/todo/lists
Content-Type: application/json
{
"displayName": "Travel items"
}
Response (201 Created):
{
"id": "AAMkADIyAAAhrbPWAAA=",
"displayName": "Travel items",
"isOwner": true,
"isShared": false,
"wellknownListName": "none"
}
PATCH /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}
Content-Type: application/json
{
"displayName": "Vacation Plan"
}
DELETE /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}
Returns 204 No Content on success.
GET /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks
Response:
{
"value": [
{
"id": "AlMKXwbQAAAJws6wcAAAA=",
"title": "Buy groceries",
"status": "notStarted",
"importance": "normal",
"isReminderOn": false,
"createdDateTime": "2024-01-15T10:00:00Z",
"lastModifiedDateTime": "2024-01-15T10:00:00Z",
"body": {
"content": "",
"contentType": "text"
},
"categories": []
}
]
}
GET /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}
POST /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks
Content-Type: application/json
{
"title": "A new task",
"importance": "high",
"status": "notStarted",
"categories": ["Important"],
"dueDateTime": {
"dateTime": "2024-12-31T17:00:00",
"timeZone": "Eastern Standard Time"
},
"startDateTime": {
"dateTime": "2024-12-01T08:00:00",
"timeZone": "Eastern Standard Time"
},
"isReminderOn": true,
"reminderDateTime": {
"dateTime": "2024-12-01T09:00:00",
"timeZone": "Eastern Standard Time"
},
"body": {
"content": "Task details here",
"contentType": "text"
}
}
Task Fields:
| Field | Type | Description |
|---|---|---|
title | String | Brief description of the task |
body | itemBody | Task body with content and contentType (text/html) |
importance | String | low, normal, or high |
status | String | notStarted, inProgress, completed, waitingOnOthers, deferred |
categories | String[] | Associated category names |
dueDateTime | dateTimeTimeZone | Due date and time |
startDateTime | dateTimeTimeZone | Start date and time |
completedDateTime | dateTimeTimeZone | Completion date and time |
reminderDateTime | dateTimeTimeZone | Reminder date and time |
isReminderOn | Boolean | Whether reminder is enabled |
recurrence | patternedRecurrence | Recurrence pattern |
PATCH /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}
Content-Type: application/json
{
"status": "completed",
"completedDateTime": {
"dateTime": "2024-01-20T15:00:00",
"timeZone": "UTC"
}
}
DELETE /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}
Returns 204 No Content on success.
Checklist items are subtasks within a task.
GET /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/checklistItems
Response:
{
"value": [
{
"id": "51d8a471-2e9d-4f53-9937-c33a8742d28f",
"displayName": "Create draft",
"createdDateTime": "2024-01-17T05:22:14Z",
"isChecked": false
}
]
}
POST /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/checklistItems
Content-Type: application/json
{
"displayName": "Final sign-off from the team"
}
PATCH /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/checklistItems/{checklistItemId}
Content-Type: application/json
{
"isChecked": true
}
DELETE /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/checklistItems/{checklistItemId}
Returns 204 No Content on success.
Linked resources connect tasks to external items (e.g., emails, files).
GET /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/linkedResources
Response:
{
"value": [
{
"id": "f9cddce2-dce2-f9cd-e2dc-cdf9e2dccdf9",
"webUrl": "https://example.com/item",
"applicationName": "MyApp",
"displayName": "Related Document",
"externalId": "external-123"
}
]
}
POST /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/linkedResources
Content-Type: application/json
{
"webUrl": "https://example.com/item",
"applicationName": "MyApp",
"displayName": "Related Document",
"externalId": "external-123"
}
DELETE /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks/{taskId}/linkedResources/{linkedResourceId}
Returns 204 No Content on success.
Microsoft Graph uses OData pagination. Use $top to limit results and $skip for offset:
GET /microsoft-to-do/v1.0/me/todo/lists/{todoTaskListId}/tasks?$top=10&$skip=0
Response includes @odata.nextLink when more results exist:
{
"value": [...],
"@odata.nextLink": "https://graph.microsoft.com/v1.0/me/todo/lists/{id}/tasks?$skip=10"
}
const response = await fetch(
'https://api.maton.ai/microsoft-to-do/v1.0/me/todo/lists',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/microsoft-to-do/v1.0/me/todo/lists',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
AAMkADIyAAAhrbPWAAA=)dateTimeTimeZone type requires both dateTime and timeZone fieldswellknownListName can be defaultList, flaggedEmails, or nonestatus values: notStarted, inProgress, completed, waitingOnOthers, deferredimportance values: low, normal, high$select, $filter, $orderby, $top, $skipcurl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| 400 | Missing Microsoft To Do connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Microsoft Graph API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
microsoft-to-do. For example:https://api.maton.ai/microsoft-to-do/v1.0/me/todo/listshttps://api.maton.ai/v1.0/me/todo/lists