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