FixFX

API References

Contributors

Access GitHub contributors and repository statistics.

The Contributors API provides access to GitHub contributor information and repository statistics for our organization. This API helps showcase community involvement and track project contributions.

Overview

The Contributors API aggregates data from GitHub to provide insights into:

  • Organization-wide contributor statistics
  • Individual repository contributors
  • Contribution metrics and activity
  • Repository health and engagement

This API is particularly useful for:

  • Displaying contributor acknowledgments
  • Building community dashboards
  • Tracking project activity
  • Generating contribution reports

Base URL

https://fixfx.wiki/api/contributors

Authentication

The Contributors API is public and doesn't require authentication. Data is refreshed periodically from GitHub.

Endpoints

GET /api/contributors

Retrieves contributor information across the ByteBrushStudios organization.

Query Parameters

ParameterTypeDescriptionDefault
repostringFilter by specific repository nameAll repositories
limitnumberMaximum number of contributors (max 100)50
sortstringSort by (contributions, name, recent)contributions
orderstringSort order (asc or desc)desc
minContributionsnumberMinimum contribution count1
sincestringInclude only contributions since date (ISO format)No limit
includeStatsbooleanInclude detailed statisticsfalse

Response Format

{
  "data": [
    {
      "login": "string",
      "id": number,
      "avatar_url": "string",
      "html_url": "string",
      "contributions": number,
      "repositories": ["string"],
      "first_contribution": "string",
      "last_contribution": "string",
      "contribution_types": {
        "commits": number,
        "issues": number,
        "pull_requests": number,
        "reviews": number
      }
    }
  ],
  "metadata": {
    "total_contributors": number,
    "total_contributions": number,
    "repositories": ["string"],
    "organization": "ByteBrushStudios",
    "last_updated": "string",
    "stats": {
      "active_contributors": number,
      "new_contributors": number,
      "top_repositories": [
        {
          "name": "string",
          "contributors": number,
          "contributions": number
        }
      ]
    }
  }
}

Example Usage

// Get top contributors
const response = await fetch(
  'https://fixfx.wiki/api/contributors?limit=10&includeStats=true'
);
const data = await response.json();
 
// Display contributors
console.log(`Total Contributors: ${data.metadata.total_contributors}`);
console.log(`Total Contributions: ${data.metadata.total_contributions}`);
 
data.data.forEach((contributor, index) => {
  console.log(`${index + 1}. ${contributor.login}`);
  console.log(`   Contributions: ${contributor.contributions}`);
  console.log(`   Repositories: ${contributor.repositories.length}`);
  console.log(`   GitHub: ${contributor.html_url}`);
  
  if (contributor.contribution_types) {
    console.log(`   Commits: ${contributor.contribution_types.commits}`);
    console.log(`   Issues: ${contributor.contribution_types.issues}`);
    console.log(`   Pull Requests: ${contributor.contribution_types.pull_requests}`);
  }
});
 
// Show repository stats
console.log('\nTop Repositories:');
data.metadata.stats.top_repositories.forEach(repo => {
  console.log(`- ${repo.name}: ${repo.contributors} contributors, ${repo.contributions} contributions`);
});

Use Cases

Community Dashboard

// Build a community contributors widget
async function buildContributorsWidget() {
  const response = await fetch(
    'https://fixfx.wiki/api/contributors?limit=20&includeStats=true&sort=contributions'
  );
  const data = await response.json();
  
  // Create widget HTML
  const widget = document.createElement('div');
  widget.className = 'contributors-widget';
  
  // Add header
  const header = document.createElement('h3');
  header.textContent = `Our ${data.metadata.total_contributors} Contributors`;
  widget.appendChild(header);
  
  // Add stats
  const stats = document.createElement('div');
  stats.className = 'contributor-stats';
  stats.innerHTML = `
    <div class="stat">
      <span class="number">${data.metadata.total_contributions}</span>
      <span class="label">Total Contributions</span>
    </div>
    <div class="stat">
      <span class="number">${data.metadata.stats.active_contributors}</span>
      <span class="label">Active Contributors</span>
    </div>
    <div class="stat">
      <span class="number">${data.metadata.stats.new_contributors}</span>
      <span class="label">New This Month</span>
    </div>
  `;
  widget.appendChild(stats);
  
  // Add contributor grid
  const grid = document.createElement('div');
  grid.className = 'contributors-grid';
  
  data.data.slice(0, 12).forEach(contributor => {
    const item = document.createElement('div');
    item.className = 'contributor-item';
    item.innerHTML = `
      <img src="${contributor.avatar_url}" alt="${contributor.login}" class="avatar">
      <div class="info">
        <h4>${contributor.login}</h4>
        <p>${contributor.contributions} contributions</p>
        <a href="${contributor.html_url}" target="_blank">View Profile</a>
      </div>
    `;
    grid.appendChild(item);
  });
  
  widget.appendChild(grid);
  return widget;
}
 
// Use the widget
buildContributorsWidget().then(widget => {
  document.getElementById('contributors-section').appendChild(widget);
});

Repository Analytics

