Authentication, paid access and rate limits
There are two ways to give a program access to your DailyGoal data: paste an API token into it, or connect it as an app that you approve. Both pause while you have no paid access, and you can revoke either one at any time.
The DailyGoal API is not available on the Free plan. It works with a paid plan or during a free trial. See plans.
Which one do I need?
API token
Each account has one API token. Create it in your DailyGoal settings on the web or in Preferences in the app. It starts with dg_live_, is shown once, and is stored only as a hash, so DailyGoal cannot show it again. Settings show its prefix and when it was last used.
Send it on every REST request and from header-based MCP clients:
Authorization: Bearer <your API token>Regenerating the token replaces it and stops the old one at once. Revoking it stops all header-based access. Signing out everywhere, resetting your password or deleting your account also revokes it.
Connected apps
OAuth clients add the MCP server by opening DailyGoal sign-in and consent instead of taking an API token. Each app you approve appears in your settings with the date it connected and when it was last used, and you can revoke it on its own. You can hold up to 20 connected apps. The REST API accepts API tokens only; connected apps use the MCP server.
Connection instructions and each client's verification status are in the MCP quickstart.
Clients discover the issuer at https://www.dailygoal.fit/.well-known/oauth-authorization-server and the protected resource at https://api.dailygoal.fit/.well-known/oauth-protected-resource/v1/mcp. Use the authorization-code flow with PKCE S256. The exact audience is https://api.dailygoal.fit/v1/mcp. Send it as resource when exchanging a code; a refresh may omit it, but cannot name another audience. Request dailygoal for API access and offline_access for refresh tokens.
DailyGoal supports dynamic client registration at https://www.dailygoal.fit/oauth2/register and client ID metadata documents (CIMD). A CIMD client uses a normalized HTTPS document URL as its client_id. The document must name that exact URL, list accepted redirect URIs and describe a public client with no secret. The document URL needs a path on a public domain, with no query, fragment or credentials. Fetches allow no redirects, at most 5 KiB and 5 seconds; cached documents refresh after one hour on the next authorization.
Access tokens last one hour. Refresh tokens rotate and expire after 90 days without refresh. Revoking a connected app stops its access and refresh tokens immediately. Signing out everywhere, resetting your password or deleting your account revokes all connected apps.
Paid access
Every API operation needs DailyGoal Pro access, including a free trial. Free app features do not grant API access. If your paid access ends, your token and connected apps are paused, not deleted: REST requests return 403 with the subscription_required code and a link to resubscribe. MCP returns that code in a tool error over HTTP 200. They work again as soon as you resubscribe, with nothing to reconnect. While paused, you can still see and revoke them in settings. Compare plans.
Feature gates and capacity
The API uses the same backend gates as the apps. Free app history covers the latest 7 days, while Pro has no plan history cap. Read operations still have per-request bounds, such as 366 days for body metrics and water. Split larger ranges across requests or follow pagination where the operation provides a cursor. Workout templates require Pro. Free accounts can create up to 5 custom foods and 3 saved meals; Pro has no plan cap for either. A lapsed account cannot use the API to reach its Free allowance.
An account can have at most 16 gym profiles, including its default. Creating a seventeenth returns limit_exceeded (409). Update or delete an existing profile first. These capacity limits are separate from request rate limits.
Rate limits
Limits apply per user and are shared by every token and connected app on the account. They use token buckets: the burst is how many requests you can make at once, and the bucket refills at the per-minute rate. get_context returns the current numbers.
| Requests | Per minute | Burst | Per day |
|---|---|---|---|
| Reads | 120 | 60 | No daily cap |
| Writes | 30 | 15 | 1,000 |
REST returns 429 with the rate_limited code and a Retry-After header in seconds. MCP tool calls return the error in a 200 JSON-RPC result with isError: true; use the wait in its message. Replayed creates still spend request quota. Food diary writes also share the app's food-write limiter.
Retrying creates
Operations marked "Accepts Idempotency-Key" accept an optional REST Idempotency-Key header or MCP idempotency_key argument. Use a unique value of 1 to 255 visible ASCII characters for each new create. Repeating it with the same operation and input within 24 hours returns the first successful result. Using it with different input or another operation returns idempotency_conflict (409). Keys are scoped to the user and credential; a regenerated token or another connected app has a separate scope. Failed writes are not recorded, and a key can create again after 24 hours. REST marks a replayed response with Idempotent-Replayed: true.
Save operations that accept an optional id use the key only when creating. Omit id entirely to create; updates with an id ignore the key. An empty string or null does not mean create.
Where requests can run
Call from a server, script or MCP client. Production rejects browser requests with an Origin header and sends no CORS headers. Use https://api.dailygoal.fit; direct requests to the Convex backend return misdirected_request.
Errors
REST and MCP return the same error envelope, with a stable code, a hint on what to do next and a retryable flag. The error reference lists every code.