Authentication#

Outeract supports multiple authentication methods depending on your use case. This guide covers all authentication options and best practices.

Overview#

MethodUse CaseEndpoint
API KeysServer-to-server, backend integrationDeveloper GraphQL API
JWT TokensAdmin dashboard, user sessionsAdmin API
OAuthPlatform connections (WhatsApp, Instagram)OAuth endpoints
Webhook SecretsVerifying incoming webhooksWebhook endpoints

API Key Authentication#

API keys are the primary authentication method for backend integrations.

Creating an API Key#

  1. Navigate to Settings → API Keys in the console
  2. Click Create API Key
  3. Enter a descriptive name
  4. Select the required scopes
  5. Set an expiration (optional)
  6. 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/json

Note: API keys are scoped to a specific application. The X-Outeract-App-ID header 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:

ScopePermissions
events:readRead events, messages, edges, conversations
events:writeCreate events, send messages
users:readRead user data and platform users
users:writeCreate and update users
logs:writeCreate log entries associated with events
*All permissions (use with caution)

Example: Minimal scope for sending messages

events:write

Example: Full read access

events:read, users:read

API Key Best Practices#

  1. Use minimal scopes - Only grant the permissions you need
  2. Set expiration dates - Rotate keys regularly
  3. Use environment variables - Never hardcode keys in source code
  4. Create separate keys - Use different keys for different services
  5. Monitor usage - Check the console for unusual activity

API Key Format#

Outeract API keys follow this format:

otr_{environment}_{random}
  • otr_live_* - Production keys
  • otr_test_* - Sandbox/test keys

Required Headers#

All API requests require these headers:

HeaderDescriptionRequired
AuthorizationBearer YOUR_API_KEYYes
X-Outeract-Org-IDOrganization ID (admin only)Admin API only
Content-Typeapplication/jsonFor POST requests

Note: API keys are scoped to a specific application, so the X-Outeract-App-ID header 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 endpoint

Configuration#

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-tenant

Using 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 URL

Starting 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:

PlanRequests/HourBurst Limit
Free1,000100
Pro10,000500
EnterpriseCustomCustom

Rate Limit Headers#

Responses include rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1640000000

Handling 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#

  1. Never expose API keys in client-side code

    • API keys should only be used server-side
    • Use environment variables for storage
  2. Rotate keys regularly

    • Set expiration dates on keys
    • Create new keys before old ones expire
  3. Use HTTPS only

    • All Outeract endpoints require HTTPS
    • Verify SSL certificates in your code
  4. Validate webhook signatures

    • Always verify the X-Outeract-Signature header
    • Reject requests with invalid signatures
  5. Implement proper error handling

    • Don’t leak sensitive information in error messages
    • Log authentication failures for monitoring
  6. 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

More troubleshooting →