Lex API

Integration guide for sending and receiving messages

Authentication

All API requests require an API key, passed as a Bearer token in the Authorization header:

Authorization: Bearer lex2_your_api_key_here

Conversations

All messages are organized into conversations — persistent threads that maintain context. There are two ways to work with them:

Simple: Single Channel

Just send messages without worrying about conversation IDs. All your messages land in a single persistent channel between you and Lex — like a DM thread. Context is maintained automatically across the whole thread.

curl -X POST https://lex.scomatic.com/api/conversations/reply \
  -H "Authorization: Bearer lex2_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Hey Lex, what's new?" }'

That's it. No conversation IDs to track, no state to manage on your end.

Multi-Conversation: Separate Threads

If you want separate threads for different topics, include a conversationId in your requests. Lex includes the conversation ID in webhook payloads and API responses so you can route replies to the right thread.

curl -X POST https://lex.scomatic.com/api/conversations/reply \
  -H "Authorization: Bearer lex2_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Let's continue our earlier discussion",
    "conversationId": "abc-123-..."
  }'

Lex may also create new conversations proactively. Each has a unique UUID included in webhook payloads and available via the conversations list endpoint.

Tip

Start with the simple approach. You can always adopt multi-conversation later — your default channel stays right where it is.


Sending Messages

POST /api/conversations/reply

Send a message to Lex. Returns immediately with 202 Accepted. Lex's reply is delivered asynchronously — via webhook, SSE stream, or polling.

Request Body

FieldTypeRequiredDescription
content string Yes The message text
conversationId string No Target conversation UUID. If omitted, uses your default conversation.

Response

202 Accepted

{
  "success": true,
  "messageId": "a1b2c3d4-...",
  "conversationId": "e5f6g7h8-..."
}

Save the conversationId from the response to continue the same thread.

Error Responses

StatusMeaning
400content is missing or not a string
401Missing or invalid API key
409Conversation is already processing — wait and retry

Receiving Lex's Replies

Three ways to receive messages from Lex. Choose the one that fits your architecture.

Option 1: Webhooks

Lex fires a webhook to your configured URL whenever it sends a message — whether in response to yours or proactively. No polling, no persistent connections needed.

The payload shape is defined by your webhook's body template. Available variables:

VariableDescription
{{message}} The text content of Lex's message
{{conversationId}} UUID of the conversation this message belongs to
{{from}} Sender identifier (e.g. "lex")
{{conversationTitle}} Title of the conversation
{{subject}} Message subject (if applicable)
{{timestamp}} ISO 8601 timestamp of the message
Tip

To reply in the same thread, include the conversationId from the webhook payload in your next request. If you omit it, your message goes to your default conversation.

Option 2: Server-Sent Events (SSE)

Subscribe to a conversation's real-time event stream. This gives you live updates including streaming tokens as Lex thinks, tool usage, and completed messages.

GET /api/conversations/:id/stream

Opens a persistent SSE connection. Sends a connected event immediately, then a conversation:init event with the current state.

Key events:

EventDescription
message:newA new message was saved to the conversation
message:chunkStreaming text token from Lex's response
message:completeLex's response is finished
message:tool_useLex is using a tool (name and input)
message:tool_resultTool execution result
conversation:stateProcessing state changed (thinking, responding, idle)
# Subscribe to a conversation's event stream
curl -N https://lex.scomatic.com/api/conversations/abc-123/stream \
  -H "Authorization: Bearer lex2_your_key"

Option 3: Polling

Fetch messages from a conversation on your own schedule. Use the since parameter to efficiently get only new messages since your last poll.

GET /api/conversations/:id/messages

Returns messages from a conversation in chronological order.

Query ParamTypeDescription
since string Message UUID — returns only messages created after this one
before string Message UUID — returns only messages before this one (for paging backwards)
limit number Maximum number of messages to return
# Get all messages in a conversation
curl https://lex.scomatic.com/api/conversations/abc-123/messages \
  -H "Authorization: Bearer lex2_your_key"

# Get only new messages since your last check
curl "https://lex.scomatic.com/api/conversations/abc-123/messages?since=msg-uuid" \
  -H "Authorization: Bearer lex2_your_key"

Response

{
  "messages": [
    {
      "id": "msg-uuid-1",
      "role": "user",
      "content": "Hey Lex",
      "created_at": "2026-02-25T00:00:00Z"
    },
    {
      "id": "msg-uuid-2",
      "role": "assistant",
      "content": "Hey! What's on your mind?",
      "created_at": "2026-02-25T00:00:01Z"
    }
  ],
  "hasMore": false
}

Other Endpoints

GET /api/conversations

List your conversations, ordered by most recently updated. Returns conversation ID, title, status, and timestamps.

GET /api/conversations/:id

Get a single conversation's metadata and messages. Supports limit and before query parameters for paginated message loading.

Webhook Configuration

GET /api/webhooks/me

Get your current webhook configuration. Returns null if no webhook is set up.

PUT /api/webhooks/me

Create or update your webhook configuration.

{
  "url": "https://your-app.example.com/webhook",
  "method": "POST",                          // optional, default: POST
  "headers": {                                // optional custom headers
    "X-Custom-Auth": "your-secret"
  },
  "bodyTemplate": {                           // optional, defines payload shape
    "text": "{{message}}",
    "conversation": "{{conversationId}}",
    "sender": "{{from}}"
  }
}
POST /api/webhooks/me/test

Send a test payload to your configured webhook. Returns the HTTP status code from your server.

DELETE /api/webhooks/me

Remove your webhook configuration. You can still receive messages via SSE or polling.

Conversation Info

GET /api/conversations/:id/status

Check if a conversation is currently being processed. Returns active (boolean) and state (e.g. "thinking", "responding", or null if idle).


Example: Full Round Trip

# 1. Send a message (no conversationId — uses your default channel)
curl -X POST https://lex.scomatic.com/api/conversations/reply \
  -H "Authorization: Bearer lex2_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "content": "What are you working on today?" }'

# Response: { "success": true, "conversationId": "abc-123-..." }

# 2. Lex processes your message and fires your webhook:
# POST https://your-app.example.com/webhook
# {
#   "text": "I've been working on the API docs...",
#   "conversationId": "abc-123-...",
#   "from": "lex"
# }

# 3. Or poll for the reply instead of using a webhook
curl "https://lex.scomatic.com/api/conversations/abc-123/messages?since=msg-uuid" \
  -H "Authorization: Bearer lex2_your_key"

# 4. Reply in the same conversation
curl -X POST https://lex.scomatic.com/api/conversations/reply \
  -H "Authorization: Bearer lex2_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Tell me more about that",
    "conversationId": "abc-123-..."
  }'
← Back to login