SucceedAI Proxy API is the production backend used by the macOS app. It keeps AI provider keys off the client, validates the app bearer token, optionally validates Lemon Squeezy licenses, and returns the same response contract expected by the app:
{
"content": "Generated text",
"model": "gpt-5.2",
"provider": "openai"
}The macOS app calls POST /v1/ai/query with:
{
"query": "Follow the instruction from the text in triple quotes below...",
"systemInfo": {
"osName": "macOS",
"osVersion": "15.x",
"model": "Mac"
}
}OpenAI is the default production provider. The backend uses the OpenAI Node SDK with the Responses API, which is the current primary OpenAI text-generation API.
Required Railway variables:
JWT_SECRET: bearer token used by the signed macOS app.OPENAI_API_KEY: OpenAI API key.OPENAI_MODEL: defaults togpt-5.2.
Optional variables:
OPENAI_MAX_OUTPUT_TOKENS: defaults to1200.OPENAI_TIMEOUT_MS: defaults to45000.LICENSE_CHECK_ENABLED: defaults tofalse.LEMON_SQUEEZY_API_KEY: required only when license checks are enabled.BROWSER_EXTENSION_SECRET: optional secondary bearer token.
Legacy Mistral and Claude adapters remain available but are disabled by default. Enable them only after setting their API keys and model names.
cp .env.dist .env
npm install
npm run devUse npm run start:dev when you want the old non-watch TypeScript startup command.
Health check:
curl http://localhost:3004/v1/healthExample app-compatible request:
curl -X POST http://localhost:3004/v1/ai/query \
-H "Authorization: Bearer $JWT_SECRET" \
-H "Content-Type: application/json" \
-d '{"query":"Rewrite this as a concise customer email: hello there","systemInfo":{"osName":"macOS"}}'This repository includes railway.json for Railway config-as-code:
- Build command:
npm ci && npm run build - Start command:
npm start - Health check:
/v1/health - Restart policy:
ON_FAILURE
Recommended setup:
railway variables set NODE_ENV=production
railway variables set JWT_SECRET=<same-token-used-in-the-macos-app>
railway variables set OPENAI_API_KEY=<openai-api-key>
railway variables set OPENAI_MODEL=gpt-5.2
railway upUse .env.railway.example as the deployment checklist. Do not commit .env.
npm run build
npm run typecheck
npm run prettier:check
npm run prettier:fix
npm run prodJWT_SECRETmust not be empty in Railway.OPENAI_API_KEYmust exist only in Railway or local.env.LICENSE_CHECK_ENABLED=falsekeeps the initial app flow working before paid license headers are shipped.- When
LICENSE_CHECK_ENABLED=true, the app must sendLicense: <license-id>:<license-key>.
MIT