Your First Message#

This guide walks you through sending your first message with Outeract: finding (or creating) the recipient, sending via the sendMessage mutation, and inspecting the event it creates.

Prerequisites#

  • An application and API key: see Quick Start and Authentication
  • At least one connected platform (WhatsApp, Telegram, Slack, etc.)

All examples use the Developer GraphQL API. Send a POST request to https://api.outeract.com/ with your API key:

POST https://api.outeract.com/
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
API keys are scoped to an application, so no extra headers are needed. If your key spans multiple apps, add `X-Outeract-App-ID: YOUR_APP_ID` to target one.

Step 1: Find your recipient#

Messages are sent to users. A user can have multiple identities, one per platform (a WhatsApp number, a Slack ID, and so on). When someone messages you first, Outeract creates their user and identity automatically, so the quickest path is to send a message to your connected platform account from your own phone, then look yourself up:

query {
  users(first: 10, orderBy: "last_active_at") {
    edges {
      node {
        id
        name
        lastActiveAt
        identities {
          id
          externalId
          identityType
          platformConnection { id platformName }
        }
      }
    }
  }
}

You can also search by name, phone number, or external ID:

query {
  users(first: 5, search: "+14155551234") {
    edges { node { id name } }
  }
}

Creating the recipient manually#

If the user has never messaged you, create them and attach a platform identity:

mutation {
  createUser(name: "Alice") {
    id
  }
}
mutation {
  createIdentity(
    userId: "USER_ID"
    externalId: "+14155551234"
    identityType: "whatsapp"
  ) {
    id
    externalId
  }
}
Most platforms restrict who a business can message first. WhatsApp, for example, only allows free-form messages inside a 24-hour window after the user's last message. Outside it you must use a [template](/docs/guides/sending-messages/). The simplest first test is to message your connected account from your own device and reply to yourself.

Step 2: Send the message#

Use the sendMessage mutation. The simplest form takes a recipient and the text. Outeract infers the platform from the recipient’s identities and sends from your connection’s system (bot) user:

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

If the recipient has identities on several platforms, pin the platform explicitly:

mutation {
  sendMessage(
    recipientUserId: "USER_ID"
    message: "Hello via WhatsApp"
    platform: WHATSAPP
  ) {
    id
  }
}

Sending to a conversation instead#

Once a conversation exists between your system user and the recipient (created automatically on the first message), you can address it directly and let Outeract infer the recipient from the participants:

query {
  conversations(first: 10) {
    edges {
      node {
        id
        title
        messageCount
        participants { userId userName }
      }
    }
  }
}
mutation {
  sendMessage(
    conversationId: "CONVERSATION_ID"
    message: "Replying in the same thread"
  ) {
    id
  }
}

Provide either recipientUserId or conversationId, never both. The full set of options (files, templates, sender overrides, connection selection) is covered in Sending Messages.

Step 3: Inspect the event#

sendMessage returns an event. Everything in Outeract is stored as an event in the ledger. Query it back with its graph edges to see how it connects to the sender, recipient, and conversation:

query {
  event(id: "EVENT_ID") {
    id
    eventTypeName    # "message.outbound"
    payload
    createdAt
    edges {
      edgeType       # sent_by / sent_to / in_conversation
      targetNodeType # identity / event
      targetNodeId   # resolve with identities(identityIds:) etc.
    }
  }
}

The payload contains the message content and live delivery tracking:

{
  "type": "message",
  "message": { "text": "Hello from Outeract!", "role": "assistant" },
  "platform": "whatsapp",
  "external_message_id": "wamid.HBgL...",
  "delivery_status": {
    "sent_at": "2026-07-14T10:30:01.123+00:00",
    "delivered_at": "2026-07-14T10:30:02.456+00:00",
    "read_at": null,
    "failed_at": null
  }
}

As the platform reports delivery receipts, delivery_status is updated in place. Re-run the query to watch delivered_at and read_at fill in. The edges tell the rest of the story:

EdgePoints toMeaning
sent_byidentityThe system (bot) identity that sent it
sent_toidentityThe recipient’s platform identity
in_conversationeventThe conversation this message belongs to

See Message Handling for the full lifecycle and Events for the data model.

Step 4: See it in the console#

Open the console at outeract.com/console and select your application. The event stream shows your message.outbound event in real time. Click it to inspect the payload, edges, and delivery status. If the recipient replies, a message.inbound event appears in the same conversation.

The console is also the quickest place to spot problems: failed sends surface in the event’s delivery_status.error and in the application logs.

What next#

  • Webhook Setup - get notified the moment a reply arrives, instead of polling
  • Sending Messages - files, templates, platform selection, and error handling
  • Inbound Messages - consume incoming messages via webhooks or polling
  • Events - how the event ledger and edges work