Personal API key
Connect your own scripts
A personal API key lets your script or data exporter work with your own EffortSignal account. You can upload completed workouts, sleep and daily measurements, or read saved training data. Choose the permissions each script needs when creating its key.
You create the key in your account settings. Application registration, callback URLs and an OAuth exchange are not needed. For a product that connects other athletes’ accounts, use API for Companies.
Create a key · Choose permissions · Use your key · Expiry and revocation
Create a key
- Sign in to EffortSignal and open Settings → Integrations. In the Russian interface, this is Настройки → Подключения.
- Find Personal API keys and select Create API key.
- Enter a Key name that identifies the script, such as
Local training export. - Choose Expires after: 30, 90, 180 or 365 days. The default is 90 days.
- Select at least one permission from the list below. For reading data, select Read workouts, thresholds and daily health data. For an uploader, select only the categories it sends.
- Select Create API key, then Copy key. Save it in your script’s secret settings or a password manager before selecting Done.
The complete key starts with es_personal_ and is shown only once. The list in Settings keeps its name, permissions, expiry and last-used date. If you lose the secret, create a replacement and revoke the old key.
Choose permissions
The creation dialog describes each permission in plain language. These are the corresponding API scope names:
| Permission | What the key can do |
|---|---|
training:read |
Read saved workouts and their available measurements, daily health records, current thresholds, units, timezone and training preferences |
activities:write |
Upload completed workouts and their recorded data |
sleep:write |
Send main sleep, deep sleep and confirmed naps |
health:write |
Send daily health measurements, including HRV and resting heart rate |
These permissions apply to the account that created the key. They do not allow editing FTP or other profile settings, scheduling workouts, deleting training history or accessing another athlete’s account.
Workout measurements received through the Garmin or Strava APIs cannot be read with personal keys. Such workouts can appear in a list with a restriction message instead of measurements. Recordings with unknown provenance may also be unavailable. Check details_access.available and its explanation before using a workout’s data; an unavailable value is not zero.
Use your key
Send the complete key in the Authorization header over HTTPS:
Authorization: Bearer YOUR_PERSONAL_API_KEY
The API base URL is https://app.effortsignal.com/api/v1/ingest/. Keep the key in private secret storage. Do not place it in a URL, public repository, browser application or shared log. It authenticates this API only; it does not sign in to the web application, connect an MCP client or create other keys.
This Python 3 example makes a read-only request for your current training settings. It uses the standard library and asks for the key at a hidden prompt. Create a key with training:read, save the code in a local .py file and run it with python3. The response contains your account data, so run it in a private terminal.
import getpass
import json
from urllib.request import HTTPRedirectHandler, Request, build_opener
class NoRedirect(HTTPRedirectHandler):
# Refuse redirects so the Authorization header cannot reach a different host.
def redirect_request(self, request, file, code, message, headers, new_url):
return None
# A hidden prompt keeps the secret out of the script and shell command history.
key = getpass.getpass("Personal API key: ").strip()
request = Request(
"https://app.effortsignal.com/api/v1/ingest/user-context/",
headers={"Authorization": f"Bearer {key}", "Accept": "application/json"},
)
with build_opener(NoRedirect()).open(request, timeout=30) as response:
result = json.load(response)
print(json.dumps(result, indent=2, ensure_ascii=False))
Read saved data
With training:read, use these routes relative to the API base URL:
| Request | Result |
|---|---|
GET activities/ |
A page of saved completed workouts, including access restrictions |
GET activities/{activity_id}/ |
One workout, its available saved metrics and requested detail sections |
GET daily-health/ |
Saved daily measurements with their local dates and sources |
GET user-context/ |
Current thresholds, units, timezone and training preferences |
Activity and daily-health lists default to the last 30 local days. Set inclusive date_from and date_to for a period of up to 366 days. limit accepts 1–100 and defaults to 20. Follow data.next_cursor while data.has_more is true, keeping the same query parameters. Activity lists also accept sport and sort=newest or sort=oldest.
Read responses contain schema_version, generated_at, data and warnings. Daily measurements are returned per saved source, so one date can have several records. Reads use saved data; they do not request fresh data from your devices or providers. See OpenAPI for fields and workout-detail sections.
Send recordings and measurements
With the matching write permission, send a completed recording to POST activities/, or sleep and daily measurements to POST daily-health/. GET connection/ returns the key’s connection, permissions, profile timezone, supported formats and upload limits.
Use the recording and daily-measurement formats from API for Companies, supplying your personal key as the bearer token. The source IDs, revision timestamps, timezone and provenance rules are the same. Start with a test account if your script sends artificial data.
An activity upload returns an import receipt. Save import_job_id and read GET imports/{import_job_id}/: acceptance is separate from publication, and published=true confirms the activity is available. Retry an upload with the same source ID, revision and bytes to avoid creating another import.
Each key has its own upload source and receipts. A replacement key cannot read the previous key’s import receipts. Keep the original key’s receipts in your script when replacing a key; expiry and revocation retain accepted training and daily history.
Expiry and revocation
To stop a script’s access, return to Settings → Integrations → Personal API keys, find its name and select Revoke key. Revocation takes effect immediately. Other keys and imported history remain available.
An expired or revoked key returns 401. Create a replacement in Settings and update the script’s secret. Personal keys have no refresh-token exchange. A 403 means the key lacks the permission required by that route; create a key with the permissions your script needs. A 400 means the request needs correction; inspect the response before retrying.
If a key is exposed, revoke it and replace it. For support, contact hello@effortsignal.com with the endpoint, HTTP status and timestamp. Leave the key, authorization header and private account data out of the message.
Content checked October 22, 2026 · EffortSignal release 0.8.0