Skip to main content

Authentication Issues

401 Unauthorized

Symptom: All requests return 401 status. Common causes:
  1. Missing Authorization header
  2. Typo in token (extra spaces, newlines)
  3. Expired or revoked token
  4. Missing Bearer prefix
Solutions:
// Check your header format
const headers = {
  'Authorization': `Bearer ${process.env.INBOX_API_TOKEN}`,  // Note the space after Bearer
  'Content-Type': 'application/json'
};

// Verify token is loaded
if (!process.env.INBOX_API_TOKEN) {
  throw new Error('INBOX_API_TOKEN environment variable not set');
}

// Test with a simple request
const response = await fetch('https://inboxapp.com/api/v1/team', { headers });
console.log('Status:', response.status);
Verification steps:
  1. Print your token (first/last 4 chars only) to verify it’s loaded
  2. Try the token in cURL to isolate the issue
  3. Generate a new token from the dashboard

403 Forbidden

Symptom: Token works for some endpoints but not others. Common causes:
  1. Accessing a resource from another team
  2. Feature not available on your plan
  3. Attempting an admin-only action
Solutions:
  1. Verify the resource belongs to your team
  2. Check your plan in the dashboard
  3. Use a token from an admin account

Resource Not Found (404)

Thread Not Found

Symptom: THREAD_NOT_FOUND error when accessing a thread. Common causes:
  1. Using platform ID instead of Inbox ID
  2. Thread was deleted
  3. Typo in thread ID
Solution:
// Wrong: Using platform ID
const threadPlatformId = '12345-67890';
await client.get(`/threads/${threadPlatformId}`);  // 404!

// Correct: Use Inbox ID
const threadInboxId = 'thread_abc123';
await client.get(`/threads/${threadInboxId}`);  // Works

// Or use lookup with platform ID
const { data } = await client.get('/threads/lookup', {
  params: {
    prospectPlatformId: '987654321',
    accountLinkId: 'acc_abc123'
  }
});

Prospect Not Found

Symptom: PROSPECT_NOT_FOUND when sending a message or looking up. Common causes:
  1. Prospect has never interacted with your team
  2. Wrong platform ID format
  3. Prospect was deleted
Solutions:
// Verify prospect exists before operations
const { data } = await client.get('/prospects/lookup', {
  params: { platformId: '987654321' }
});

if (!data.prospect) {
  console.log('Prospect not in system. They need to message you first,');
  console.log('or you need to start a conversation via /threads endpoint.');
}
Prospects are auto-created when they message you or when you create a thread with them. You cannot create prospects directly.

Symptom: ACCOUNT_LINK_NOT_FOUND when sending messages. Common causes:
  1. Using platform ID instead of Inbox ID
  2. Account was disconnected
  3. Typo in account link ID
Solution:
// List your account links to get valid IDs
const { data } = await client.get('/account-links');
console.log('Valid account link IDs:');
data.accountLinks.forEach((a: any) => {
  console.log(`  ${a.platformUsername}: ${a.id}`);
});

Rate Limiting

429 Too Many Requests

