{"openapi":"3.1.0","info":{"title":"umeter API","version":"1.0.0","description":"Track AI usage limits, subscriptions, usage meters and expirations. Every token is bound to one workspace. The same tools are available over MCP at /mcp. See /llms.txt."},"servers":[{"url":"https://umeter.psyirius.dev"}],"security":[{"bearer":[]},{"oauth":["trackers:read"]}],"tags":[{"name":"Tools: read","description":"Agent tools that only read"},{"name":"Tools: safe writes","description":"Agent tools that change trackers (never delete)"},{"name":"Trackers","description":"Ingest endpoints for scripts and cron jobs"}],"paths":{"/api/v1/tools/get_workspace":{"post":{"operationId":"get_workspace","summary":"Workspace overview","description":"The connected umeter workspace: name, time zone, default currency, tracker counts by kind, and what needs attention (limited AI limits, meters over a threshold, things due in the next 24 hours). Call this first to orient yourself.","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/list_trackers":{"post":{"operationId":"list_trackers","summary":"List trackers","description":"List trackers in the workspace. Kinds: \"limit\" (AI usage limits with reset windows, e.g. Claude 5-hour sessions), \"subscription\" (recurring bills like Netflix), \"meter\" (usage or budget with % thresholds, e.g. cloud spend), \"expiry\" (one-off dates like a domain or certificate).","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"description":"Only this kind","type":"string","enum":["limit","subscription","meter","expiry"]},"status":{"default":"active","type":"string","enum":["active","paused","all"]},"query":{"description":"Case-insensitive name filter","type":"string","maxLength":80}}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/get_tracker":{"post":{"operationId":"get_tracker","summary":"Get a tracker","description":"Full details of one tracker: its extra limits (`meters`, each with its own reset) and, for meters, the last 10 readings.","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"Tracker id (from list_trackers)"}},"required":["id"]}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/upcoming":{"post":{"operationId":"upcoming","summary":"Upcoming resets and renewals","description":"What happens next, soonest first: limit resets, subscription renewals (with price), meter cycle resets and expirations within the given window.","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"within_hours":{"default":168,"description":"Look-ahead window in hours (default 168 = one week)","type":"integer","minimum":1,"maximum":8784},"kind":{"type":"string","enum":["limit","subscription","meter","expiry"]}}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/spending_summary":{"post":{"operationId":"spending_summary","summary":"Subscription spending","description":"Monthly-equivalent subscription spend, totalled separately per currency (amounts are never converted between currencies), plus each active subscription.","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/list_alerts":{"post":{"operationId":"list_alerts","summary":"Recent alerts","description":"Alert history, newest first: reminders, \"limit available again\" pings, threshold crossings and digests, with delivery status. Use `pending` to see what is scheduled next.","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"default":"history","type":"string","enum":["history","pending"]},"tracker_id":{"type":"string","minLength":1,"maxLength":64,"description":"Tracker id (from list_trackers)"},"limit":{"default":20,"type":"integer","minimum":1,"maximum":100}}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/list_presets":{"post":{"operationId":"list_presets","summary":"Built-in presets","description":"Built-in presets for common services (Claude, ChatGPT, Gemini, Netflix, Spotify, AWS, …) with typical windows and prices. Pass a preset key to create_tracker.","tags":["Tools: read"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","maxLength":80},"category":{"type":"string","enum":["ai","streaming","music","cloud","dev","productivity","gaming","other"]}}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/record_usage":{"post":{"operationId":"record_usage","summary":"Record meter usage","description":"Set a meter to an absolute value or add to it (e.g. this month's cloud spend so far). Crossing a % threshold queues an alert. Meters only.","tags":["Tools: safe writes"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"Tracker id (from list_trackers)"},"value":{"description":"New absolute value","type":"number","minimum":0,"maximum":1000000000000000},"increment":{"description":"Amount to add","type":"number","minimum":-1000000000000000,"maximum":1000000000000000}},"required":["id"]}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/set_limit_state":{"post":{"operationId":"set_limit_state","summary":"Update an AI limit","description":"Update a usage-limit tracker: \"running\" starts a rolling window now (e.g. the first Claude message of a session), \"limited\" means the cap was hit (pass when it resets if the service said so), \"available\" means usable again. Reminders are rescheduled automatically.","tags":["Tools: safe writes"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"Tracker id (from list_trackers)"},"state":{"type":"string","enum":["running","limited","available"]},"reset_at":{"description":"For \"limited\": when the limit resets (ISO 8601)","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"reset_in_minutes":{"description":"For \"limited\": alternative to reset_at","type":"integer","minimum":1,"maximum":86400}},"required":["id","state"]}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/update_meter":{"post":{"operationId":"update_meter","summary":"Update one of a tracker’s limits","description":"Act on an extra limit of a tracker (see `meters` in get_tracker), e.g. Claude Max's \"Weekly\" or \"Opus\" cap. For limit meters: \"start_window\" (rolling window starts now), \"limited\" (cap hit; pass reset_at or reset_in_minutes if known), \"available\". For usage meters: \"usage\" with `value` (the new total), or \"reset\".","tags":["Tools: safe writes"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"Tracker id (from list_trackers)"},"meter_id":{"type":"string","minLength":1,"maxLength":64,"description":"The meter id from get_tracker"},"action":{"type":"string","enum":["start_window","limited","available","usage","reset"]},"value":{"description":"For \"usage\": the new total","type":"number","minimum":0},"reset_at":{"description":"For \"limited\": when it resets (ISO 8601)","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"reset_in_minutes":{"description":"For \"limited\": alternative to reset_at","type":"integer","minimum":1,"maximum":86400}},"required":["id","meter_id","action"]}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/reset_tracker":{"post":{"operationId":"reset_tracker","summary":"Reset a meter or limit","description":"Start over: a meter goes back to 0 for a new cycle, a limit becomes available. Other kinds can't be reset.","tags":["Tools: safe writes"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"Tracker id (from list_trackers)"}},"required":["id"]}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/tools/create_tracker":{"post":{"operationId":"create_tracker","summary":"Create a tracker","description":"Add a tracker, ideally from a preset (see list_presets) so windows and prices are filled in. Subscriptions and expirations need `date` (next renewal or expiry date). Reminders use the preset defaults and alerts go to all channels; fine-tune in the app afterwards.","tags":["Tools: safe writes"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"preset":{"description":"Preset key, e.g. \"netflix\" or \"claude-session\"","type":"string","maxLength":64},"kind":{"description":"Required without a preset","type":"string","enum":["limit","subscription","meter","expiry"]},"name":{"description":"Defaults to the preset name","type":"string","minLength":1,"maxLength":80},"date":{"description":"Next renewal (subscription), expiry date (expiry) or next fixed reset. YYYY-MM-DD, YYYY-MM-DDTHH:mm (workspace time zone) or ISO 8601","type":"string","maxLength":40},"amount":{"description":"Price in major units, e.g. 15.49","type":"number","minimum":0,"maximum":1000000000000},"currency":{"description":"ISO 4217 code; defaults to the workspace currency","type":"string","minLength":3,"maxLength":3},"every":{"description":"Billing interval for subscriptions (defaults to the preset or monthly)","type":"object","properties":{"unit":{"type":"string","enum":["day","week","month","year"]},"count":{"default":1,"type":"integer","minimum":1,"maximum":1000}},"required":["unit"]},"window_hours":{"description":"Rolling window length for limits","type":"number","minimum":0.25,"maximum":1440},"meter_max":{"description":"Budget or quota for meters","type":"number","minimum":0,"maximum":1000000000000000},"meter_unit":{"type":"string","maxLength":16},"timezone":{"type":"string"},"notes":{"type":"string","maxLength":2000}}}}}},"responses":{"200":{"description":"Tool result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"403":{"description":"Read-only connection","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/trackers":{"get":{"operationId":"listTrackersRest","summary":"List trackers","tags":["Trackers"],"responses":{"200":{"description":"All trackers","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Tracker"}}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/trackers/{id}":{"get":{"operationId":"getTrackerRest","summary":"Get a tracker","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The tracker","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Tracker"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/trackers/{id}/usage":{"post":{"operationId":"recordUsageRest","summary":"Record meter usage","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"number"},"increment":{"type":"number"}},"description":"Exactly one of value or increment"}}}},"responses":{"200":{"description":"The tracker","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Tracker"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/trackers/{id}/limit":{"post":{"operationId":"setLimitStateRest","summary":"Update a limit","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"type":"string","enum":["limited","running","available"]},"reset_at":{"type":"string","format":"date-time"},"reset_in_minutes":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"The tracker","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Tracker"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}},"/api/v1/trackers/{id}/reset":{"post":{"operationId":"resetTrackerRest","summary":"Reset a meter or limit","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The tracker","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Tracker"}}}}}},"401":{"description":"Missing, invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"404":{"description":"Not found in this workspace","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}},"422":{"description":"Invalid arguments","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}}}},"components":{"schemas":{"Tracker":{"type":"object","description":"A tracker. Instants are ISO 8601 UTC; money is per item currency.","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["limit","subscription","meter","expiry"]},"status":{"type":"string","enum":["active","paused"]},"preset":{"type":["string","null"]},"next_at":{"type":["string","null"],"format":"date-time"},"interval":{"type":["object","null"],"properties":{"unit":{"type":"string"},"count":{"type":"integer"}}},"timezone":{"type":"string"},"limit":{"type":"object","properties":{"mode":{"type":"string","enum":["rolling","fixed"]},"state":{"type":"string","enum":["available","running","limited"]},"window_minutes":{"type":["integer","null"]}}},"meter":{"type":"object","properties":{"value":{"type":"number"},"max":{"type":["number","null"]},"unit":{"type":["string","null"]},"percent":{"type":["number","null"]},"thresholds":{"type":"array","items":{"type":"number"}}}},"price":{"type":"object","properties":{"amount":{"type":"number"},"amount_minor":{"type":"integer"},"currency":{"type":"string"},"monthly_equivalent":{"type":"number"}}},"updated_at":{"type":"string","format":"date-time"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}},"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Workspace API token (um_…) from Settings → API tokens"},"oauth":{"type":"oauth2","description":"OAuth 2.1 with PKCE; dynamic client registration is open.","flows":{"authorizationCode":{"authorizationUrl":"https://umeter.psyirius.dev/api/auth/oauth2/authorize","tokenUrl":"https://umeter.psyirius.dev/api/auth/oauth2/token","refreshUrl":"https://umeter.psyirius.dev/api/auth/oauth2/token","scopes":{"trackers:read":"Read trackers, upcoming events, spending and alerts","trackers:write":"Record usage, update limits, reset and create trackers"}}}}}}}