Authentication#
Outeract supports multiple authentication methods depending on your use case. This guide covers all authentication options and best practices.
Overview#
| Method | Use Case | Endpoint |
|---|---|---|
| API Keys | Server-to-server, backend integration | Developer GraphQL API |
| JWT Tokens | Admin dashboard, user sessions | Admin API |
| OAuth | Platform connections (WhatsApp, Instagram) | OAuth endpoints |
| Webhook Secrets | Verifying incoming webhooks | Webhook endpoints |
API Key Authentication#
API keys are the primary authentication method for backend integrations.
Creating an API Key#
- Navigate to Settings → API Keys in the console
- Click Create API Key
- Enter a descriptive name
- Select the required scopes
- Set an expiration (optional)
- Click Create
Using API Keys#
Include your API key in the Authorization header:
POST / HTTP/1.1
Host: api.outeract.com
Authorization: Bearer otr_live_abc123...
Content-Type: application/jsonNote: API keys are scoped to a specific application. The
X-Outeract-App-IDheader is not required when using API key authentication - the app context is automatically derived from the key itself.
API Key Scopes#
Scopes control what operations an API key can perform:
| Scope | Permissions |
|---|---|
events:read | Read events, messages, edges, conversations |
events:write | Create events, send messages |
users:read | Read user data and platform users |
users:write | Create and update users |
logs:write | Create log entries associated with events |
* | All permissions (use with caution) |
Example: Minimal scope for sending messages
events:writeExample: Full read access
events:read, users:readAPI Key Best Practices#
- Use minimal scopes - Only grant the permissions you need
- Set expiration dates - Rotate keys regularly
- Use environment variables - Never hardcode keys in source code
- Create separate keys - Use different keys for different services
- Monitor usage - Check the console for unusual activity
API Key Format#
Outeract API keys follow this format:
otr_{environment}_{random}otr_live_*- Production keysotr_test_*- Sandbox/test keys
Required Headers#
All API requests require these headers:
| Header | Description | Required |
|---|---|---|
Authorization | Bearer YOUR_API_KEY | Yes |
X-Outeract-Org-ID | Organization ID (admin only) | Admin API only |
Content-Type | application/json | For POST requests |
Note: API keys are scoped to a specific application, so the
X-Outeract-App-IDheader is not required when using API key authentication.
JWT Authentication (Admin API)#
The Admin API uses JWT tokens for authentication. This is primarily used by the Outeract Console and admin applications.
JWT Flow#
1. User authenticates with identity provider (Firebase, Auth0, etc.)
2. Identity provider issues JWT token
3. Include JWT in Authorization header
4. Outeract validates JWT against configured JWKS endpointConfiguration#
JWT validation is configured via environment variables:
# Primary JWT (Firebase)
TOKEN_JWKS_URI=https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com
TOKEN_ISSUER=https://securetoken.google.com/your-project
TOKEN_AUDIENCES=your-project
# Firebase tenant (optional)
FIREBASE_PROJECT_ID=your-project
FIREBASE_TENANT_ID=your-tenantUsing JWT Tokens#
POST /admin HTTP/1.1
Host: api.outeract.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
X-Outeract-Org-ID: org_abc123
Content-Type: application/json
{
"query": "{ organisation { id name } }"
}OAuth (Platform Connections)#
OAuth is used to connect Meta platforms (WhatsApp, Instagram, Facebook Messenger).
OAuth Flow#
1. Your app redirects to Outeract OAuth endpoint
2. User authorizes on Meta
3. Meta redirects back to Outeract
4. Outeract exchanges code for tokens
5. Outeract redirects to your callback URLStarting OAuth#
mutation {
startPlatformOAuth(
platformName: WHATSAPP
redirectUri: "https://yourapp.com/oauth/callback"
) {
authorizationUrl
state
}
}Handling the Callback#
After authorization, the user is redirected to your redirectUri with:
code- Authorization code (handled by Outeract)state- State parameter for CSRF protection
The platform connection is automatically created with the obtained tokens.
Token Refresh#
Outeract automatically refreshes OAuth tokens before they expire. You don’t need to handle token refresh yourself.
Webhook Signature Verification#
When receiving webhooks, verify the signature to ensure the request is from Outeract.
Signature Format#
Outeract sends a signature in the X-Outeract-Signature header:
sha256=abc123...Verification Example#
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
# Usage
is_valid = verify_webhook(
request.data,
request.headers.get("X-Outeract-Signature"),
WEBHOOK_SECRET
)const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Usage
const isValid = verifyWebhook(
JSON.stringify(req.body),
req.headers['x-outeract-signature'],
WEBHOOK_SECRET
);import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
func verifyWebhook(payload []byte, signature, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(payload)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signature))
}Rate Limiting#
API requests are rate limited based on your plan:
| Plan | Requests/Hour | Burst Limit |
|---|---|---|
| Free | 1,000 | 100 |
| Pro | 10,000 | 500 |
| Enterprise | Custom | Custom |
Rate Limit Headers#
Responses include rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1640000000Handling Rate Limits#
When rate limited, you’ll receive a 429 Too Many Requests response:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 60 seconds.",
"retry_after": 60
}
}Implement exponential backoff:
import time
import requests
def make_request_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after * (2 ** attempt))
continue
return response
raise Exception("Max retries exceeded")Security Best Practices#
Never expose API keys in client-side code
- API keys should only be used server-side
- Use environment variables for storage
Rotate keys regularly
- Set expiration dates on keys
- Create new keys before old ones expire
Use HTTPS only
- All Outeract endpoints require HTTPS
- Verify SSL certificates in your code
Validate webhook signatures
- Always verify the
X-Outeract-Signatureheader - Reject requests with invalid signatures
- Always verify the
Implement proper error handling
- Don’t leak sensitive information in error messages
- Log authentication failures for monitoring
Use IP allowlisting (Enterprise)
- Restrict API access to specific IP ranges
- Contact support to enable
Troubleshooting#
“Unauthorized” (401)#
- Verify your API key is correct
- Check the key hasn’t expired
- Ensure required headers are present
“Forbidden” (403)#
- API key lacks required scopes
- Organization/Application ID mismatch
- Resource belongs to different organization
“Rate Limited” (429)#
- Implement request throttling
- Use exponential backoff
- Consider upgrading your plan