Quick Start Guide#

Get Outeract running in your application in under 5 minutes.

TL;DR#

# 1. Set your API key
export OUTERACT_API_KEY="your-api-key"

# 2. Send a message (GraphQL over HTTP)
curl https://api.outeract.com/ \
  -H "Authorization: Bearer $OUTERACT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SendMessage($userId: UUID!, $message: String!) { sendMessage(recipientUserId: $userId, message: $message) { id eventTypeName createdAt } }",
    "variables": {
      "userId": "RECIPIENT_USER_ID",
      "message": "Hello from Outeract!"
    }
  }'

The API is GraphQL, and all operations go to https://api.outeract.com/ as a POST with a query (and optional variables). The same URL serves GraphiQL in your browser for exploring the schema.

Step-by-Step#

1. Sign Up and Create an Application#

  1. Sign up, then open the console
  2. Create a new application - this is your messaging container
  3. Copy your Application ID from the dashboard

2. Create an API Key#

  1. Navigate to Settings → API Keys
  2. Click Create API Key
  3. Select scopes:
    • events:read - For reading messages
    • events:write - For sending messages
    • users:read - For user lookups
    • users:write - For user management
  4. Save your API key - it’s only shown once

API keys are scoped to a single application, so you don’t need to send an X-Outeract-App-ID header.

3. Connect a Platform#

Choose your messaging platform and follow the setup:

PlatformAuth TypeSetup Time
WhatsAppOAuth5 min
InstagramOAuth5 min
TelegramBot Token2 min
SlackBot Token3 min
DiscordBot Token3 min
TwilioAPI Key2 min
EmailAPI Key2 min

After connecting, copy your Platform Connection ID.

4. Send Your First Message#

Users are created automatically when someone messages one of your connected platforms. Message your bot or number from your own account, then look the user up:

query {
  users(first: 10) {
    edges {
      node {
        id
        name
        identities {
          externalId
          identityType
        }
      }
    }
  }
}

Then send a message to that user. Outeract infers the platform and sender automatically (pass platformConnectionId to pick a specific connection):

curl https://api.outeract.com/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation SendMessage($userId: UUID!, $message: String!) { sendMessage(recipientUserId: $userId, message: $message) { id eventTypeName payload createdAt } }",
    "variables": {
      "userId": "RECIPIENT_USER_ID",
      "message": "Hello from Outeract!"
    }
  }'
import requests

response = requests.post(
    "https://api.outeract.com/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "query": """
            mutation SendMessage($userId: UUID!, $message: String!) {
              sendMessage(recipientUserId: $userId, message: $message) {
                id
                eventTypeName
                payload
                createdAt
              }
            }
        """,
        "variables": {
            "userId": "RECIPIENT_USER_ID",
            "message": "Hello from Outeract!",
        },
    },
)

print(response.json())
const response = await fetch('https://api.outeract.com/', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query: `
      mutation SendMessage($userId: UUID!, $message: String!) {
        sendMessage(recipientUserId: $userId, message: $message) {
          id
          eventTypeName
          payload
          createdAt
        }
      }
    `,
    variables: {
      userId: 'RECIPIENT_USER_ID',
      message: 'Hello from Outeract!'
    }
  })
});

const data = await response.json();
console.log(data);

Response:

{
  "data": {
    "sendMessage": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "eventTypeName": "message.outbound",
      "payload": {
        "type": "message",
        "message": { "text": "Hello from Outeract!", "role": "assistant" }
      },
      "createdAt": "2024-01-15T10:30:00Z"
    }
  }
}

5. Receive Messages (Optional)#

Set up a webhook subscription to receive incoming messages. Subscriptions are managed in the console under Settings → Webhooks: give it a name, point it at your endpoint URL, and select the event types you care about (e.g. message.inbound).

Your server will receive POST requests like:

{
  "event_id": "123e4567-e89b-12d3-a456-426614174000",
  "event_type": "message.inbound",
  "timestamp": "2024-01-15T10:30:00Z",
  "app_id": "app-uuid",
  "data": {
    "type": "message",
    "message": {
      "text": "Hello!",
      "role": "user"
    },
    "user_id": "sender-user-uuid",
    "from_user_id": "sender-user-uuid",
    "from_identity_id": "sender-identity-uuid"
  },
  "edges": [
    {
      "edge_type": "sent_by",
      "target_node_type": "identity",
      "target_node_id": "sender-identity-uuid"
    }
  ]
}

Example: Echo Bot#

Here’s a complete example that echoes messages back:

from flask import Flask, request, jsonify
import requests
import hmac
import hashlib

app = Flask(__name__)

OUTERACT_API_KEY = "your-api-key"
WEBHOOK_SECRET = "your-webhook-secret"

SEND_MESSAGE = """
mutation SendMessage($userId: UUID!, $message: String!) {
  sendMessage(recipientUserId: $userId, message: $message) {
    id
  }
}
"""

@app.route("/webhooks/outeract", methods=["POST"])
def handle_webhook():
    # Verify signature
    signature = request.headers.get("X-Outeract-Signature")
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        request.data,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(f"sha256={expected}", signature):
        return jsonify({"error": "Invalid signature"}), 401

    data = request.json

    if data["event_type"] == "message.inbound":
        # Echo the message back to the sender
        sender_user_id = data["data"]["user_id"]
        message_text = data["data"]["message"]["text"]

        requests.post(
            "https://api.outeract.com/",
            headers={"Authorization": f"Bearer {OUTERACT_API_KEY}"},
            json={
                "query": SEND_MESSAGE,
                "variables": {
                    "userId": sender_user_id,
                    "message": f"You said: {message_text}",
                },
            },
        )

    return jsonify({"status": "ok"})

if __name__ == "__main__":
    app.run(port=3000)
const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

const OUTERACT_API_KEY = 'your-api-key';
const WEBHOOK_SECRET = 'your-webhook-secret';

const SEND_MESSAGE = `
  mutation SendMessage($userId: UUID!, $message: String!) {
    sendMessage(recipientUserId: $userId, message: $message) {
      id
    }
  }
`;

app.post('/webhooks/outeract', async (req, res) => {
  // Verify signature
  const signature = req.headers['x-outeract-signature'];
  const expected = 'sha256=' + crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const { event_type, data } = req.body;

  if (event_type === 'message.inbound') {
    // Echo the message back to the sender
    await fetch('https://api.outeract.com/', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${OUTERACT_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        query: SEND_MESSAGE,
        variables: {
          userId: data.user_id,
          message: `You said: ${data.message.text}`
        }
      })
    });
  }

  res.json({ status: 'ok' });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Next Steps#

Common Issues#

“Unauthorized” Error#

  • Check your API key is correct
  • Ensure your API key has the required scopes

“Platform Connection Not Found”#

  • Verify the platformConnectionId is correct
  • Check the connection is active in the console

Messages Not Delivering#

  • For WhatsApp: Ensure the recipient has messaged you first (24-hour window)
  • For Telegram: Bot must be started by the user first
  • Check the platform connection health in the console

More troubleshooting →