Skip to main content
Learn how to use the Qwairy API with real-world examples, from simple queries to complete integrations.

Quick Start

Get your GEO Score in one command:
curl -s -H "Authorization: Bearer $QWAIRY_API_TOKEN" \
  "https://qwairy.co/api/v1/brands/YOUR_BRAND_ID/performance?period=30" \
  | jq '.scores'
Output:
{
  "global": 62,
  "mentionRate": 45.2,
  "sourceRate": 23.9,
  "shareOfVoice": 8.13,
  "sentiment": 78.1
}

API Client

Reusable client with error handling for all guides on this site.
// qwairy-client.js
class QwairyClient {
  constructor(apiToken) {
    this.baseUrl = 'https://qwairy.co/api/v1';
    this.headers = {
      'Authorization': `Bearer ${apiToken}`,
      'Content-Type': 'application/json',
    };
  }

  async request(endpoint, params = {}) {
    const url = new URL(`${this.baseUrl}${endpoint}`);
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        url.searchParams.append(key, value);
      }
    });

    const response = await fetch(url.toString(), { headers: this.headers });

    if (!response.ok) {
      const error = await response.json().catch(() => ({}));
      const code = error.error?.code || 'UNKNOWN_ERROR';
      const message = error.error?.message || `HTTP ${response.status}`;

      if (response.status === 429) {
        const resetTime = response.headers.get('X-RateLimit-Reset');
        throw new Error(`Rate limited. Retry after: ${resetTime}`);
      }

      throw new Error(`[${code}] ${message}`);
    }

    return response.json();
  }

  async getPerformance(brandId, params = {}) {
    return this.request(`/brands/${brandId}/performance`, params);
  }

  async getCompetitors(brandId, params = {}) {
    return this.request(`/brands/${brandId}/competitors`, params);
  }

  async getSources(brandId, params = {}) {
    return this.request(`/brands/${brandId}/sources`, params);
  }

  async getCompetitorEvolution(brandId, competitorId, params = {}) {
    return this.request(`/brands/${brandId}/competitors/${competitorId}/evolution`, params);
  }
}

// Usage
const client = new QwairyClient(process.env.QWAIRY_API_TOKEN);
All guides on this site use this client. Copy it to your project or adapt it to your needs.

TypeScript Types

Type definitions for the API client.
// qwairy-types.ts
interface QwairyScores {
  global: number;
  mentionRate: number;
  sourceRate: number;
  shareOfVoice: number;
  sentiment: number;
}

interface QwairyMethodology {
  promptsCount: number;
  responsesTotal: number;
  providers: string[];
}

interface QwairyPerformance {
  scores: QwairyScores;
  methodology: QwairyMethodology;
  byProvider?: Array<{ provider: string; scores: QwairyScores }>;
  byTopic?: Array<{ topic: string; scores: QwairyScores }>;
  byTag?: Array<{ tag: string; scores: QwairyScores }>;
}

interface QwairyCompetitor {
  id: string;
  name: string;
  relationship: 'SELF' | 'DIRECT' | 'INDIRECT';
  totalMentions: number;
  shareOfVoice: number;
  avgPosition: number;
  avgSentiment: number;
}

interface QwairySource {
  id: string;
  domain: string;
  type: 'INSTITUTIONAL' | 'COMMERCIAL' | 'MEDIA' | 'BLOG' | 'SOCIAL' | 'OTHER';
  isSelf: boolean;
  totalMentions: number;
  rate: number;
  avgPosition: number;
}

interface QwairyPagination {
  total: number;
  count: number;
  limit: number;
  offset: number;
}

interface QwairyCompetitorsResponse {
  success: boolean;
  pagination: QwairyPagination;
  competitors: QwairyCompetitor[];
}

interface QwairySourcesResponse {
  success: boolean;
  pagination: QwairyPagination;
  sources: QwairySource[];
}

Pagination

Fetch all results when you have more than 100 items.
async function fetchAllCompetitors(client, brandId, period = 30) {
  const allCompetitors = [];
  let offset = 0;
  const limit = 100;

  while (true) {
    const response = await client.getCompetitors(brandId, { period, limit, offset });
    allCompetitors.push(...response.competitors);

    if (response.competitors.length < limit || allCompetitors.length >= response.pagination.total) {
      break;
    }
    offset += limit;
  }

  return allCompetitors;
}

// Usage
const allCompetitors = await fetchAllCompetitors(client, 'your-brand-id', 30);
console.log(`Total competitors: ${allCompetitors.length}`);

Field Reference

Mapping between business metrics and API fields:
Business MetricEndpointFieldDescription
GEO Score/performancescores.globalOverall optimization score (0-100)
Brand Visibility/performancescores.mentionRate% of responses mentioning your brand
Citation Rate/performancescores.sourceRate% of responses citing your content
Share of Voice/competitorsshareOfVoiceYour % of all competitor mentions
Share of Citations/sourcesrateSource’s % of all citations
Sentiment/performancescores.sentimentAverage sentiment score (0-100)
Average Position/competitorsavgPositionAverage rank in AI responses (1 = first)
Use /performance for aggregated KPIs. Use /competitors and /sources for detailed breakdowns.