> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inboxapp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Common issues and solutions for the Inbox API

## 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:**

```typescript theme={null}
// 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:**

```typescript theme={null}
// Wrong: Using platform ID
const threadPlatformId = '1566123362161725440:1876543210987654321';
await client.get(`/threads/${threadPlatformId}`);  // 404!

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

// Or use lookup with platform ID
const { data: thread } = await client.get('/threads/lookup', {
  params: {
    externalPlatformId: '1876543210987654321',
    accountLinkId: 'df6jbw4h36qm5d9iu2sgn7kx'
  }
});
```

***

### 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:**

```typescript theme={null}
// Verify prospect exists before operations
const { data: prospect } = await client.get('/prospects/lookup', {
  params: { platformId: '1876543210987654321' }
});

if (!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.');
}
```

<Note>
  Prospects are auto-created when they message you or when you create a thread with them. You cannot create prospects directly.
</Note>

***

### Account link not found

**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:**

```typescript theme={null}
// List your account links to get valid IDs
const { data: accountLinks } = await client.get('/account-links');
console.log('Valid account link IDs:');
accountLinks.forEach((a: any) => {
  console.log(`  @${a.username}: ${a.id}`);
});
```

***

## Rate limiting

### 429 Too many requests

**Symptom:** Requests start failing with 429 after sending many messages.

**Solutions:**

```typescript theme={null}
// 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](/reference/rate-limits) for detailed limits.

***

## Pagination issues

### Missing data

**Symptom:** Not all threads/messages are returned.

**Cause:** Not handling pagination properly.

**Solution:**

```typescript theme={null}
// Always paginate through all results
async function getAllThreads() {
  const threads: any[] = [];
  let cursorId: string | undefined;
  let cursorTimestamp: string | undefined;

  do {
    const { data } = await client.get('/threads', {
      params: {
        limit: 100,
        ...(cursorId && { cursorId, cursorTimestamp })
      }
    });

    threads.push(...data.threads);
    cursorId = data.nextCursor?.id;
    cursorTimestamp = data.nextCursor?.timestamp;
  } while (cursorId);

  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 parameter names

```typescript theme={null}
// Correct: use flat cursor parameters
const { data } = await client.get('/threads', {
  params: {
    cursorId: nextCursor.id,
    cursorTimestamp: 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:**

```typescript theme={null}
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:**

```typescript theme={null}
// Correct filter format (nested bracket notation)
const { data } = await client.get('/threads', {
  params: {
    'filters[tags][selectedIds][0]': 't8rvk2m5j0xn4wq7ybftcael',
    'filters[tags][selectedIds][1]': 'u9swl3n6k1yo5xr8zcgudbfm'
  }
});

// Wrong: using incorrect key structure
const { data } = await client.get('/threads', {
  params: {
    'filter[tagIds][0]': 't8rvk2m5j0xn4wq7ybftcael'  // Wrong key!
  }
});
```

See the [Query Parameters guide](/reference/query-parameters) 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:**

```typescript theme={null}
// Check all inbox views
const views = ['default', 'no-reply', 'requests', 'archived'];

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

***

## Quick diagnostic script

Run this to verify your setup:

```typescript theme={null}
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: accountLinks } = await client.get('/account-links');
  console.log(`   ✓ ${accountLinks.length} account(s) connected`);
  accountLinks.forEach((a: any) => {
    console.log(`     - @${a.username} (${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](/reference/error-codes)
2. **Review the API reference** for the specific endpoint
3. **Contact support** at [helpcenter.inboxapp.com](https://helpcenter.inboxapp.com)
4. **Email** [kevin@inboxapp.com](mailto: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)

## Related

<CardGroup cols={2}>
  <Card title="Error codes" icon="shield-x" href="/reference/error-codes">
    Complete error reference
  </Card>

  <Card title="Rate limits" icon="gauge" href="/reference/rate-limits">
    Rate limiting details
  </Card>

  <Card title="FAQ" icon="circle-question" href="/resources/faq">
    Common questions
  </Card>

  <Card title="Authentication" icon="key" href="/configuration/authentication">
    Auth setup guide
  </Card>
</CardGroup>
