Public API · v1
The Habit Pocket API
A small, honest REST API. Read your habits, entries, and server-computed stats; log daily values; create habits and dashboard charts — all over HTTPS with an API key. It's a Pro feature, and a key only ever reaches your own data.
5 habits free. No credit card. Sync is free.
Overview
What the API does, and what it doesn’t.
You can read everything — habits, entries, stats, sections, charts — log and clear daily values, create habits, and add chart cards to your dashboard. Editing, archiving, and deleting stay in the app, on purpose: creating is additive and easily undone, restructuring what you built by hand is not.
- Base URL
- https://api.habitpocket.io
- Auth
- Send your key in the
X-API-KEYheader. - Access
- A Pro feature. A key on a non-Pro account gets a
402. - Rate limit
- 1000 requests per minute, per account.
| Method | Path | What it does |
|---|---|---|
| GET | /api/v1/account | Your timezone, week start, and today’s date in your timezone. |
| GET | /api/v1/habits | List your active habits. |
| POST | /api/v1/habits | Create a habit. |
| GET | /api/v1/habits/{habitId}/entries | Read one habit’s entries across a date range. |
| GET | /api/v1/entries | Read every habit’s entries across a date range, grouped per habit. |
| GET | /api/v1/stats | Server-computed stats: streaks, rates, perfect days, weekly breakdowns. |
| PUT | /api/v1/habits/{habitId}/entries/{date} | Set a habit’s value for one day. |
| DELETE | /api/v1/habits/{habitId}/entries/{date} | Clear a habit’s value for one day. |
| GET | /api/v1/sections | List your sections (habit groups). |
| GET | /api/v1/charts | List your dashboard charts. |
| POST | /api/v1/charts | Add a chart card to your dashboard. |
Prefer a machine-readable contract? The full OpenAPI spec is at https://api.habitpocket.io/swagger/public-v1/swagger.json. Point your codegen at it for a typed client.
Authentication
One key, two ways to send it.
Create a key in the app under Settings → Integrations. It looks like mp_live_xxxxx. Send it on every request — either in the X-API-KEY header, or as a standard Bearer token if your tooling prefers Authorization headers. A missing, invalid, or revoked key returns 401. Keep the key secret — treat it like a password.
X-API-KEY: mp_live_xxxxxcurl https://api.habitpocket.io/api/v1/habits \
-H "Authorization: Bearer mp_live_xxxxx"Your data stays yours
An API key only ever accesses the key-holder’s own data, using their own account. Your habit data is never shared with anyone else — it’s only ever available to the tools you explicitly authorize with a key. Revoke a key from Settings → Integrations at any time and that access ends immediately.
Using an AI assistant instead of writing code?
The same contract is available as an MCP server at https://api.habitpocket.io/mcp, so Claude, ChatGPT, and other MCP-capable assistants can read your habits, log values, and build charts without you writing a line of code. Read the MCP setup guide →
Account context
GET /api/v1/account
Your timezone, week start day, and — the part that matters — today's date resolved in your timezone. Entry dates are calendar days in your timezone, so anything that logs 'today' should read it from here instead of guessing from UTC.
{
"timezone": "Europe/Kyiv", // IANA id
"weekStartDay": "monday", // "sunday" | "monday" | "saturday"
"timeFormat": "24h", // "12h" | "24h"
"today": "2026-07-21", // today in YOUR timezone — use this, not UTC
"serverTimeUtc": "2026-07-21T18:40:00Z"
}Rate limits
1000 requests a minute.
That’s per account, across all your keys. If you go over, the next request returns 429 with a Retry-After header — the number of seconds to wait before trying again. Back off for that long and you’re fine.
List habits
GET /api/v1/habits
Returns an array of your active habits. Fields that don’t apply to a habit’s type come back as null or an empty array, so you can always read the same shape.
curl https://api.habitpocket.io/api/v1/habits \
-H "X-API-KEY: mp_live_xxxxx"{
"id": "b3f1...-uuid",
"name": "Run",
"description": null,
"type": "metric", // "boolean" | "metric" | "time" | "select"
"color": "#16a34a",
"unit": "km", // metric habits; null otherwise
"target": 5, // metric daily goal; null if none
"timeTarget": null, // "HH:mm" for time habits; null otherwise
"goalOperator": "above", // "above" | "exact" | "below"; null = above
"isMultiSelect": false, // select habits
"options": [ // select habits only; else []
{ "id": "...-uuid", "label": "Great", "color": "#16a34a" }
],
"excludedDays": [0, 6], // 0=Sun ... 6=Sat
"currentStreak": 3,
"bestStreak": 12,
"section": { "id": "...-uuid", "name": "Health" },
"createdAt": "2026-01-05T10:00:00Z"
}Create a habit
POST /api/v1/habits
Create a habit. It appears in the app immediately and syncs to your other devices like one created by hand. Send only the fields that match the type — a mismatch (say, options on a metric habit) returns 400 with a message saying exactly what to fix. Returns 201 with the created habit. Sections come from GET /api/v1/sections; omit sectionId for your default section.
{
"name": "Sleep hours",
"type": "metric", // "boolean" | "metric" | "time" | "select"
"unit": "hours", // metric only
"target": 8, // metric only, optional
"goalOperator": "above", // with a target: "above" | "exact" | "below"
"excludedDays": [], // optional, 0=Sun ... 6=Sat
"sectionId": null // optional; omit for your default section
}curl -X POST https://api.habitpocket.io/api/v1/habits \
-H "X-API-KEY: mp_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Sleep hours", "type": "metric", "unit": "hours", "target": 8 }'Read entries
GET /api/v1/habits/{habitId}/entries
Read one habit’s entries across an inclusive date range. Both from and to are required (YYYY-MM-DD), and the range can span at most 366 days per request. An invalid or too-wide range returns 400; a habit that isn’t yours returns 404.
curl "https://api.habitpocket.io/api/v1/habits/b3f1...-uuid/entries?from=2026-03-01&to=2026-03-31" \
-H "X-API-KEY: mp_live_xxxxx"{
"habitId": "...-uuid",
"date": "2026-03-01",
"status": "done", // "none" | "done" | "skip"
"value": 8, // metric; null otherwise
"time": null, // "HH:mm" for time habits; null otherwise
"optionIds": [] // select habits; else []
}All entries
GET /api/v1/entries
Every active habit's entries across one date range (from and to, max 366 days), grouped per habit — one request instead of one per habit. Habits with no entries in the range are included with an empty list, because 'not tracked this week' is information too.
[
{
"habitId": "b3f1...-uuid",
"name": "Run",
"type": "metric",
"unit": "km",
"target": 5,
"entries": [
{ "habitId": "b3f1...-uuid", "date": "2026-03-01", "status": "done",
"value": 6, "time": null, "optionIds": [] }
]
},
{
"habitId": "a2c4...-uuid",
"name": "Meditate",
"type": "boolean",
"unit": null,
"target": null,
"entries": [] // no entries in range — "not tracked" is signal
}
]Stats
GET /api/v1/stats
The same computation behind the app's dashboard: per-habit completion rates, current and best streaks, perfect days, weekly breakdowns, and metric averages across a date range (max 366 days). Use these numbers instead of recomputing your own — the streak rules around excluded days and skips are subtle, and these always match what the app shows.
curl "https://api.habitpocket.io/api/v1/stats?from=2026-03-01&to=2026-03-31" \
-H "X-API-KEY: mp_live_xxxxx"{
"from": "2026-03-01",
"to": "2026-03-31",
"totalDone": 54, // boolean-habit completions in range
"totalPossible": 62,
"overallRate": 87, // percent, 0-100
"bestStreak": 21,
"bestStreakHabitName": "Meditate",
"perfectDays": 12, // days where every applicable habit was done
"weeklyPerfectDays": [ { "week": "Mar 2", "value": 4 } ],
"habits": [
{
"id": "b3f1...-uuid",
"name": "Run",
"type": "metric",
"unit": "km",
"target": 5,
"currentStreak": 3,
"bestStreak": 12,
"trackedDays": 18, // days with a recorded entry
"totalDays": 27, // applicable days (excluded weekdays removed)
"rate": 66,
"average": 5.4, // metric habits; null otherwise
"dailyValues": { "2026-03-01": 6 },
"weeklyRates": [ { "week": "Mar 2", "value": 71 } ]
}
]
}Set a value
PUT /api/v1/habits/{habitId}/entries/{date}
Set a habit’s value for one day (date is YYYY-MM-DD). This creates the entry or overwrites it. The request body depends on the habit’s type — send only the field that matches. A mismatch returns 400 with a helpful message. Returns 200 with the saved entry.
boolean
{ "status": "done" } // or { "status": "skip" }An empty body {} marks the day done. To clear a day, use DELETE.
metric
{ "value": 8 }The value is required.
time
{ "time": "07:30" }Required, 24-hour HH:mm.
select
{ "optionIds": ["…-uuid"] }Required. The ids must be real options of that habit. A single-select habit rejects more than one.
curl -X PUT \
https://api.habitpocket.io/api/v1/habits/b3f1...-uuid/entries/2026-03-01 \
-H "X-API-KEY: mp_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{ "value": 8 }'{
"habitId": "...-uuid",
"date": "2026-03-01",
"status": "done", // "none" | "done" | "skip"
"value": 8, // metric; null otherwise
"time": null, // "HH:mm" for time habits; null otherwise
"optionIds": [] // select habits; else []
}Clear a value
DELETE /api/v1/habits/{habitId}/entries/{date}
Clear a habit’s value for a single day — the same as emptying that cell in the app. Returns 204 on success. A habit that isn’t yours returns 404.
Charts
GET & POST /api/v1/charts
List the chart cards on your dashboard, or add one. Four types: line, heatmap, summary, and candle — the daily bar spanning two time or metric habits (sleep bracketed by bedtime and wake-up, say) with up to three overlay lines. For candles, habitIds is ordered [bottom, top, ...overlays], and the offsets shift which day a value is read from: candleBottomOffset -1 starts tonight's bar from yesterday's bedtime. Creating returns 201; colors follow each habit's own color, and restyling or deleting stays in the app.
{
"name": "Sleep window",
"type": "candle", // "line" | "heatmap" | "summary" | "candle"
"habitIds": [ // candle: [bottom, top, ...up to 3 overlays]
"bedtime-uuid", "wakeup-uuid", "sleepscore-uuid"
],
"days": 30,
"candleBottomOffset": -1 // -1 = previous day's bedtime starts the bar
}{
"id": "e9d2...-uuid",
"name": "Sleep window",
"type": "candle", // "line" | "heatmap" | "summary" | "candle"
"habitIds": ["bedtime-uuid", "wakeup-uuid", "sleepscore-uuid"],
"days": 30, // 0 = type default, -1 = year-to-date
"isDefault": false,
"candleBottomOffset": -1, // read bottom metric from the previous day
"candleTopOffset": 0
}Errors
What each status code means.
Failures use standard HTTP status codes. A 400 always carries a JSON body with a message field so you know exactly what to fix.
| Status | When |
|---|---|
| 401 | No key, or the key is invalid or revoked. |
| 402 | The account isn’t on Pro. The API is a Pro feature. |
| 404 | The habit or entry doesn’t exist, or it isn’t yours. |
| 400 | The request failed validation. The body carries a "message" explaining what to fix. |
| 429 | You went over the rate limit. A Retry-After header says how many seconds to wait. |
FAQ
API — common questions
Open the app, go to Settings → Integrations, and create a key. It looks like mp_live_xxxxx. Copy it right away and keep it somewhere safe. Send it on every request in the X-API-KEY header, or as an Authorization: Bearer token. You can revoke a key from the same screen at any time, and a revoked key stops working immediately.
You can create habits (POST /api/v1/habits) and add dashboard charts (POST /api/v1/charts). Editing, archiving, and deleting stay in the app, on purpose: creating is additive and easily undone, restructuring what you built by hand is not.
Yes — that’s what the MCP server is for. Connect Habit Pocket to Claude (or any MCP-capable assistant) at https://api.habitpocket.io/mcp and it can read your habits and stats, log values, and build charts through the same contract as this API. The setup guide at habitpocket.io/mcp walks through it.
Only you. An API key acts as you and reaches only your own account’s data. Your habits and values are never shared with anyone else, and are only ever available to the tools you choose to hand a key to. Revoke the key and that access ends.
A thousand requests a minute, per account. Go over and you get a 429 with a Retry-After header telling you how many seconds to wait before trying again.
Yes. The full spec is at https://api.habitpocket.io/swagger/public-v1/swagger.json, so you can generate a typed client or explore every endpoint in your tool of choice.
Five habits. Thirty days.
See what shows up.
No credit card. Pick five habits. Come back in a month.