Appearance
API v2
WARNING
This version of the API is in active development. The API and its associated documentation are likely to be incomplete and/or incorrect, and may change without notice.
Authentication
To use the TaskRatchet API, you need an API key. This key is used to authenticate your requests and is required for all endpoints.
Example request with API key:
bash
curl "https://api.taskratchet.com/api2/me" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"Please reach out to support@taskratchet.com to get an API key.
Rate Limiting
Rate limiting is handled at the edge by Cloudflare. Limits are configured per route pattern:
/api2/*: 60 requests per 10 seconds
Rate-limited requests receive HTTP 429 (Too Many Requests) responses.
Schema
Base URL: https://api.taskratchet.com/api2/
| Endpoint | Description |
|---|---|
GET /api2/me | Get your profile data |
PUT /api2/me | Update your profile |
DELETE /api2/me | Delete your account |
GET /api2/me/tasks | Get all your tasks |
POST /api2/me/tasks | Create a new task |
GET /api2/me/tasks/:task_id | Get a single task |
PUT /api2/me/tasks/:task_id | Update a task |
POST /api2/me/tasks/:task_id/uncle | Give up on a task and trigger charge |
GET /api2/me/recurring | Get your recurring tasks |
DELETE /api2/me/recurring/:recurring_id | Stop a recurring task |
POST /api2/me/token | Reset your API v2 token |
GET /api2/me/token | Get your API v2 token |
POST /api2/me/calendar-token | Generate/regenerate your calendar feed token |
GET /api2/me/calendar-token | Get your calendar feed token |
GET /api2/calendar/:token.ics | Public iCal feed of task deadlines (no auth) |
GET /api2/health/stripe | Stripe connectivity probe (public, no auth) |
GET /api2/me
| Response Field | Type | Description |
|---|---|---|
| id | string | The account's unique identifier |
| name | string | User's full name (optional) |
| string | User's email address | |
| timezone | string | Deprecated. User's IANA timezone (optional) |
| integrations | object | User's integration settings; currently only Beeminder |
| has_stripe_customer | boolean | Whether the user has a Stripe customer account |
| has_calendar_token | boolean | Whether the user has generated a calendar feed token |
| monthly_stake_limit_cents | number | null | Per-user monthly stake cap in cents, or null if no limit is set |
| monthly_charge_limit_cents | number | null | Per-user monthly cap (in cents) on charges via POST /api2/me/charges, or null for no limit |
Example response:
json
{
"id": "Zu0qDVncIgSuUbQfr261",
"name": "Jon Doe",
"email": "jon@doe.com",
"timezone": "America/New_York",
"integrations": {
"beeminder": {
"user": "jondoe",
"goal_new_tasks": "tr_tasks"
}
},
"has_stripe_customer": true,
"has_calendar_token": false,
"monthly_stake_limit_cents": 50000
}PUT /api2/me
Updates the authenticated user's profile. The request body should be a JSON object with at least one of the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | false | User's full name |
| string | false | User's email address | |
| timezone | string | false | Deprecated. User's IANA timezone |
| email_global_unsubscribe | boolean | false | Unsubscribe from all emails (e.g. daily reminders) |
| beeminder_user | string | false | Beeminder username for the connected integration |
| beeminder_token | string | false | Beeminder auth token for the connected integration |
| beeminder_goal_new_tasks | string | false | Beeminder goal slug for new-task tracking |
| monthly_stake_limit_cents | number | null | false | Monthly stake cap in cents (non-negative integer), or null to remove |
| monthly_charge_limit_cents | number | null | false | Monthly API-charge cap in cents (non-negative integer), or null to remove the cap (uncapped) |
Example request:
bash
curl -X PUT "https://api.taskratchet.com/api2/me" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Jane Doe"}'On success, returns the updated user profile object (same shape as GET /api2/me).
DELETE /api2/me
Deletes the user's account. This action is irreversible.
GET /api2/me/tasks
Returns an array of tasks. This route is paginated.
Query params:
| Param | Type | Required | Description |
|---|---|---|---|
| page | number | false | Page number (default: 0) |
| status | string | false | Filter by task status (pending, complete, expired) |
| due_before | number | false | Unix timestamp; only return tasks due before this time |
| due_after | number | false | Unix timestamp; only return tasks due after this time |
Response format:
| Response Field | Type | Description |
|---|---|---|
| id | string | The task's unique identifier |
| task | string | The task description |
| due | number | Unix timestamp of the task's due date |
| cents | number | The task's stakes in cents |
| complete | boolean | Whether the task is complete |
| status | string | The task's status (pending, complete, expired) |
| chargeStatus | string | Present only when a charge has been initiated. One of: notified, authorized, captured (optional) |
| contested | boolean | Present and true only when the user has contested the charge (optional) |
Example request:
bash
curl "https://api.taskratchet.com/api2/me/tasks?page=0" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"Example response:
json
[
{
"id": "tdDPzh1GpZHAGZURVBf6",
"task": "Take out the trash",
"due": 1614556800,
"cents": 100,
"complete": false,
"status": "pending"
},
{
"id": "xkL9mN2OpQrStUvWxYz3",
"task": "File tax return",
"due": 1614470400,
"cents": 500,
"complete": false,
"status": "expired",
"chargeStatus": "notified"
}
]POST /api2/me/tasks
Creates a new task. The request body should be a JSON object with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
| task | string | true | The task description (must be non-empty) |
| due | number | true | Unix timestamp of the task's due date |
| cents | number | true | The task's stakes in cents (minimum 100) |
| recurrence | object | false | The task's recurrence settings |
| recurrence.days | number | true | Number of days between recurrences |
WARNING
The recurrence feature is incomplete and likely buggy. Use it at your own risk.
Error responses:
| Status | Body | Condition |
|---|---|---|
| 422 | { "error": "Monthly stake limit exceeded" } | Adding the new task's cents would push the current calendar month's total over the user's monthly_stake_limit_cents |
| 422 | Unprocessable Entity | Invalid request body (missing or malformed fields) |
On success, the response will be the created task object.
Example response:
json
{
"id": "tdDPzh1GpZHAGZURVBf6",
"task": "Take out the trash",
"due": 1614556800,
"cents": 100,
"complete": false,
"status": "pending"
}GET /api2/me/tasks/:task_id
Returns a single task by ID.
Example request:
bash
curl "https://api.taskratchet.com/api2/me/tasks/tdDPzh1GpZHAGZURVBf6" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"Example response:
json
{
"id": "tdDPzh1GpZHAGZURVBf6",
"task": "Take out the trash",
"due": 1614556800,
"cents": 100,
"complete": false,
"status": "pending"
}PUT /api2/me/tasks/:task_id
Updates an existing task. All fields are optional, but at least one must be provided.
| Field | Type | Required | Description |
|---|---|---|---|
| complete | boolean | false | Mark the task complete or incomplete (cannot mark as complete if expired) |
| cents | number | false | Update the stakes in cents (can only be increased, minimum 100) |
| due | number | false | Update the due date as a Unix timestamp (can only be moved earlier) |
INFO
Stakes can only be increased and deadlines can only be moved earlier — you cannot make a task easier after creating it.
Example request:
bash
curl -X PUT "https://api.taskratchet.com/api2/me/tasks/tdDPzh1GpZHAGZURVBf6" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN" \
-H "Content-Type: application/json" \
-d '{"complete": true}'On success, returns the updated task object.
Example response:
json
{
"id": "tdDPzh1GpZHAGZURVBf6",
"task": "Take out the trash",
"due": 1614556800,
"cents": 100,
"complete": true,
"status": "complete"
}POST /api2/me/tasks/:task_id/uncle
Gives up on a task early ("cries uncle"), triggering the charge process before the deadline. This sends a charge notification email and begins the charge flow. Can only be called once per task — returns 409 Conflict if the task has already been uncled or a charge has already been initiated.
Example request:
bash
curl -X POST "https://api.taskratchet.com/api2/me/tasks/tdDPzh1GpZHAGZURVBf6/uncle" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"Returns 200 OK with body ok on success.
POST /api2/me/charges
Charges the authenticated user's saved card an arbitrary amount, independent of any task. Intended for external integrations that impose their own penalties on top of TaskRatchet. The charge is captured immediately — there is no authorization window and no advance warning email; a receipt email is sent after a successful charge.
The request body should be a JSON object with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
| cents | number | true | Amount to charge, in cents (minimum 100, i.e. $1.00) |
| note | string | false | A short description of the charge (max 500 chars). Included on the receipt email and the Stripe charge. |
| requestid | string | false | Idempotency token. A repeat request with the same requestid returns the original charge instead of charging again. |
| dryrun | boolean | false | When true, validates the request (amount, limit, payment method) and returns a simulated charge without charging the card. |
Idempotency
Supplying a unique requestid per logical charge makes retries safe: if a request times out or you resend it, you get the original result back rather than a second charge. To intentionally retry after a declined card, use a new requestid.
Monthly charge limit
Charges are bounded by the user's monthly_charge_limit_cents (a separate cap from monthly_stake_limit_cents), summed over successful charges in the current calendar month:
- A finite value caps the total charged per month. Every account starts at a default of $100/month.
0disables the endpoint (every charge is rejected).nullmeans no limit (uncapped). Set it viaPUT /api2/me.
Error responses:
| Status | Body | Condition |
|---|---|---|
| 422 | { "error": "Monthly charge limit exceeded" } | This charge would push the calendar month's successful-charge total over monthly_charge_limit_cents |
| 422 | Unprocessable Entity | Invalid request body (e.g. cents below 100) |
| 400 | { "error": "No payment method on file" } | The user has no saved card to charge |
| 402 | { "error": "<decline message>" } | The card was declined (the attempt is still recorded) |
Example request:
bash
curl -X POST "https://api.taskratchet.com/api2/me/charges" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN" \
-H "Content-Type: application/json" \
-d '{"cents": 500, "note": "Missed my workout", "requestid": "2026-06-15-workout"}'Example response:
json
{
"id": "9f8b0c2e-1a2b-4c3d-8e9f-0a1b2c3d4e5f",
"cents": 500,
"note": "Missed my workout",
"status": "succeeded",
"created": 1614556800
}GET /api2/me/recurring
Returns an array of your recurring tasks — the schedules that automatically create new tasks on a fixed cadence. This route is paginated.
Query params:
| Param | Type | Required | Description |
|---|---|---|---|
| page | number | false | Page number (default: 0) |
Response format:
| Response Field | Type | Description |
|---|---|---|
| id | string | The recurring task's unique identifier |
| task | string | The task description applied to each created task |
| last_due | number | Unix timestamp of the most recent due date in the schedule |
| cents | number | The stakes in cents applied to each created task |
| recurrence | object | The cadence, e.g. { "days": 7 } for every 7 days |
Example request:
bash
curl "https://api.taskratchet.com/api2/me/recurring" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"Example response:
json
[
{
"id": "59059053-55dd-4c7e-bdf5-c08eeb37106d",
"task": "Weekly system review",
"last_due": 1780882200,
"cents": 5000,
"recurrence": { "days": 7 }
}
]DELETE /api2/me/recurring/:recurring_id
Stops a recurring task by deleting its recurrence schedule, so no new tasks are created from it going forward. Tasks that have already been created from the schedule are left untouched.
Example request:
bash
curl -X DELETE "https://api.taskratchet.com/api2/me/recurring/59059053-55dd-4c7e-bdf5-c08eeb37106d" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"Responses:
| Status | Body | Condition |
|---|---|---|
| 200 | success | Recurring task deleted |
| 404 | { "error": "Recurring task not found" } | No matching recurring task exists for your account |
| 403 | { "error": "Forbidden" } | Missing or invalid authentication |
POST /api2/me/token
Reset your account's API v2 token. This will invalidate the old token and generate a new one.
You'll need to be authenticated in order to reset your token. If you don't already have a token, contact support for help.
GET /api2/me/token
Returns the current API v2 token for the authenticated user.
POST /api2/me/calendar-token
Generates a new calendar feed token for the authenticated user, replacing any existing one (which invalidates the previous feed URL). Use this to enable the feed or to rotate the token if a URL is exposed.
Returns the token as a plain-text response body. Combine it with the public feed route to build the subscription URL: https://api.taskratchet.com/api2/calendar/<token>.ics.
bash
curl -X POST "https://api.taskratchet.com/api2/me/calendar-token" \
-H "Authorization: ApiKey-v2 YOUR_API_V2_TOKEN"GET /api2/me/calendar-token
Returns the authenticated user's current calendar feed token as a plain-text response body.
| Status | Body | Meaning |
|---|---|---|
200 OK | the token | A calendar token exists |
400 Bad Request | { "error": "Calendar token has not been generated for this user. Please use the POST /api2/me/calendar-token endpoint to generate a new calendar token." } | No token has been generated yet |
GET /api2/calendar/:token.ics
Public, unauthenticated iCal feed of the user's pending task deadlines, secured by the token in the URL. Subscribe to this URL from any calendar app. The .ics extension is optional. Each pending task is emitted as a VEVENT whose summary includes the task description and stake amount; expired tasks are excluded.
Responses are served as text/calendar; charset=utf-8 with Cache-Control: no-cache.
| Status | Body | Meaning |
|---|---|---|
200 OK | iCal (VCALENDAR) document | Token resolved; feed returned |
404 Not Found | Not Found | No user matches the supplied token |
500 Internal Server Error | Internal Server Error | The feed could not be generated |
bash
curl "https://api.taskratchet.com/api2/calendar/YOUR_CALENDAR_TOKEN.ics"GET /api2/health/stripe
Public, unauthenticated Stripe connectivity probe intended for uptime monitors. It makes a lightweight, read-only call to Stripe and reports whether the API can reach it.
| Status | Body | Meaning |
|---|---|---|
200 OK | {"stripe":"ok"} | Stripe is reachable |
503 Service Unavailable | {"stripe":"unreachable"} | The Stripe call failed |
bash
curl "https://api.taskratchet.com/api2/health/stripe"Example response (healthy):
json
{ "stripe": "ok" }