Skip to main content

Integration Guide

Learn how to integrate VendorTruth's verification engine into your application.

Quick Start

1. Get API Key

Sign up at portal.vendortruth.org and generate an API key from your dashboard.

2. Make Your First Request

curl -X POST https://api.vendortruth.org/v1/reports \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vendor": "aws",
    "claim": "zero vendor lock-in",
    "depth": "comprehensive"
  }'

3. Poll for Results

curl https://api.vendortruth.org/v1/reports/job_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"

Integration Patterns

Synchronous Verification

For simple integrations, use the synchronous endpoint:

const response = await fetch('https://api.vendortruth.org/v1/verify', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    vendor: 'mongodb',
    claim: 'elastic scalability',
  }),
});

const result = await response.json();
console.log(result.verdict); // 'partially-true', 'true', 'false', 'misleading'

Asynchronous Verification (Recommended)

For comprehensive reports, use the async pattern:

// 1. Initiate verification
const job = await fetch('https://api.vendortruth.org/v1/reports', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    vendor: 'vercel',
    claim: 'zero vendor lock-in',
    depth: 'comprehensive',
  }),
}).then((r) => r.json());

// 2. Poll for completion
const checkStatus = async (jobId) => {
  const status = await fetch(`https://api.vendortruth.org/v1/reports/${jobId}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  }).then((r) => r.json());

  if (status.state === 'completed') {
    return status.report;
  } else if (status.state === 'failed') {
    throw new Error(status.error);
  } else {
    // Still processing, check again in 5 seconds
    await new Promise((resolve) => setTimeout(resolve, 5000));
    return checkStatus(jobId);
  }
};

const report = await checkStatus(job.id);

Webhook Notifications

Receive notifications when reports complete:

// 1. Register webhook endpoint
await fetch('https://api.vendortruth.org/v1/webhooks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://yourapp.com/webhooks/vendortruth',
    events: ['report.completed', 'report.failed'],
  }),
});

// 2. Handle webhook in your app
app.post('/webhooks/vendortruth', (req, res) => {
  const { event, data } = req.body;

  if (event === 'report.completed') {
    console.log('Report ready:', data.report_id);
    // Process the completed report
  }

  res.status(200).send('OK');
});

Monitoring Alerts Integration

Subscribe to vendor change notifications:

// Create alert for pricing changes
await fetch('https://api.vendortruth.org/v1/alerts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    vendor: 'aws',
    types: ['pricing-change', 'security-issue'],
    notification_url: 'https://yourapp.com/webhooks/alerts',
  }),
});

Rate Limits

API requests are rate-limited by plan tier:

PlanRequests/minRequests/dayConcurrent Reports
Free101,0001
Pro10050,0005
EnterpriseCustomCustomUnlimited

Rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1699564800

Error Handling

Handle common error scenarios:

try {
  const response = await fetch('https://api.vendortruth.org/v1/reports', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ vendor: 'aws', claim: 'zero lock-in' }),
  });

  if (!response.ok) {
    const error = await response.json();

    switch (response.status) {
      case 401:
        throw new Error('Invalid API key');
      case 429:
        throw new Error(`Rate limited. Retry after ${error.retry_after} seconds`);
      case 422:
        throw new Error(`Validation error: ${error.message}`);
      default:
        throw new Error(`API error: ${error.message}`);
    }
  }

  const result = await response.json();
} catch (err) {
  console.error('Verification failed:', err.message);
}

Best Practices

Cache Results

Cache verification results to avoid redundant API calls:

const cache = new Map();

async function verifyVendor(vendor, claim) {
  const cacheKey = `${vendor}:${claim}`;

  if (cache.has(cacheKey)) {
    return cache.get(cacheKey);
  }

  const result = await callVendorTruthAPI(vendor, claim);
  cache.set(cacheKey, result);

  return result;
}

Handle Timeouts

Set reasonable timeouts for long-running verifications:

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 60000); // 60s timeout

try {
  const response = await fetch('https://api.vendortruth.org/v1/verify', {
    method: 'POST',
    signal: controller.signal,
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: JSON.stringify({ vendor: 'aws', claim: 'zero lock-in' }),
  });
} catch (err) {
  if (err.name === 'AbortError') {
    console.log('Request timed out, falling back to async pattern');
  }
} finally {
  clearTimeout(timeoutId);
}

Batch Requests

Verify multiple claims efficiently:

const claims = [
  { vendor: 'aws', claim: 'zero lock-in' },
  { vendor: 'vercel', claim: 'zero vendor lock-in' },
  { vendor: 'mongodb', claim: 'elastic scalability' },
];

const jobs = await Promise.all(
  claims.map(({ vendor, claim }) =>
    fetch('https://api.vendortruth.org/v1/reports', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ vendor, claim }),
    }).then((r) => r.json()),
  ),
);

Security

Protect Your API Key

Never expose your API key in client-side code:

// ❌ BAD - Exposed in browser
const report = await fetch('https://api.vendortruth.org/v1/verify', {
  headers: { Authorization: `Bearer vt_live_abc123...` }, // Visible in DevTools!
});

// ✅ GOOD - Proxy through your backend
const report = await fetch('/api/verify-vendor', {
  method: 'POST',
  body: JSON.stringify({ vendor: 'aws', claim: 'zero lock-in' }),
});

Verify Webhook Signatures

Validate webhook authenticity:

const crypto = require('crypto');

app.post('/webhooks/vendortruth', (req, res) => {
  const signature = req.headers['x-vendortruth-signature'];
  const payload = JSON.stringify(req.body);

  const expectedSignature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');

  if (signature !== expectedSignature) {
    return res.status(401).send('Invalid signature');
  }

  // Process webhook...
  res.status(200).send('OK');
});

Next Steps