# Neuroencoder API > EEG embeddings from the EPI-300K foundation model: one 768-d vector per 30 s window of EEG, any montage. Research use only; not a medical device. Base URL: https://api.neuroencoder.com/v1 Auth: Authorization: Bearer $NEUROENCODER_API_KEY (keys look like ne_live_..., 56 characters) ## See real output without a key GET /v1/samples lists precomputed EPI-300K outputs: a full Sleep-EDF night with the scored sleep stage per window, and a 10-minute EDF crop of it with its embeddings (send that file to POST /v1/embeddings to check your setup gives the same numbers). GET /v1/samples/{name} returns the README, licence and the embeddings in the POST /v1/embeddings response format; files are .npz. ## Get a key Agent, no human needed: POST /v1/signup {"agent": true} returns a provisional key at once (no email): curl -X POST https://api.neuroencoder.com/v1/signup -H 'content-type: application/json' -d '{"agent":true}' 2 h of EEG, 20 requests/min, at most 120 windows per request or job, 7 days, 3 per IP per day. The answer carries claim_url: give it to your human; confirming an email there makes the same key a trial key ("email": mails it). Browser: POST /v1/signup with {"email": "you@lab.org"} mails a single-use link (valid 30 minutes) that shows the key once. curl -X POST https://api.neuroencoder.com/v1/signup -H 'content-type: application/json' -d '{"email":"you@lab.org"}' Terminal or agent (no copy-paste): add "device": true. 1. POST /v1/signup {"email": "...", "device": true} -> device_code (keep secret), user_code, interval (5 s), expires_in (1800 s) 2. Show user_code to the human; they open the emailed link and approve if the page shows the same code. 3. POST /v1/signup/token {"device_code": "..."} every interval s: {"status": "pending"} until approved, then the key exactly once. Signing up again for an address that already has a trial key mails a replacement link; the old key stops working when the new one is issued. ## Embed a file curl https://api.neuroencoder.com/v1/embeddings -H "Authorization: Bearer $NEUROENCODER_API_KEY" -F file=@recording.edf EDF, BDF and FIF carry their own rate and channel names. For .npy add -F 'metadata={"sfreq": 256, "channel_names": ["Fp1", "C3", "O2"]}'. JSON also works: {"input": [[...], ...], "sfreq": 256, "channel_names": [...]} (channels x samples), or base64 float32 with "shape". Optional: stride_seconds (default 30), filter (default true), encoding_format ("float" or "base64"), header Idempotency-Key. ## Long recordings: async jobs For a whole night (more than 1024 windows or 512 MB), upload once and poll (steps: https://docs.neuroencoder.com/api#jobs-for-long-recordings). Python client 2.3.0 and later does all of it with neuroencoder.embed_file("night.edf"). 1. POST /v1/files {"filename": "night.edf", "bytes": } -> {"id": "file_...", "upload_url", "upload_headers"} 2. curl -X PUT --upload-file night.edf "" (within 10 minutes; .edf, .bdf or .npy, at most 2 GB) 3. POST /v1/jobs {"file": "file_...", "task": "embeddings", "options": {"stride_seconds": 30, "picks": ["EEG Fpz-Cz"], "channel_names": [...]}} (header Idempotency-Key) -> 202 job 4. GET /v1/jobs/{id} every Retry-After (5) s until status is succeeded, failed or cancelled. 5. result.url: presigned GET (10 minutes; GET the job again for a fresh one) of an .npy float32 [windows, 768]; window i starts at i * result.t_start_step s. Per job: 24 h, 400 M samples, 8192 windows. Quota is reserved at submit and refunded if the job fails or is cancelled (POST /v1/jobs/{id}/cancel). Results are kept 7 days; DELETE /v1/jobs/{id} removes them now. The upload is deleted when the job ends. ## Limits Trial: 100 h of EEG per month, 30 requests/min, 2000 windows/min, 2 requests in flight, 1 running job (20 queued), 30 days. GET /v1/me shows a key's limits. Per request: 1024 windows, 256 channels, 512 MB upload. Billed 30 s per window; failed requests are free. ## Errors Every error from the API is {"error": {"message", "type", "code", "param", "fix"}}. Branch on code; follow fix. The API's 429 and 503 carry Retry-After. A 429 or 503 from the gateway in front of the API (plain text, no code) may not: retry it with exponential backoff and jitter. ## Remote MCP https://api.neuroencoder.com/mcp (streamable HTTP, header Authorization: Bearer ). Tools: account, list_samples, get_sample, create_upload (presigned PUT URL; you upload the local file yourself), start_embedding_job, get_job, get_result_url. claude mcp add --transport http neuroencoder https://api.neuroencoder.com/mcp --header "Authorization: Bearer $NEUROENCODER_API_KEY" Local stdio server with file access: pip install "neuroencoder[mcp]"; neuroencoder mcp ## More OpenAPI: https://api.neuroencoder.com/v1/openapi.json Docs: https://docs.neuroencoder.com/api Docs for agents: https://docs.neuroencoder.com/llms.txt Python: pip install neuroencoder; from neuroencoder import embeddings; embeddings(eeg, sfreq=256, channel_names=[...])