Skip to content

Authentication Guide

Learn how to authenticate with the Connix API using API keys and OAuth2. This guide covers everything from getting your first API key to implementing secure authentication in production applications.

Connix supports two primary authentication methods:

  1. API Key Authentication - Simple and secure for server-to-server communication
  2. OAuth2 Authentication - Industry standard for user-facing applications

API key authentication is the simplest and most common method for accessing the Connix API.

  1. Sign in to console.connix.io
  2. Navigate to SettingsAPI Keys
  3. Click Generate New API Key
  4. Copy and securely store your API key
  5. Name your key for easy identification

Include your API key in the X-API-Key header:

Terminal window
curl -X GET https://api.connix.io/api/v1/projects \
-H "X-API-Key: cx_1234567890abcdef1234567890abcdef"

Store API keys securely using environment variables:

Terminal window
# Add to ~/.bashrc or ~/.zshrc
export CONNIX_API_KEY="cx_1234567890abcdef1234567890abcdef"
# Reload your shell
source ~/.bashrc

Most Connix SDKs automatically detect environment variables:

import { ConnixClient } from '@connix/sdk';
// Auto-detects CONNIX_API_KEY
const client = new ConnixClient();
// Or explicit
const client = new ConnixClient({
apiKey: process.env.CONNIX_API_KEY
});

OAuth2 is ideal for user-facing applications where you need to act on behalf of users.

  1. Authorization Request - Redirect user to Connix authorization server
  2. User Consent - User grants permissions to your application
  3. Authorization Code - Connix redirects back with authorization code
  4. Token Exchange - Exchange code for access token
  5. API Requests - Use access token for authenticated requests

Register your application at console.connix.io:

  1. Go to SettingsOAuth Applications
  2. Click New OAuth Application
  3. Fill in your application details:
    • Application Name: Your app name
    • Homepage URL: Your app’s homepage
    • Callback URL: Where users return after authorization
  4. Note your Client ID and Client Secret

Authorization URL:

https://console.connix.io/oauth2/authorize

Token URL:

https://console.connix.io/oauth2/token

Available OAuth2 scopes:

ScopeDescription
readRead access to user’s projects and agents
writeFull access to create, update, and delete resources
const express = require('express');
const app = express();
const CLIENT_ID = 'your-client-id';
const CLIENT_SECRET = 'your-client-secret';
const REDIRECT_URI = 'http://localhost:3000/callback';
// Step 1: Redirect to authorization
app.get('/auth', (req, res) => {
const authUrl = new URL('https://console.connix.io/oauth2/authorize');
authUrl.searchParams.set('client_id', CLIENT_ID);
authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'read write');
authUrl.searchParams.set('state', 'random-state-string');
res.redirect(authUrl.toString());
});
// Step 2: Handle callback
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// Verify state parameter (important for security)
if (state !== 'random-state-string') {
return res.status(400).send('Invalid state');
}
// Exchange code for token
const tokenResponse = await fetch('https://console.connix.io/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: code,
redirect_uri: REDIRECT_URI
})
});
const tokens = await tokenResponse.json();
// Store tokens securely (session, database, etc.)
req.session.accessToken = tokens.access_token;
req.session.refreshToken = tokens.refresh_token;
res.redirect('/dashboard');
});
// Use access token for API requests
app.get('/api/projects', async (req, res) => {
const accessToken = req.session.accessToken;
const response = await fetch('https://api.connix.io/api/v1/projects', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const projects = await response.json();
res.json(projects);
});

Access tokens expire after 1 hour. Use refresh tokens to get new access tokens:

async function refreshAccessToken(refreshToken) {
const response = await fetch('https://console.connix.io/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
refresh_token: refreshToken
})
});
const tokens = await response.json();
// Update stored tokens
localStorage.setItem('access_token', tokens.access_token);
if (tokens.refresh_token) {
localStorage.setItem('refresh_token', tokens.refresh_token);
}
return tokens.access_token;
}
// Automatic token refresh on API calls
async function makeAuthenticatedRequest(url, options = {}) {
let accessToken = localStorage.getItem('access_token');
const response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${accessToken}`
}
});
// If token expired, refresh and retry
if (response.status === 401) {
const refreshToken = localStorage.getItem('refresh_token');
accessToken = await refreshAccessToken(refreshToken);
// Retry request with new token
return fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${accessToken}`
}
});
}
return response;
}
  1. Never expose API keys in client-side code
  2. Use environment variables, never hardcode keys
  3. Rotate keys regularly (every 90 days)
  4. Use different keys for different environments
  5. Monitor key usage for unusual activity
  6. Revoke compromised keys immediately
  1. Always validate the state parameter
  2. Use HTTPS for all OAuth flows
  3. Store tokens securely (encrypted if possible)
  4. Implement proper token refresh logic
  5. Use short-lived access tokens
  6. Validate redirect URIs strictly
  7. Implement CSRF protection
// Implement exponential backoff for rate limits
async function makeRequestWithBackoff(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, i) * 1000;
console.log(`Rate limited, retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Terminal window
# Test API key
curl -X GET https://api.connix.io/api/v1/hello?name=Test \
-H "X-API-Key: $CONNIX_API_KEY"
# Expected response:
# {"message": "Hello Test! Welcome to Connix API v1"}

Create a simple test application to verify your OAuth2 setup:

// Simple OAuth2 test server
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send(`
<h1>Connix OAuth2 Test</h1>
<a href="/auth">Sign in with Connix</a>
`);
});
app.get('/auth', (req, res) => {
const authUrl = new URL('https://console.connix.io/oauth2/authorize');
authUrl.searchParams.set('client_id', process.env.CLIENT_ID);
authUrl.searchParams.set('redirect_uri', 'http://localhost:3000/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'read');
authUrl.searchParams.set('state', 'test-state');
res.redirect(authUrl.toString());
});
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
if (state !== 'test-state') {
return res.status(400).send('Invalid state');
}
try {
// Exchange code for token
const tokenResponse = await fetch('https://console.connix.io/oauth2/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code: code,
redirect_uri: 'http://localhost:3000/callback'
})
});
const tokens = await tokenResponse.json();
res.json({
message: 'OAuth2 flow successful!',
token_type: tokens.token_type,
expires_in: tokens.expires_in,
scope: tokens.scope
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('OAuth2 test server running on http://localhost:3000');
});

Invalid API Key (401)

  • Verify the API key is correct and active
  • Check that you’re using the X-API-Key header
  • Ensure the key hasn’t been revoked

Rate Limiting (429)

  • Implement exponential backoff
  • Check rate limit headers
  • Consider upgrading your plan

OAuth2 State Mismatch

  • Verify the state parameter matches
  • Ensure proper session management
  • Check for URL encoding issues

Token Expired

  • Implement automatic token refresh
  • Check token expiration times
  • Ensure refresh tokens are stored securely

If you encounter authentication issues:

  1. Check the API status page
  2. Review your API key permissions
  3. Test with the hello endpoint first
  4. Contact engineering@connix.io