API reference
Current bananabay API routes and the product actions they support.
This reference documents the current route map and what each route is for. It is generated from the shared OpenAPI schema catalog so endpoint response shapes stay in one place.
Use https://api.bananabay.xyz as the origin. Except for GET /api/ping, send Authorization: Bearer $BANANABAY_API_KEY.
Public
GET /api/ping
Checks whether the public API surface can answer a basic request. No API key is required.
Response: 200 OK
Response shape
{
"msg": "pong"
}Food inventory
GET /api/food/audit
Reads audit information for food records owned by the authenticated account. Use it when reconciling inventory state.
Response: 200 OK
Response shape
{
"ok": true,
"auditType": "product",
"identifier": "036632032893",
"facts": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"items": [
{
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
}
],
"userId": "user_123"
}GET /api/food/intake
Reads food intake summary data for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"records": [
{
"schemaVersion": 1,
"userId": "user_123",
"localDate": "2026-05-24",
"timezone": "America/Denver",
"entries": [
{
"id": "intake_123",
"itemId": "food_item_123",
"consumedAt": "2026-05-24T15:30:00.000Z",
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"macros": {
"calories": 120,
"protein": 15
}
}
],
"totals": {
"calories": 120,
"protein": 15
},
"updatedAt": "2026-05-24T15:30:00.000Z"
}
],
"userId": "user_123"
}GET /api/food
Lists food inventory records for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"count": 1,
"total": 1,
"limit": 50,
"offset": 0,
"next_offset": null,
"items": [
{
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
}
],
"userId": "user_123"
}POST /api/food
Creates a food inventory record. Send JSON for the item name, amount, storage details, and any supported inventory fields.
Response: 201 Created
Response shape
{
"ok": true,
"id": "food_item_123",
"userId": "user_123"
}GET /api/food/items/:itemId
Reads one food inventory item by item ID.
Response: 200 OK
Response shape
{
"ok": true,
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"userId": "user_123"
}PATCH /api/food/items/:itemId
Updates one food inventory item. Send JSON with the fields being changed.
Response: 200 OK
Response shape
{
"ok": true,
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"userId": "user_123"
}DELETE /api/food/items/:itemId
Deletes one food inventory item.
Response: 200 OK
Response shape
{
"ok": true,
"id": "food_item_123",
"userId": "user_123"
}POST /api/food/items/:itemId/image
Uploads an item-specific food image. Send multipart form data with an image file. The uploaded image is scoped to this inventory item and does not change SKU/product images.
Response: 201 Created
Response shape
{
"ok": true,
"image": {
"id": "food_image_123",
"url": "/api/food/images/food_image_123",
"ownerKind": "item",
"ownerId": "food_item_123",
"contentType": "image/jpeg",
"sizeBytes": 38422,
"fileName": "yogurt.jpg",
"createdAt": "2026-05-24T15:30:00.000Z"
},
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"userId": "user_123"
}POST /api/food/items/:itemId/adjust
Adjusts an inventory item's amount without replacing the whole record.
Response: 200 OK
Response shape
{
"ok": true,
"action": "updated",
"count": 1,
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"userId": "user_123"
}POST /api/food/items/:itemId/consume-grams
Records gram-based consumption for an inventory item.
Response: 200 OK
Response shape
{
"ok": true,
"grams": 150,
"inventoryAction": "updated",
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"consumedItem": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"remainingItem": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"intakeEntry": {
"id": "intake_123",
"itemId": "food_item_123",
"consumedAt": "2026-05-24T15:30:00.000Z",
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"macros": {
"calories": 120,
"protein": 15
}
},
"userId": "user_123"
}POST /api/food/items/:itemId/remove
Removes an inventory amount or item using the food removal workflow.
Response: 200 OK
Response shape
{
"ok": true,
"removalId": "removal_123",
"kind": "consume",
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"undoExpiresAt": "2026-05-24T15:35:00.000Z",
"userId": "user_123"
}POST /api/food/removals/:removalId/undo
Undoes a recorded food removal when the removal can still be reversed.
Response: 200 OK
Response shape
{
"ok": true,
"removalId": "removal_123",
"kind": "consume",
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"userId": "user_123"
}GET /api/food/search
Searches authenticated food inventory records.
Response: 200 OK
Response shape
{
"ok": true,
"searchType": "name",
"query": "yogurt",
"status": "matched",
"items": [
{
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
}
],
"userId": "user_123"
}POST /api/food/upc
Looks up or attaches UPC-oriented food information where the product workflow supports it.
Response: 200 OK
Response shape
{
"ok": true,
"action": "updated",
"count": 1,
"item": {
"schemaVersion": 1,
"id": "food_item_123",
"name": "Greek yogurt",
"qty": 2,
"unit": "container",
"category": "Dairy",
"location": "fridge",
"upc": "036632032893",
"status": "active",
"tags": [
"breakfast"
],
"addedAt": "2026-05-24T15:30:00.000Z",
"expiresAt": "2026-06-01"
},
"userId": "user_123"
}Food labels and facts
GET /api/food/labels
Lists food labels available to the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"labels": [
{
"id": "label_123",
"userId": "user_123",
"slug": "breakfast",
"name": "Breakfast",
"color": "#0ea5e9",
"scope": "both"
}
],
"userId": "user_123"
}POST /api/food/labels
Creates or updates food labels for account-owned food organization.
Response: 200 OK
Response shape
{
"ok": true,
"label": {
"id": "label_123",
"userId": "user_123",
"slug": "breakfast",
"name": "Breakfast",
"color": "#0ea5e9",
"scope": "both"
},
"userId": "user_123"
}GET /api/food/facts/resolve
Resolves food facts for an item using available identifiers and account-owned records.
Response: 200 OK
Response shape
{
"ok": true,
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"source": "user",
"resolutionReason": "matched-upc",
"userId": "user_123"
}GET /api/food/facts/suggest
Suggests food facts matches that may fit a food item.
Response: 200 OK
Response shape
{
"ok": true,
"suggestions": [
{
"id": "facts_123",
"scope": "user",
"canonicalName": "Greek yogurt",
"brand": "Example Dairy",
"category": "Dairy",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"sourceLabel": "Personal facts"
}
],
"userId": "user_123"
}GET /api/food/facts
Lists personal food facts records for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"entries": [
{
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"linkedInventoryItemCount": 2
}
],
"count": 1,
"total": 1,
"limit": 50,
"offset": 0,
"nextOffset": null,
"userId": "user_123"
}POST /api/food/facts
Creates a personal food facts record.
Response: 200 OK
Response shape
{
"ok": true,
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"userId": "user_123"
}GET /api/food/facts/:upc
Reads food facts by UPC when a UPC-backed facts record exists.
Response: 200 OK
Response shape
{
"ok": true,
"item": {
"factsId": "facts_123",
"scope": "user",
"upc": "036632032893",
"name": "Greek yogurt",
"canonicalName": "Greek yogurt",
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual"
},
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"source": "user",
"resolutionReason": "matched-upc",
"userId": "user_123"
}PATCH /api/food/facts/:upc
Updates UPC-backed food facts when the authenticated account can edit that record.
Response: 200 OK
Response shape
{
"ok": true,
"item": {
"factsId": "facts_123",
"scope": "user",
"upc": "036632032893",
"name": "Greek yogurt",
"canonicalName": "Greek yogurt",
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual"
},
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"source": "user",
"resolutionReason": "matched-upc",
"userId": "user_123"
}GET /api/food/facts/records/:factsId
Reads a food facts record by facts record ID.
Response: 200 OK
Response shape
{
"ok": true,
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"userId": "user_123"
}PATCH /api/food/facts/records/:factsId
Updates a food facts record by facts record ID.
Response: 200 OK
Response shape
{
"ok": true,
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"userId": "user_123"
}DELETE /api/food/facts/records/:factsId
Deletes a food facts record owned by the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"userId": "user_123"
}POST /api/food/facts/records/:factsId/check-upstream
Checks whether a facts record has relevant upstream information available.
Response: 200 OK
Response shape
{
"ok": true,
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"changedFields": [
"nutrition"
],
"diff": [
{
"field": "nutrition",
"label": "Nutrition",
"status": "changed_upstream",
"localValue": {
"calories": 120
},
"upstreamValue": {
"calories": 130
}
}
],
"checkedAt": "2026-05-24T15:30:00.000Z",
"userId": "user_123"
}POST /api/food/facts/records/:factsId/image
Uploads an image for a personal food facts record. Send multipart form data with an image file. Item-specific image overrides remain separate.
Response: 201 Created
Response shape
{
"ok": true,
"image": {
"id": "food_image_123",
"url": "/api/food/images/food_image_123",
"ownerKind": "facts",
"ownerId": "facts_123",
"contentType": "image/jpeg",
"sizeBytes": 38422,
"fileName": "yogurt.jpg",
"createdAt": "2026-05-24T15:30:00.000Z"
},
"record": {
"schemaVersion": 1,
"id": "facts_123",
"scope": "user",
"ownerUserId": "user_123",
"canonicalName": "Greek yogurt",
"aliases": [
"yogurt"
],
"upcs": [
"036632032893"
],
"brand": "Example Dairy",
"category": "Dairy",
"source": "manual",
"nutrition": {
"perServing": {
"calories": 120,
"protein": 15
}
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
},
"userId": "user_123"
}GET /api/food/images/:imageId
Reads an authenticated food image by image ID. Images are only returned to the account that owns the related food item or personal facts record.
Response: 200 OK
Response shape
{
"contentType": "image/jpeg | image/png | image/webp",
"body": "<binary image bytes>"
}Meals
GET /api/meals/plans
Lists meal plans for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"plans": [
{
"id": "meal_plan_123",
"ownerUserId": "user_123",
"date": "2026-05-24",
"mealSlot": "breakfast",
"title": "Yogurt bowl",
"plannedItems": [
{
"inventoryItemId": "food_item_123",
"quantityNote": "1 container"
}
],
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
]
}POST /api/meals/plans
Creates a meal plan.
Response: 200 OK
Response shape
{
"ok": true,
"plan": {
"id": "meal_plan_123",
"ownerUserId": "user_123",
"date": "2026-05-24",
"mealSlot": "breakfast",
"title": "Yogurt bowl",
"plannedItems": [
{
"inventoryItemId": "food_item_123",
"quantityNote": "1 container"
}
],
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}PATCH /api/meals/plans/:planId
Updates one meal plan by plan ID.
Response: 200 OK
Response shape
{
"ok": true,
"plan": {
"id": "meal_plan_123",
"ownerUserId": "user_123",
"date": "2026-05-24",
"mealSlot": "breakfast",
"title": "Yogurt bowl",
"plannedItems": [
{
"inventoryItemId": "food_item_123",
"quantityNote": "1 container"
}
],
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}DELETE /api/meals/plans/:planId
Deletes one meal plan by plan ID.
Response: 200 OK
Response shape
{
"ok": true,
"deletedId": "meal_plan_123"
}Privacy
GET /api/privacy/user-data
Exports app-owned data for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"userId": "user_123",
"exportedAt": "2026-05-24T15:30:00.000Z",
"domains": {
"siteSettings": {},
"food": {},
"schedule": {},
"meals": {},
"tasks": {},
"weather": {}
},
"externalProcessors": {
"clerk": "handled-by-provider",
"vercel": "handled-by-provider"
}
}DELETE /api/privacy/user-data
Deletes app-owned data for the authenticated account. This is destructive and should be called only after explicit user confirmation.
Response: 200 OK
Response shape
{
"ok": true,
"userId": "user_123",
"deletedAt": "2026-05-24T15:30:00.000Z",
"domains": {
"siteSettings": {
"deletedCount": 1
},
"food": {
"deletedCount": 12
},
"schedule": {
"deletedCount": 4
},
"meals": {
"deletedCount": 2
},
"tasks": {
"deletedCount": 6
},
"weather": {
"deletedCount": 3
}
},
"externalProcessors": {
"clerk": "not-deleted-by-app-operation",
"vercel": "not-app-owned"
}
}Schedule
GET /api/schedule/config
Reads schedule configuration for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"scheduleEngine": "clock",
"sunWakeAltitudeDegrees": -6,
"clockWakeTime": "07:30",
"solarDeathWindowEnabled": true,
"solarDeathWindowAngleDegrees": 6,
"latitude": null,
"longitude": null,
"timezone": null,
"locationSource": "user"
}PATCH /api/schedule/config
Updates schedule configuration.
Response: 200 OK
Response shape
{
"ok": true,
"scheduleEngine": "clock",
"sunWakeAltitudeDegrees": -6,
"clockWakeTime": "07:30",
"solarDeathWindowEnabled": true,
"solarDeathWindowAngleDegrees": 6,
"latitude": null,
"longitude": null,
"timezone": null,
"locationSource": "user"
}GET /api/schedule/now
Reads the current schedule state for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"currentBlock": "Breakfast",
"startIso": "2026-05-24T14:00:00.000Z",
"endIso": "2026-05-24T14:30:00.000Z",
"minutesRemaining": 12,
"weather": null
}POST /api/schedule/sleep/ingest
Ingests sleep data into the schedule workflow.
Response: 200 OK
Response shape
{
"ok": true,
"provider": "health_connect",
"dataSource": "google_health",
"count": 1,
"schedule": {}
}POST /api/schedule/sleep
Writes sleep information used by the schedule workflow.
Response: 200 OK
Response shape
{
"ok": true,
"count": 1
}GET /api/schedule/today
Reads today's schedule view for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"scheduleEngine": "clock",
"currentBlock": "Breakfast",
"blocks": [
{
"name": "Breakfast",
"startIso": "2026-05-24T14:00:00.000Z",
"endIso": "2026-05-24T14:30:00.000Z"
}
],
"idealBlocks": [
{
"name": "Breakfast",
"startIso": "2026-05-24T14:00:00.000Z",
"endIso": "2026-05-24T14:30:00.000Z"
}
],
"userWakeTime": "07:30",
"userBedtime": "23:00",
"locationSource": "user",
"locationConfigured": true,
"astroDataAvailable": true,
"weather": null
}DELETE /api/schedule/track/comments/:commentId
Deletes one schedule track comment by comment ID.
Response: 200 OK
Response shape
{
"ok": true,
"active": {
"id": "track_123",
"name": "Deep work",
"startedAt": "2026-05-24T15:00:00.000Z",
"stoppedAt": null,
"comments": []
}
}PATCH /api/schedule/track/comments/:commentId
Updates one schedule track comment by comment ID.
Response: 200 OK
Response shape
{
"ok": true,
"active": {
"id": "track_123",
"name": "Deep work",
"startedAt": "2026-05-24T15:00:00.000Z",
"stoppedAt": null,
"comments": []
}
}POST /api/schedule/track/comments
Creates a schedule track comment.
Response: 200 OK
Response shape
{
"ok": true,
"active": {
"id": "track_123",
"name": "Deep work",
"startedAt": "2026-05-24T15:00:00.000Z",
"stoppedAt": null,
"comments": []
}
}DELETE /api/schedule/track
Deletes schedule tracking state for the requested scope.
Response: 200 OK
Response shape
{
"ok": true,
"active": null
}GET /api/schedule/track
Reads schedule tracking state.
Response: 200 OK
Response shape
{
"ok": true,
"active": {
"id": "track_123",
"name": "Deep work",
"startedAt": "2026-05-24T15:00:00.000Z",
"stoppedAt": null,
"comments": []
}
}POST /api/schedule/track
Creates or records schedule tracking state.
Response: 200 OK
Response shape
{
"ok": true,
"active": {
"id": "track_123",
"name": "Deep work",
"startedAt": "2026-05-24T15:00:00.000Z",
"stoppedAt": null,
"comments": []
}
}POST /api/schedule/wake
Records wake information used by the schedule workflow.
Response: 200 OK
Response shape
{
"ok": true,
"actualWakeTime": "2026-05-24T13:30:00.000Z",
"schedule": {}
}Settings
GET /api/settings/food
Reads food settings for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"food": {
"consumeLogRetentionDays": 365
}
}POST /api/settings/food
Updates food settings.
Response: 200 OK
Response shape
{
"ok": true,
"food": {
"consumeLogRetentionDays": 365
}
}GET /api/settings/location
Reads location settings.
Response: 200 OK
Response shape
{
"ok": true,
"latitude": 39.7392,
"longitude": -104.9903,
"timezone": "America/Denver",
"location_source": "user"
}POST /api/settings/location
Updates location settings.
Response: 200 OK
Response shape
{
"ok": true,
"latitude": 39.7392,
"longitude": -104.9903,
"timezone": "America/Denver",
"location_source": "user"
}GET /api/settings/measurement
Reads measurement settings.
Response: 200 OK
Response shape
{
"ok": true,
"measurement": {
"system": "metric",
"weather": {
"temperature": "celsius",
"windSpeed": "kilometers_per_hour",
"precipitation": "millimeters"
}
}
}POST /api/settings/measurement
Updates measurement settings.
Response: 200 OK
Response shape
{
"ok": true,
"measurement": {
"system": "metric",
"weather": {
"temperature": "celsius",
"windSpeed": "kilometers_per_hour",
"precipitation": "millimeters"
}
}
}GET /api/settings/tasks
Reads task settings.
Response: 200 OK
Response shape
{
"ok": true,
"tasks": {
"completedTaskRetentionDays": 90,
"desktopNotificationsEnabled": true
}
}POST /api/settings/tasks
Updates task settings.
Response: 200 OK
Response shape
{
"ok": true,
"tasks": {
"completedTaskRetentionDays": 90,
"desktopNotificationsEnabled": true
}
}GET /api/settings/time
Reads time settings.
Response: 200 OK
Response shape
{
"ok": true,
"timeFormat": "12h"
}POST /api/settings/time
Updates time settings.
Response: 200 OK
Response shape
{
"ok": true,
"timeFormat": "12h"
}Tasks
GET /api/tasks
Lists tasks for the authenticated account.
Response: 200 OK
Response shape
{
"ok": true,
"tasks": [
{
"id": "task_123",
"ownerUserId": "user_123",
"title": "Take vitamins",
"status": "active",
"subtasks": [],
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:30"
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
]
}POST /api/tasks
Creates a task.
Response: 200 OK
Response shape
{
"ok": true,
"task": {
"id": "task_123",
"ownerUserId": "user_123",
"title": "Take vitamins",
"status": "active",
"subtasks": [],
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:30"
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}GET /api/tasks/completions
Lists task completions.
Response: 200 OK
Response shape
{
"ok": true,
"completions": [
{
"id": "completion_123",
"taskId": "task_123",
"completedAt": "2026-05-24T15:30:00.000Z",
"completedSubtaskIds": [],
"retained": true,
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
]
}POST /api/tasks/completions
Creates a task completion.
Response: 200 OK
Response shape
{
"ok": true,
"completion": {
"id": "completion_123",
"taskId": "task_123",
"completedAt": "2026-05-24T15:30:00.000Z",
"completedSubtaskIds": [],
"retained": true,
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}PATCH /api/tasks/completions/:completionId
Updates one task completion by completion ID.
Response: 200 OK
Response shape
{
"ok": true,
"completion": {
"id": "completion_123",
"taskId": "task_123",
"completedAt": "2026-05-24T15:30:00.000Z",
"completedSubtaskIds": [],
"retained": true,
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}DELETE /api/tasks/completions/:completionId
Deletes one task completion by completion ID.
Response: 200 OK
Response shape
{
"ok": true,
"deletedId": "completion_123"
}GET /api/tasks/routines
Lists task routines.
Response: 200 OK
Response shape
{
"ok": true,
"routines": [
{
"id": "routine_123",
"ownerUserId": "user_123",
"title": "Morning routine",
"status": "active",
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:00"
},
"taskIds": [
"task_123"
],
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
]
}POST /api/tasks/routines
Creates a task routine.
Response: 200 OK
Response shape
{
"ok": true,
"routine": {
"id": "routine_123",
"ownerUserId": "user_123",
"title": "Morning routine",
"status": "active",
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:00"
},
"taskIds": [
"task_123"
],
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}PATCH /api/tasks/routines/:routineId
Updates one task routine by routine ID.
Response: 200 OK
Response shape
{
"ok": true,
"routine": {
"id": "routine_123",
"ownerUserId": "user_123",
"title": "Morning routine",
"status": "active",
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:00"
},
"taskIds": [
"task_123"
],
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}DELETE /api/tasks/routines/:routineId
Deletes one task routine by routine ID.
Response: 200 OK
Response shape
{
"ok": true,
"deletedId": "routine_123"
}GET /api/tasks/today
Reads today's task view.
Response: 200 OK
Response shape
{
"ok": true,
"date": "2026-05-24",
"timezone": "America/Denver",
"entries": [
{
"id": "task_123",
"source": "task",
"taskId": "task_123",
"title": "Take vitamins",
"start": "2026-05-24T14:30:00.000Z",
"end": null,
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:30"
},
"completed": false,
"overdue": false,
"completionIds": [],
"subtaskCount": 0,
"completedSubtaskCount": 0
}
],
"pendingConditions": [],
"appletVariables": []
}GET /api/tasks/:taskId
Reads one task by task ID.
Response: 200 OK
Response shape
{
"ok": true,
"task": {
"id": "task_123",
"ownerUserId": "user_123",
"title": "Take vitamins",
"status": "active",
"subtasks": [],
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:30"
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}PATCH /api/tasks/:taskId
Updates one task by task ID.
Response: 200 OK
Response shape
{
"ok": true,
"task": {
"id": "task_123",
"ownerUserId": "user_123",
"title": "Take vitamins",
"status": "active",
"subtasks": [],
"scheduleRule": {
"type": "recurring-time",
"frequency": "daily",
"time": "08:30"
},
"createdAt": "2026-05-24T15:30:00.000Z",
"updatedAt": "2026-05-24T15:30:00.000Z"
}
}DELETE /api/tasks/:taskId
Deletes one task by task ID.
Response: 200 OK
Response shape
{
"ok": true,
"deletedId": "task_123"
}Weather
POST /api/weather/report
Creates or refreshes the weather report used by the authenticated account's settings and schedule workflows.
Response: 200 OK
Response shape
{
"ok": true,
"report": {
"provider": "openweathermap",
"location": {
"latitude": 39.7392,
"longitude": -104.9903
},
"units": "metric",
"timezone": "America/Denver",
"timezoneOffsetSeconds": -21600,
"current": {
"observedAt": 1779636600,
"temperature": 18.4,
"feelsLike": 18.1,
"pressure": 1014,
"humidity": 35,
"dewPoint": 2.4,
"uvIndex": 4.2,
"cloudCover": 20,
"visibility": 10000,
"windSpeed": 3.4,
"windDirection": 220,
"conditions": [
{
"id": 801,
"main": "Clouds",
"description": "few clouds",
"icon": "02d"
}
]
},
"hourly": [],
"daily": []
},
"capturedAt": "2026-05-24T15:30:00.000Z",
"appletVariables": []
}