Skip to main content

Error Response Format

All Thrust API errors follow a consistent format:
{
  "success": false,
  "error": "Descriptive error message"
}

HTTP Status Codes

The API uses standard HTTP status codes to indicate success or failure:
Status CodeMeaningDescription
200OKRequest successful
400Bad RequestInvalid parameters or missing required fields
401UnauthorizedAuthentication required or token invalid
403ForbiddenInsufficient permissions
404Not FoundResource doesn’t exist
405Method Not AllowedWrong HTTP method (all endpoints use POST)
500Internal Server ErrorServer-side error

Common Error Messages

Authentication Errors

Missing Authorization Header

{
  "error": "Missing authorization header"
}
Solution: Include the Authorization: Bearer {token} header in your request.
const response = await fetch(endpoint, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`, // ✅ Don't forget this!
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});

Invalid or Expired Token

{
  "error": "Invalid or expired authentication token"
}
Solution: Refresh your JWT token or re-authenticate.
const handleExpiredToken = async () => {
  try {
    // Try the API call
    const response = await apiCall();
    return response;
  } catch (error) {
    if (error.message.includes('expired')) {
      // Refresh token and retry
      await refreshAuthToken();
      return await apiCall();
    }
    throw error;
  }
};

No User ID in Token

{
  "error": "No user ID in token"
}
Solution: The JWT token is malformed. Obtain a new token from Ory.

Validation Errors

Missing Required Fields

{
  "error": "Missing required fields: tokenId, chainSlug"
}
Solution: Include all required fields in your request body.
// ❌ Bad
{
  "chainSlug": "base"
}

// ✅ Good
{
  "tokenId": "550e8400-e29b-41d4-a716-446655440000",
  "chainSlug": "base"
}

Invalid Parameters

{
  "error": "Invalid filter value. Must be one of: trending, new, popular, top_posts"
}
Solution: Use only allowed values for enum fields.

Resource Errors

Token Not Found

{
  "error": "Token not found"
}
Solution: Verify the tokenId exists and is correct.
// Check if token exists before making requests
const checkToken = async (tokenId) => {
  const response = await fetch(`${API_URL}/tag-coin`, {
    method: 'POST',
    headers: { /* ... */ },
    body: JSON.stringify({ slug: tokenId })
  });

  if (!response.ok) {
    throw new Error('Token not found');
  }

  return response.json();
};

Token Not Available on Chain

{
  "error": "Token not available on chain base-sepolia"
}
Solution: Use a supported chain for the token. Check token_addresses to see available chains.

Trading Errors

Insufficient Liquidity

{
  "error": "UniswapV3 quote failed for all fee tiers. Pool may not exist or have insufficient liquidity"
}
Solution: The token may have graduated but not have sufficient Uniswap V3 liquidity yet. Try a smaller amount or wait for more liquidity.

Insufficient Balance

{
  "error": "Insufficient token balance"
}
Solution: User doesn’t have enough tokens to complete the transaction.
// Check balance before attempting trade
const balance = await getUserBalance(userId, tokenId);
if (balance < amount) {
  throw new Error('Insufficient balance');
}

Permission Errors

Access Denied to Club

{
  "error": "Access denied: You don't have permission to view this club"
}
Solution: User needs to hold the required token or meet visibility rules to access the club.

Method Errors

Wrong HTTP Method

{
  "error": "Method not allowed"
}
Solution: All Thrust API endpoints use POST requests, not GET.
// ❌ Bad
fetch(endpoint, { method: 'GET' })

// ✅ Good
fetch(endpoint, { method: 'POST', body: JSON.stringify(data) })

Error Handling Best Practices

1. Always Check Response Status

const apiCall = async (endpoint, data) => {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  });

  const result = await response.json();

  if (!response.ok) {
    throw new Error(result.error || `HTTP ${response.status}`);
  }

  return result;
};

2. Implement Retry Logic

const apiCallWithRetry = async (endpoint, data, maxRetries = 3) => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await apiCall(endpoint, data);
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      // Exponential backoff
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
};

3. Handle Specific Error Types

const handleApiError = (error) => {
  if (error.message.includes('expired')) {
    // Refresh token
    return refreshAndRetry();
  } else if (error.message.includes('not found')) {
    // Show 404 UI
    showNotFoundMessage();
  } else if (error.message.includes('Insufficient')) {
    // Show balance error
    showInsufficientBalanceError();
  } else {
    // Generic error handling
    showGenericError(error.message);
  }
};

4. Use Try-Catch Blocks

const safeFetchTokens = async () => {
  try {
    const tokens = await fetchTokens();
    return { success: true, data: tokens };
  } catch (error) {
    console.error('Failed to fetch tokens:', error);
    return { success: false, error: error.message };
  }
};

5. Validate Before API Calls

const createPost = async (postData) => {
  // Client-side validation
  if (!postData.title || !postData.content) {
    throw new Error('Title and content are required');
  }

  if (postData.title.length > 200) {
    throw new Error('Title too long (max 200 characters)');
  }

  // Make API call
  return await apiCall('/create-post', postData);
};

Debugging Tips

Enable Detailed Logging

const DEBUG = true;

const apiCall = async (endpoint, data) => {
  if (DEBUG) {
    console.log('API Request:', { endpoint, data });
  }

  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: { /* ... */ },
      body: JSON.stringify(data)
    });

    const result = await response.json();

    if (DEBUG) {
      console.log('API Response:', { status: response.status, result });
    }

    return result;
  } catch (error) {
    if (DEBUG) {
      console.error('API Error:', error);
    }
    throw error;
  }
};

Check Request Headers

// Verify your auth token is correctly formatted
const token = localStorage.getItem('jwt_token');
console.log('Token:', token.substring(0, 20) + '...');

// Check if token is expired
const parseJwt = (token) => {
  const base64Url = token.split('.')[1];
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  const jsonPayload = decodeURIComponent(
    atob(base64).split('').map(c => {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join('')
  );

  return JSON.parse(jsonPayload);
};

const payload = parseJwt(token);
console.log('Token expires:', new Date(payload.exp * 1000));

Test with cURL

When debugging, use cURL to isolate issues:
curl -v -X POST "https://yppncslmsswqydhhgygz.supabase.co/functions/v1/get-tokens" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": "trending",
    "limit": 1
  }'
The -v flag shows verbose output including headers and response codes.

Rate Limiting

While not explicitly documented, consider implementing rate limiting on your end:
class RateLimiter {
  constructor(maxRequests = 100, windowMs = 60000) {
    this.maxRequests = maxRequests;
    this.windowMs = windowMs;
    this.requests = [];
  }

  async checkLimit() {
    const now = Date.now();
    this.requests = this.requests.filter(time => now - time < this.windowMs);

    if (this.requests.length >= this.maxRequests) {
      throw new Error('Rate limit exceeded');
    }

    this.requests.push(now);
  }
}

const limiter = new RateLimiter();

const apiCall = async (endpoint, data) => {
  await limiter.checkLimit();
  // Make API call...
};

Getting Help

If you encounter errors not covered here:
  1. Check the API Reference for endpoint-specific documentation
  2. Search or ask in our Discord community
  3. Email support@thrust.app with:
    • The endpoint you’re calling
    • Your request payload (remove sensitive data)
    • The error response
    • Your API client/SDK version

API Reference

View detailed documentation for all endpoints