Symptom: Requests start failing with 429 after sending many messages. Solutions:
// Implement retry with backoff
async function sendWithRetry(threadId: string, text: string) {
  let retries = 0;
  const maxRetries = 5;

  while (retries < maxRetries) {
    try {
      return await client.post(`/threads/${threadId}/messages`, { text });
    } catch (error) {
      if (axios.isAxiosError(error) && error.response?.status === 429) {
        const retryAfter = parseInt(
          error.response.headers['retry-after'] || '60',
          10
        );
        console.log(`Rate limited. Waiting ${retryAfter}s...`);
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        retries++;
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}

// Add delays between bulk operations
for (const message of messages) {
  await sendMessage(message);
  await new Promise(r => setTimeout(r, 6000));  // 6 seconds between sends
}
See the Rate Limits guide for detailed limits.

Pagination Issues

Missing Data

Symptom: Not all threads/messages are returned. Cause: Not handling pagination properly. Solution:
// Always paginate through all results
async function getAllThreads() {
  const threads = [];
  let cursor = undefined;

  do {
    const { data } = await client.get('/threads', {
      params: {
        limit: 100,
        ...(cursor && {
          'cursor[id]': cursor.id,
          'cursor[timestamp]': cursor.timestamp
        })
      }
    });

    threads.push(...data.threads);
    cursor = data.nextCursor;
  } while (cursor);

  return threads;
}

Invalid Cursor

Symptom: INVALID_CURSOR error when paginating. Common causes:
  1. Cursor was modified
  2. Cursor from a different query
  3. Cursor format is wrong
Solutions:
  1. Use cursors exactly as returned (don’t modify)
  2. Start fresh if cursor errors persist
  3. Check cursor encoding in URLs
// Correct cursor encoding
const { data } = await client.get('/threads', {
  params: {
    'cursor[id]': nextCursor.id,
    'cursor[timestamp]': nextCursor.timestamp
  }
});

Message Sending Issues

Message Not Delivered

Symptom: API returns success but message doesn’t appear on X. Possible causes:
  1. Platform-level restrictions on your X account
  2. Recipient has blocked you
  3. Temporary platform issues
Diagnostic steps:
  1. Check the thread in the Inbox dashboard
  2. Verify the message appears there
  3. Try sending from the X app directly
  4. Contact support if the issue persists

Empty Message Error

Symptom: VALIDATION_ERROR when sending a message. Solution:
function validateMessage(text: string) {
  if (!text?.trim()) {
    throw new Error('Message cannot be empty');
  }
  if (text.length > 10000) {
    throw new Error('Message exceeds 10,000 character limit');
  }
}

// Always validate before sending
validateMessage(messageText);
await client.post(`/threads/${threadId}/messages`, { text: messageText });

Filter Issues

Filters Not Working

Symptom: Filters return unexpected results. Common causes:
  1. Wrong parameter format
  2. Incorrect filter combination
Solutions:
// Correct filter format (bracket notation)
const { data } = await client.get('/threads', {
  params: {
    'filter[tagIds][0]': 'tag_abc',
    'filter[tagIds][1]': 'tag_xyz'
  }
});

// Wrong: passing array directly
const { data } = await client.get('/threads', {
  params: {
    'filter[tagIds]': ['tag_abc', 'tag_xyz']  // Won't work!
  }
});
See the Query Parameters guide for encoding rules.

Data Sync Issues

Stale Prospect Data

Symptom: Prospect profile data (followers, bio) seems outdated. Explanation: Prospect profile data is synced periodically from the platform, not in real-time. Solutions:
  1. Profile data updates on each interaction
  2. For critical decisions, fetch directly from X API
  3. Don’t rely on real-time accuracy for follower counts

Missing Threads

Symptom: Conversations visible in Inbox UI don’t appear in API. Possible causes:
  1. Pagination not complete
  2. Filtering out results
  3. Different inbox views
Diagnostic steps:
// Check all inbox views
const views = ['default', 'no-reply', 'requests', 'archived'];

for (const view of views) {
  const { data } = await client.get('/threads', {
    params: { inboxView: view, limit: 1 }
  });
  console.log(`${view}: ${data.threads.length} threads`);
}

Quick Diagnostic Script

Run this to verify your setup:
async function diagnose() {
  console.log('=== Inbox API Diagnostic ===\n');

  // 1. Check authentication
  console.log('1. Testing authentication...');
  try {
    const { data: team } = await client.get('/team');
    console.log(`   ✓ Connected to team: ${team.name}`);
  } catch (error) {
    console.log(`   ✗ Auth failed: ${error.message}`);
    return;
  }

  // 2. Check account links
  console.log('\n2. Checking account links...');
  const { data: accounts } = await client.get('/account-links');
  console.log(`   ✓ ${accounts.accountLinks.length} account(s) connected`);
  accounts.accountLinks.forEach((a: any) => {
    console.log(`     - @${a.platformUsername} (${a.id})`);
  });

  // 3. Check threads
  console.log('\n3. Checking threads...');
  const { data: threads } = await client.get('/threads', {
    params: { limit: 5 }
  });
  console.log(`   ✓ ${threads.threads.length} recent threads`);

  // 4. Check rate limit status
  console.log('\n4. Rate limit status...');
  // Make a request and check headers
  const response = await client.get('/team');
  const remaining = response.headers['x-ratelimit-remaining'];
  const limit = response.headers['x-ratelimit-limit'];
  console.log(`   ✓ ${remaining}/${limit} requests remaining`);

  console.log('\n=== Diagnostic Complete ===');
}

diagnose().catch(console.error);

Getting Help

If you’re still stuck:
  1. Check the error code in the Error Codes reference
  2. Review the API reference for the specific endpoint
  3. Contact support at helpcenter.inboxapp.com
  4. Email kevin@inboxapp.com for urgent issues
When contacting support, include:
  • Error message and code
  • Request endpoint and parameters
  • Timestamp of the issue
  • Your team ID (from /team response)