API reference
OAuth service
List broker and payment providers, start an OAuth connection, and check whether an account is connected.
How a connection works
- Start
Your server calls
GET /api/v1/oauth/{provider}with your key and gets a redirect to the provider's authorization page. - Authorize
You send the user there, and they approve access on the provider's site.
- Callback
The provider calls back to ENTON, which exchanges the code for tokens and stores them encrypted against the account that owns the key.
- Use
Endpoints such as trade execution then act through that connection. Check it at any time with
GET /api/v1/oauth/{provider}/status.
List providers
/api/v1/oauth/providersThe OAuth providers ENTON lists, each with whether your account has connected it.
Request
No parameters and no body.
Response
200 Providers and connection counts.
| Field | Description |
|---|---|
providersarray of object | Providers. |
providers[].idstring | Provider id. |
providers[].namestring | Display name. |
providers[].descriptionstring | What it offers. |
providers[].categoriesarray of string | Categories. |
providers[].featuresarray of string | Feature list. |
providers[].authTypestring | "oauth". |
providers[].authUrlstring | The path that starts the connection. |
providers[].requiredScopesarray of string | The provider's own scopes. |
providers[].connectedboolean | Whether your account has a token or OAuth key for it. |
providers[].lastConnectedstring or null | When it was connected, or null.date-time |
totalProvidersinteger | Length of providers. |
connectedProvidersinteger | How many are connected. |
availableProvidersinteger | How many are not. |
{
"providers": [
{
"id": "alpaca",
"name": "Alpaca",
"description": "Stock and crypto trading with commission-free access",
"categories": [
"trading",
"stocks",
"crypto"
],
"features": [
"Real-time market data",
"Commission-free trading",
"Paper trading environment",
"Extended hours trading"
],
"authType": "oauth",
"authUrl": "/api/v1/oauth/alpaca",
"requiredScopes": [
"account:read",
"trading",
"data"
],
"connected": true,
"lastConnected": "2026-09-14T17:20:05.000Z"
}
],
"totalProviders": 3,
"connectedProviders": 1,
"availableProviders": 2
}Errors
| Status | When | error |
|---|---|---|
| 403 | The key has neither "oauth:read" nor "*". | Insufficient permissions. Required scope: oauth:read |
| 500 | The lookup failed. | Failed to list OAuth providers. |
Errors use the standard error body. Any request can also get the authentication errors (401) and the rate-limit error (429).
Examples
curl "https://enton.ai/api/v1/oauth/providers" \
-H "Authorization: Bearer $ENTON_API_KEY"Notes
- The list still includes Plaid, which ENTON removed in June 2026. GET /oauth/plaid returns 400. Only alpaca and paypal can be connected.
Start a connection
/api/v1/oauth/{provider}Starts the provider's OAuth flow for the account that owns the key. On success the response is a redirect to the provider's authorization page. After the user approves, the provider calls back to ENTON, which exchanges the code and stores the tokens, encrypted, against the account.
Known issue
Requests that pass the API-key checks currently fail with 401. This endpoint forwards to an internal route that expects a signed-in session, and the forwarded request does not carry one. The failed call still counts against your rate limit and monthly quota. This page will say so when it is fixed.
Request
Path parameters
| Field | Description |
|---|---|
providerstringrequired | Provider id. "coinbase" returns 410.one of "alpaca", "paypal" |
Query parameters
| Field | Description |
|---|---|
redirectstring | Where to send the user afterwards. redirect_uri is accepted as an alias. |
statestring | Opaque value passed through to the flow. |
Response
307 A redirect to the provider's authorization page (Location header). If the provider returns no URL, a 200 JSON body with provider, authorizationUrl, state and message instead.
Errors
| Status | When | error |
|---|---|---|
| 403 | The key has neither "oauth:connect" nor "*". | Insufficient permissions. Required scope: oauth:connect |
| 400 | provider is not alpaca or paypal. | Invalid provider. Supported providers: alpaca, paypal |
| 410 | provider is coinbase. | Coinbase integration is currently disabled |
| 500 | Starting the flow failed. The message names the provider. | Varies |
Errors use the standard error body. Any request can also get the authentication errors (401) and the rate-limit error (429).
Examples
curl -i "https://enton.ai/api/v1/oauth/alpaca?redirect=https%3A%2F%2Fyour-app.example.com%2Fconnected" \
-H "Authorization: Bearer $ENTON_API_KEY"Notes
- The call needs your API key in the Authorization header, so make it from your server and send the user to the Location it returns. A plain browser link cannot add the header.
Check a connection
/api/v1/oauth/{provider}/statusWhether the account that owns the key has connected the provider, and whether its tokens have expired.
Request
Path parameters
| Field | Description |
|---|---|
providerstringrequired | Provider id. "coinbase" returns 410.one of "alpaca", "paypal" |
Response
200 Connection status.
| Field | Description |
|---|---|
connectedboolean | Whether any token or OAuth key exists for the provider. |
providerstring | The provider you asked about. |
statusstring | "expired" when every stored token is past its expiry.one of "active", "expired", "disconnected" |
accountsinteger | Stored tokens plus OAuth keys. |
activeAccountsinteger | Tokens that have not expired. |
lastConnectedstring or null | Newest connection time, or null.date-time |
needsRefreshboolean | True when connected but every token has expired. Reconnect. |
connectionsobject | Counts by kind. |
connections.oauthTokensinteger | OAuth tokens stored. |
connections.oauthApiKeysinteger | OAuth-backed keys stored. |
{
"connected": true,
"provider": "alpaca",
"status": "active",
"accounts": 2,
"activeAccounts": 2,
"lastConnected": "2026-09-14T17:20:05.000Z",
"needsRefresh": false,
"connections": {
"oauthTokens": 2,
"oauthApiKeys": 0
}
}Errors
| Status | When | error |
|---|---|---|
| 403 | The key has neither "oauth:read" nor "*". | Insufficient permissions. Required scope: oauth:read |
| 400 | provider is not alpaca or paypal. | Invalid provider. Supported providers: alpaca, paypal |
| 410 | provider is coinbase. | Coinbase integration is currently disabled |
| 500 | The lookup failed. The message names the provider. | Varies |
Errors use the standard error body. Any request can also get the authentication errors (401) and the rate-limit error (429).
Examples
curl "https://enton.ai/api/v1/oauth/alpaca/status" \
-H "Authorization: Bearer $ENTON_API_KEY"Notes
- Alpaca stores one token per environment you authorized (paper and live), so accounts can be 2 for one Alpaca login.