// Analyze repository activity
async function analyzeRepositoryActivity() {
  const repositories = ['FixFX', 'fivem-boilerplate', 'redm-resources'];
  const results = {};
  
  for (const repo of repositories) {
    const response = await fetch(
      `https://fixfx.wiki/api/contributors?repo=${repo}&includeStats=true`
    );
    const data = await response.json();
    
    results[repo] = {
      contributors: data.metadata.total_contributors,
      contributions: data.metadata.total_contributions,
      topContributor: data.data[0],
      activity: {
        active: data.metadata.stats.active_contributors,
        new: data.metadata.stats.new_contributors
      }
    };
  }
  
  // Generate report
  console.log('Repository Activity Report');
  console.log('==========================');
  
  Object.entries(results).forEach(([repo, stats]) => {
    console.log(`\n${repo}:`);
    console.log(`  Contributors: ${stats.contributors}`);
    console.log(`  Contributions: ${stats.contributions}`);
    console.log(`  Top Contributor: ${stats.topContributor.login} (${stats.topContributor.contributions} contributions)`);
    console.log(`  Active Contributors: ${stats.activity.active}`);
    console.log(`  New Contributors: ${stats.activity.new}`);
  });
  
  // Find most active repository
  const mostActive = Object.entries(results)
    .reduce((a, b) => results[a[0]].contributions > results[b[0]].contributions ? a : b);
  
  console.log(`\nMost Active Repository: ${mostActive[0]} (${mostActive[1].contributions} contributions)`);
  
  return results;
}
 
// Run analysis
analyzeRepositoryActivity();

Contribution Recognition

// Generate contributor recognition badges
async function generateContributorBadges() {
  const response = await fetch(
    'https://fixfx.wiki/api/contributors?includeStats=true&limit=100'
  );
  const data = await response.json();
  
  const badges = {
    topContributor: null,
    mostActive: null,
    newcomer: null,
    allRounder: null
  };
  
  // Top Contributor (most contributions overall)
  badges.topContributor = data.data[0];
  
  // Most Active (most recent activity)
  badges.mostActive = data.data
    .filter(c => c.last_contribution)
    .sort((a, b) => new Date(b.last_contribution) - new Date(a.last_contribution))[0];
  
  // Newcomer (recent first contribution)
  badges.newcomer = data.data
    .filter(c => c.first_contribution)
    .sort((a, b) => new Date(b.first_contribution) - new Date(a.first_contribution))[0];
  
  // All-Rounder (balanced contribution types)
  badges.allRounder = data.data
    .filter(c => c.contribution_types)
    .map(c => ({
      ...c,
      diversity: Object.keys(c.contribution_types).filter(key => c.contribution_types[key] > 0).length
    }))
    .sort((a, b) => b.diversity - a.diversity)[0];
  
  console.log('Contributor Recognition Badges');
  console.log('==============================');
  
  Object.entries(badges).forEach(([badge, contributor]) => {
    if (contributor) {
      console.log(`\n🏆 ${badge.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}:`);
      console.log(`   ${contributor.login} (${contributor.contributions} contributions)`);
      console.log(`   GitHub: ${contributor.html_url}`);
      
      if (contributor.contribution_types) {
        const types = Object.entries(contributor.contribution_types)
          .filter(([, count]) => count > 0)
          .map(([type, count]) => `${type}: ${count}`)
          .join(', ');
        console.log(`   Types: ${types}`);
      }
    }
  });
  
  return badges;
}
 
// Generate and display badges
generateContributorBadges();

Data Freshness

  • Contributor data is refreshed every 6 hours
  • Statistics are calculated in real-time
  • GitHub API rate limits may affect update frequency
  • Cache headers indicate last update time

Rate Limiting

  • 100 requests per minute per IP address
  • Burst allowance of 20 requests
  • No authentication required

Error Handling

Standard HTTP status codes:

  • 200: Success
  • 400: Bad Request - Invalid parameters
  • 404: Not Found - Repository not found
  • 429: Too Many Requests - Rate limit exceeded
  • 503: Service Unavailable - GitHub API issues

Example error response:

{
  "error": "Repository not found",
  "message": "The specified repository does not exist in the organization",
  "statusCode": 404
}

Best Practices

  1. Caching

    • Cache contributor data locally for frequently accessed information
    • Respect the API's cache headers
    • Implement proper cache invalidation
  2. Performance

    • Use pagination for large contributor lists
    • Request only necessary data with query parameters
    • Implement proper error handling
  3. Recognition

    • Display contributor information prominently
    • Link back to GitHub profiles
    • Update contributor displays regularly
  4. Privacy

    • Respect contributor privacy preferences
    • Only display publicly available information
    • Provide opt-out mechanisms where appropriate

Support

For questions about the Contributors API, please join our Discord. We can help with:

  • API integration
  • Data interpretation
  • Custom analytics
  • Recognition programs

The Contributors API helps build community engagement by recognizing valuable contributions across our projects.

Contribution data is sourced from public GitHub activity and may not reflect all forms of contribution to our projects.

On this page