Skip to main content
Glama
check-saola-account.cjs8.58 kB
#!/usr/bin/env node const https = require('https'); const axios = require('axios'); const axiosInstance = axios.create({ httpsAgent: new https.Agent({ rejectUnauthorized: false }), timeout: 60000 // 60 second timeout }); async function checkSaolaAccount() { console.log('\n' + '═'.repeat(70)); console.log(' 🌟 SAOLA ACCOUNT DETAILED CHECK'); console.log('═'.repeat(70)); const baseUrl = 'https://api.umbrellacost.io/api/v1'; try { // Step 1: Authenticate console.log('\n1️⃣ AUTHENTICATION'); console.log('────────────────────────────'); console.log('Username: david+saola@umbrellacost.com'); console.log('Password: Dsamsung1!'); const authResponse = await axiosInstance.post(`${baseUrl}/users/signin`, { username: 'david+saola@umbrellacost.com', password: 'Dsamsung1!' }); if (!authResponse.data || !authResponse.data.jwtToken) { throw new Error('No JWT token received'); } const token = authResponse.data.jwtToken; console.log('✅ Authentication successful'); // Parse JWT const tokenPayload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); const userKey = tokenPayload.username || tokenPayload['custom:username'] || tokenPayload.sub; console.log(`User Key: ${userKey}`); // Step 2: Get user info and accounts console.log('\n2️⃣ FETCHING USER ACCOUNTS'); console.log('────────────────────────────'); let accounts = []; let accountKey = '9350'; // Default SAOLA account try { const userResponse = await axiosInstance.get(`${baseUrl}/users`, { headers: { 'Authorization': token, 'Content-Type': 'application/json' }, timeout: 10000 }); if (userResponse.data && userResponse.data.accounts) { accounts = userResponse.data.accounts; console.log(`✅ Found ${accounts.length} account(s)`); // Show all accounts accounts.forEach((acc, i) => { console.log(` ${i+1}. ${acc.accountName || 'Unnamed'} (Key: ${acc.accountKey}, Type: ${acc.cloudType || 'N/A'})`); }); // Find SAOLA account const saolaAccount = accounts.find(acc => acc.accountKey === '9350' || acc.accountKey === 9350 || (acc.accountName && acc.accountName.toLowerCase().includes('saola')) ); if (saolaAccount) { accountKey = saolaAccount.accountKey; console.log(`\n✅ Using SAOLA account: ${saolaAccount.accountName} (Key: ${accountKey})`); } else { console.log(`\n⚠️ SAOLA account not found, using default key: ${accountKey}`); } } } catch (userErr) { console.log('⚠️ Could not fetch user accounts (timeout/error), using default'); console.log(` Error: ${userErr.message}`); } // Step 3: Build API key and query costs const apiKey = `${userKey}:${accountKey}:0`; console.log(`\nAPI Key: ${apiKey}`); console.log('\n3️⃣ QUERYING SAOLA COSTS (March-July 2025)'); console.log('────────────────────────────────────────────'); // Try different query approaches const queries = [ { name: 'With groupBy=usagedate', params: { startDate: '2025-03-01', endDate: '2025-07-31', periodGranLevel: 'month', groupBy: 'usagedate', costType: 'cost' } }, { name: 'With groupBy=none', params: { startDate: '2025-03-01', endDate: '2025-07-31', periodGranLevel: 'month', groupBy: 'none', costType: 'cost' } } ]; for (const query of queries) { console.log(`\n📊 ${query.name}:`); try { const params = new URLSearchParams(query.params); const response = await axiosInstance.get(`${baseUrl}/invoices/caui?${params}`, { headers: { 'Authorization': token, 'apikey': apiKey, 'Content-Type': 'application/json' }, timeout: 30000 }); if (response.data && response.data.length > 0) { console.log(`✅ Got ${response.data.length} result(s)`); // Show data if (query.params.groupBy === 'usagedate') { // Monthly breakdown const expected = { '2025-03': 104755.07, '2025-04': 111340.42, '2025-05': 149774.24, '2025-06': 165666.57, '2025-07': 183920.58 }; console.log('\n Month Actual Expected Match'); console.log(' ─────────────────────────────────────────────────'); response.data.forEach(item => { const month = item.usage_date; const monthName = { '2025-03': 'March 2025', '2025-04': 'April 2025', '2025-05': 'May 2025', '2025-06': 'June 2025', '2025-07': 'July 2025' }[month]; if (monthName && expected[month]) { const actual = item.total_cost; const exp = expected[month]; const match = Math.abs(actual - exp) < 1; console.log(` ${monthName.padEnd(12)} $${actual.toFixed(2).padEnd(13)} $${exp.toFixed(2).padEnd(12)} ${match ? '✅' : '❌'}`); } }); console.log(`\n Account ID: ${response.data[0].account_id}`); console.log(` Expected: 932213950603`); console.log(` Match: ${response.data[0].account_id === '932213950603' ? '✅' : '❌'}`); } else { // Total const total = response.data[0].total_cost; const expectedTotal = 715456.88; console.log(` Total Cost: $${total.toFixed(2)}`); console.log(` Expected: $${expectedTotal.toFixed(2)}`); console.log(` Account ID: ${response.data[0].account_id}`); } } else { console.log('❌ No data returned'); } } catch (queryErr) { console.log(`❌ Query failed: ${queryErr.message}`); } } console.log('\n' + '═'.repeat(70)); console.log(' TEST COMPLETE'); console.log('═'.repeat(70)); } catch (error) { console.error('\n❌ Fatal Error:', error.message); if (error.response) { console.error('Response status:', error.response.status); console.error('Response data:', error.response.data); } } } checkSaolaAccount().catch(console.error);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/daviddraiumbrella/invoice-monitoring'

If you have feedback or need assistance with the MCP directory API, please join our Discord server