User & Settings
Everything under /api/v1/user acts on the authenticated account. Three of these endpoints are
Pro-gated; the rest, including every export, work on any plan.
Get Current User
Section titled “Get Current User”GET /api/v1/user/me
Returns the profile, the current idea count, and trial state. Encrypted provider keys are
stripped and replaced by has_*_key booleans.
curl https://neuralrepo.com/api/v1/user/me \ -H "X-API-Key: nrp_YOUR_KEY"const res = await fetch("https://neuralrepo.com/api/v1/user/me", { headers: { "X-API-Key": "nrp_YOUR_KEY" },});const user = await res.json();Response 200 OK
{ "id": "3f2a91c47b0e4d5aa8c61e0f2b7d4c93", "email": "you@example.com", "display_name": "Jane Doe", "avatar_url": "https://avatars.githubusercontent.com/u/1?v=4", "plan": "pro", "settings_json": "{\"preferred_ai_provider\":\"anthropic\"}", "has_anthropic_key": true, "has_openai_key": false, "has_openrouter_key": false, "trial_ends_at": "2026-04-01 00:00:00", "trial_used": 1, "active_idea_count": 137, "is_trialing": true, "trial_days_remaining": 6, "created_at": "2026-01-15 08:00:00", "updated_at": "2026-03-20 12:00:00"}| Field | Meaning |
|---|---|
plan | free or pro. Trialing accounts read pro — the gates treat them as Pro |
active_idea_count | Unarchived ideas; compare with 50 to see how close a Free account is to its cap |
is_trialing | true only when the plan is pro, the trial has not ended, and there is no Stripe subscription |
trial_days_remaining | Whole days, rounded up; null when not trialing |
Update Profile
Section titled “Update Profile”PATCH /api/v1/user/me
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | No | 1–100 characters |
settings_json | string | No | A JSON string, max 10,000 characters. See User Settings |
curl -X PATCH https://neuralrepo.com/api/v1/user/me \ -H "X-API-Key: nrp_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"display_name": "Jane D.", "settings_json": "{\"search_threshold\":0.3}"}'Response 200 OK — the updated user object, with the same stripped fields as GET /user/me
but without active_idea_count and the trial fields.
API Keys
Section titled “API Keys”List Keys
Section titled “List Keys”GET /api/v1/user/api-keys
Returns every key on the account, newest first, with no key material — not even a masked prefix.
Response 200 OK
{ "api_keys": [ { "id": "9c4f1b7e2d3a48f0b6e5c8d1a2f7b904", "label": "CI Pipeline", "scopes": null, "source": "manual", "last_used_at": "2026-03-24 08:12:00", "created_at": "2026-03-20 10:00:00" } ]}source is manual for keys made here and mcp for tokens minted by the MCP OAuth flow;
scopes is null on every manual key, which means full access.
Create Key
Section titled “Create Key”POST /api/v1/user/api-keys
| Field | Type | Required | Description |
|---|---|---|---|
label | string | No | Max 100 characters; defaults to default |
Response 201 Created
{ "id": "9c4f1b7e2d3a48f0b6e5c8d1a2f7b904", "key": "nrp_a1b2c3d4...", "label": "CI Pipeline", "created_at": "2026-03-24 09:00:00"}Delete Key
Section titled “Delete Key”DELETE /api/v1/user/api-keys/:id
Revokes the key immediately, using the id from the list endpoint (a 32-character hex string,
not the key itself). Works on every plan. Returns 404 if the id is not yours.
Response 200 OK
{ "success": true}MCP Tokens
Section titled “MCP Tokens”GET /api/v1/user/mcp-tokens
Lists the tokens issued by the MCP OAuth flow when you authorize a client such as Claude. It does not create tokens — the client does that during authorization.
Response 200 OK
{ "tokens": [ { "id": "b17d0e59a4c34f8e91d2c6b7f0a35e82", "label": "MCP (claude-ai)", "scopes": "ideas:read ideas:write", "source": "mcp", "last_used_at": "2026-03-24 08:00:00", "created_at": "2026-03-20 10:00:00" } ]}The client’s identity appears inside label; there is no separate client_id field. Revoke a
token with DELETE /api/v1/user/api-keys/:id — MCP tokens live in the same store as API keys.
BYOK (Bring Your Own Key)
Section titled “BYOK (Bring Your Own Key)”AI features that run on your own provider account — POST /ideas/:id/develop in this API — need
a stored provider key. NeuralRepo encrypts it at rest and never returns it.
Save Provider Key
Section titled “Save Provider Key”PUT /api/v1/user/byok/:provider
Pro only. :provider must be anthropic, openai, or openrouter.
| Field | Type | Required | Description |
|---|---|---|---|
api_key | string | Yes | Your provider key; must be at least 10 characters |
curl -X PUT https://neuralrepo.com/api/v1/user/byok/anthropic \ -H "X-API-Key: nrp_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"api_key": "sk-ant-..."}'The key is stored without being tested — a typo is accepted here and fails later at
develop time. Run the test endpoint below to confirm it works.
Response 200 OK
{ "success": true, "provider": "anthropic"}Delete Provider Key
Section titled “Delete Provider Key”DELETE /api/v1/user/byok/:provider
Removes the stored key. Unlike saving and testing, this is not Pro-gated — an account that lapses to Free can still delete keys it stored while on Pro.
Response 200 OK
{ "success": true, "provider": "anthropic"}Test Provider Key
Section titled “Test Provider Key”POST /api/v1/user/byok/:provider/test
Pro only. Decrypts the stored key and makes a minimal live call to the provider.
curl -X POST https://neuralrepo.com/api/v1/user/byok/anthropic/test \ -H "X-API-Key: nrp_YOUR_KEY"Response 200 OK
{ "ok": true}A failure is also 200, with the reason in the body: { "ok": false, "error": "No anthropic key configured" }
when nothing is stored, or the provider’s own message when the call is rejected. Check ok,
not the status code.
Check All Providers
Section titled “Check All Providers”GET /api/v1/user/byok/status
Returns which providers have keys and which one will actually be used.
Response 200 OK
{ "active_provider": "anthropic", "has_anthropic_key": true, "has_openai_key": false, "has_openrouter_key": false}active_provider resolves as: your preferred_ai_provider setting if a key for it is
stored, otherwise the first available in the fixed order Anthropic → OpenAI → OpenRouter. It is
null when no keys are stored — which is when develop returns needs_byok. Setting a
preference for a provider you have no key for is silently ignored rather than erroring.
Shortcuts
Section titled “Shortcuts”GET /api/v1/user/shortcuts
Returns the iCloud Shortcut URL used for Siri capture. The same URL for every account.
curl https://neuralrepo.com/api/v1/user/shortcuts \ -H "X-API-Key: nrp_YOUR_KEY"Response 200 OK
{ "quick_capture_url": "https://www.icloud.com/shortcuts/..."}Support Link
Section titled “Support Link”GET /api/v1/user/support-link
Mints a single-use, pre-authenticated URL into the NeuralRepo support site for the account’s email address, so you arrive already signed in.
Response 200 OK
{ "url": "https://support.neuralrepo.com/..."}Returns 502 { "error": "Failed to generate support link" } if the support service is
unreachable. Treat the URL as a credential — anyone holding it is signed in as you.
Test Digest
Section titled “Test Digest”POST /api/v1/user/test-digest
Sends the weekly digest email to your own address immediately, and returns the rendered content so you can preview it without waiting for Sunday.
curl -X POST https://neuralrepo.com/api/v1/user/test-digest \ -H "X-API-Key: nrp_YOUR_KEY"Response 200 OK
{ "success": true, "content": "..."}If sending fails, the endpoint returns 500 with the underlying error message.
User Settings
Section titled “User Settings”settings_json is a JSON string on the profile. Values outside the stated ranges are discarded
when the settings are parsed, and the default applies instead — nothing reports the mistake.
| Field | Type | Range | Default | Description |
|---|---|---|---|---|
preferred_ai_provider | string | anthropic, openai, openrouter | — | Provider for develop, if a key for it is stored |
search_threshold | number | 0.1–0.9 | 0.2 | Semantic results must score above this |
dedup_threshold | number | 0.1–0.9 | 0.75 | Score above which a pair is flagged as a duplicate |
related_threshold | number | 0.1–0.9 | 0.5 | Score above which a related edge is created automatically |
code_mode | boolean | — | — | Exposes the MCP code-mode tool surface |
weekly_digest | boolean | — | opted in | Only an explicit false stops the Sunday digest |
stale_nudges | boolean | — | opted in | Only an explicit false stops stale-idea nudge emails |
stale_threshold_days | integer | 7–180 | 30 | Days before a captured idea counts as stale |
Data Export
Section titled “Data Export”Export is available on every plan, and all three endpoints are POST with no body. Each
covers up to 10,000 ideas and excludes archived ideas — export before you archive, not after.
JSON Export
Section titled “JSON Export”POST /api/v1/user/export
The complete dump: profile, ideas with their tags, links, and relations, plus the tag list with
counts. Returned as a JSON body (not a file download), stamped with exported_at.
curl -X POST https://neuralrepo.com/api/v1/user/export \ -H "X-API-Key: nrp_YOUR_KEY" \ -o export.jsonCSV Export
Section titled “CSV Export”POST /api/v1/user/export/csv
A flat table for spreadsheets: id, number, title, body, status, tags (semicolon
separated), source, created_at. Sent as a UTF-8 BOM’d text/csv attachment named
neuralrepo-ideas-YYYY-MM-DD.csv. Relations and links are not included.
curl -X POST https://neuralrepo.com/api/v1/user/export/csv \ -H "X-API-Key: nrp_YOUR_KEY" \ -o export.csvMarkdown Export
Section titled “Markdown Export”POST /api/v1/user/export/markdown
A ZIP of one Markdown file per idea, named NNNN-slug.md from the idea’s display number and
title. Each file carries YAML frontmatter (number, title, status, source, tags,
created, updated), the body, a Links section, and a Related section where relations become
[[wiki-links]] — so an Obsidian vault reproduces your mind map graph.
curl -X POST https://neuralrepo.com/api/v1/user/export/markdown \ -H "X-API-Key: nrp_YOUR_KEY" \ -o neuralrepo-markdown.zipStatus Codes
Section titled “Status Codes”| Status | Meaning |
|---|---|
200 OK | Successful read, update, delete, or export |
201 Created | API key created |
400 Bad Request | Validation error, or an unknown BYOK provider |
401 Unauthorized | Missing or invalid auth |
403 Forbidden | Pro-only endpoint on a Free plan (pro_required: true) |
404 Not Found | API key id not yours, or the user record is missing |
500 Internal Server Error | test-digest failed to send |
502 Bad Gateway | The support service could not mint a link |