Skip to main content

Send your first message

This tutorial walks you through sending your first DM using the Inbox API. You’ll learn the core workflow: authenticate, find an account, locate or create a thread, and send a message.
Before starting, make sure you have an API token. See the Authentication guide to get one.

Prerequisites

npm install axios
Set your API token as an environment variable:
export INBOX_API_TOKEN="your_token_here"

Step 1: Verify authentication

Confirm your API token works by fetching your team information:
import axios from "axios";

const client = axios.create({
  baseURL: "https://inboxapp.com/api/v1",
  headers: {
    Authorization: `Bearer ${process.env.INBOX_API_TOKEN}`,
    "Content-Type": "application/json",
  },
});

const { data: team } = await client.get("/team");
console.log("Connected to team:", team.name);
Response:
{
  "id": "hzcai5t59nn9vsck3rbuepyg",
  "name": "Acme Corp",
  "slug": "acme-corp",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": null,
  "currency": "USD",
  "allowSupportAccess": false
}
Account links are X accounts connected to your team. You need one to send messages:
const { data: accountLinks } = await client.get("/account-links");
console.log(`Found ${accountLinks.length} account(s)`);

const account = accountLinks[0];
console.log(`Using account: @${account.username}`);
Response:
[
  {
    "id": "df6jbw4h36qm5d9iu2sgn7kx",
    "platform": "twitter",
    "platformId": "1566123362161725440",
    "name": "Acme Corp",
    "username": "acmecorp",
    "image": "https://pbs.twimg.com/profile_images/...",
    "createdAt": "2024-06-01T12:00:00.000Z",
    "status": "active",
    "syncedAt": "2025-01-15T10:30:00.000Z"
  }
]

Step 3: Find or create a thread

Option A: Lookup an existing thread

If you know the prospect’s X user ID:
const { data: thread } = await client.get("/threads/lookup", {
  params: {
    externalPlatformId: "1876543210987654321",
    accountLinkId: account.id,
  },
});

if (thread) {
  console.log("Found existing thread:", thread.id);
} else {
  console.log("No thread exists yet");
}

Option B: Create a new thread

const { data: thread } = await client.post("/threads", {
  externalPlatformId: "1876543210987654321",
  accountLinkId: account.id,
});

console.log("Created thread:", thread.id);
Creating a thread doesn’t send a message. Use the messages endpoint to send a DM.

Step 4: Send a message

Replying to contacts who have already messaged you works on all plans. Sending the first message to a new contact requires the Outbound Messages addon on a paid plan. See Working with messages for details.
const { data: message } = await client.post(`/threads/${thread.id}/messages`, {
  content: "Hello! Thanks for reaching out.",
});

console.log("Message sent:", message.id);
Response:
{
  "id": "p8rvk2m5j0xn4wq7ybftcael",
  "platform": "twitter",
  "platformId": "1876543210987654322",
  "threadId": "l44e15irdq4db30i77cgphhx",
  "teamId": "hzcai5t59nn9vsck3rbuepyg",
  "authorId": "df6jbw4h36qm5d9iu2sgn7kx",
  "userId": "r3km7xj9wq5p2bvnhfdteoly",
  "campaignId": null,
  "content": "Hello! Thanks for reaching out.",
  "origin": "api",
  "createdAt": "2025-01-15T10:30:00.000Z",
  "updatedAt": null,
  "isEdited": false,
  "entities": null,
  "attachment": null,
  "reactions": [],
  "replyData": null,
  "forwardData": null
}

Complete example

import axios from "axios";

const client = axios.create({
  baseURL: "https://inboxapp.com/api/v1",
  headers: {
    Authorization: `Bearer ${process.env.INBOX_API_TOKEN}`,
    "Content-Type": "application/json",
  },
});

async function sendFirstMessage(
  prospectPlatformId: string,
  messageContent: string,
) {
  // 1. Verify authentication
  const { data: team } = await client.get("/team");
  console.log("Connected to:", team.name);

  // 2. Get account link
  const { data: accountLinks } = await client.get("/account-links");
  const account = accountLinks[0];
  console.log(`Using account: @${account.username}`);

  // 3. Lookup or create thread
  let thread;

  const { data: existing } = await client.get("/threads/lookup", {
    params: {
      externalPlatformId: prospectPlatformId,
      accountLinkId: account.id,
    },
  });

  if (existing) {
    thread = existing;
    console.log("Found existing thread");
  } else {
    const { data: created } = await client.post("/threads", {
      externalPlatformId: prospectPlatformId,
      accountLinkId: account.id,
    });
    thread = created;
    console.log("Created new thread");
  }

  // 4. Send message
  const { data: message } = await client.post(
    `/threads/${thread.id}/messages`,
    { content: messageContent },
  );

  console.log("Message sent:", message.id);
  return message;
}

sendFirstMessage("1876543210987654321", "Hello from the API!").catch((error) =>
  console.error("Error:", error.response?.data ?? error.message),
);

Quick send alternative

For one-off messages, quick send combines thread lookup/creation and sending in one request:
const { data } = await client.post("/threads/messages", {
  externalPlatformId: "1876543210987654321",
  accountLinkId: account.id,
  content: "Hey, I saw your post and wanted to reach out!",
});

console.log("Message sent:", data.message.id);
console.log("Thread:", data.thread.id);
Response:
{
  "message": {
    "id": "p8rvk2m5j0xn4wq7ybftcael",
    "platform": "twitter",
    "threadId": "l44e15irdq4db30i77cgphhx",
    "content": "Hey, I saw your post and wanted to reach out!",
    "origin": "api",
    "createdAt": "2025-01-15T10:30:00.000Z"
  },
  "thread": {
    "id": "l44e15irdq4db30i77cgphhx",
    "platform": "twitter",
    "platformId": "1566123362161725440:1876543210987654321"
  }
}
Use quick send for simple scenarios. For more control over thread management, use the standard create/lookup + send workflow.

Next steps

Core concepts

Understand threads, prospects, and the data model

Managing threads

Learn thread operations and filtering

Working with prospects

Manage prospect data and context

Rate limits

Understand API limits