Connected Accounts
Connected Accounts is the OpenEdge credential and authorization center. It lets users connect external providers once and reuse those connections from service instances.
Why It Exists
Without Connected Accounts, every service would need to store its own provider key, webhook token, or OAuth token. That is harder to secure, harder to rotate, and harder for customers to understand.
Connected Accounts centralizes:
- Provider catalog.
- Encrypted API key storage.
- Connection status.
- Scopes and provider metadata.
- Testing and audit events.
- OAuth authorization flows.
Supported Providers
| Provider | Auth type | Status | Used by |
|---|---|---|---|
| OpenAI-compatible | API key | Available | AI Model Gateway |
| OpenRouter | API key | Available | AI Model Gateway |
| DeepSeek | API key | Available | AI Model Gateway |
| Custom API Key | API key | Available | AI, Webhook Push, plugins |
| Telegram Bot | API key | Available | Webhook Push |
| Slack | OAuth/webhook | Planned | Webhook Push |
| GitHub | OAuth | Planned | Developer automation |
| Discord | OAuth | Available | Community automation identity grants |
Console Flow
- Open the Console.
- Go to Connections.
- Choose a provider.
- Enter a display name and API key.
- Optionally enter a provider base URL.
- Save and test the connection.
- Reuse it from AI Model Gateway or Webhook Push service configuration.
For Discord, choose Connect from the provider catalog. OpenEdge redirects the user to Discord, validates the OAuth state on callback, encrypts the returned tokens, and stores the Discord user id/name as provider metadata.
API Routes
Console routes require an authenticated console session:
GET /console/connections/providers
GET /console/connections
POST /console/connections/api-key
POST /console/connections/:id/test
DELETE /console/connections/:id
GET /console/connections/:provider/start
GET /oauth/connections/:provider/callbackExample API key connection request:
{
"provider": "openrouter",
"display_name": "OpenRouter Production",
"credentials": {
"api_key": "sk-or-..."
},
"config": {
"base_url": "https://openrouter.ai/api/v1"
},
"scopes": ["chat"]
}Responses never include the raw secret:
{
"success": true,
"data": {
"id": "conn_...",
"provider": "openrouter",
"auth_type": "api_key",
"display_name": "OpenRouter Production",
"status": "active",
"credentials": {
"api_key": "configured...[REDACTED]"
}
}
}Discord OAuth setup requires these Worker secrets/config values:
DISCORD_CLIENT_ID
DISCORD_CLIENT_SECRET
CONFIG_ENCRYPTION_KEY
FRONTEND_URLRegister this redirect URL in the Discord Developer Portal, unless DISCORD_OAUTH_REDIRECT_URI is set to a custom value:
https://api.open4x.com/oauth/connections/discord/callbackService References
Services reference a connection with:
{
"connected_account_id": "conn_..."
}At runtime, OpenEdge checks:
- The connection belongs to the authenticated user.
- The connection is active.
- The provider is allowed for the calling service.
- The encrypted credential can be decrypted.
- Provider configuration such as
base_urlpasses URL safety checks.
Security Requirements
- Raw API keys exist only in request memory.
- Encrypted credentials are stored in D1.
- The encryption key must be configured as
CONFIG_ENCRYPTION_KEY. - OAuth callbacks use one-time states stored in
connection_oauth_states. - Deleted or inactive connections cannot be used by service calls.
- Connection test results store summaries, not full upstream responses.