Skip to main content
GET
/
api
/
v1
/
analytics
/
contributors
Contributor Analytics
curl --request GET \
  --url https://api.example.com/api/v1/analytics/contributors
{
  "repo": "<string>",
  "contributor_count": 123,
  "page": 123,
  "per_page": 123,
  "total_pages": 123,
  "contributors": [
    {}
  ],
  "contributors[].username": "<string>",
  "contributors[].profile_summary": "<string>",
  "contributors[].patterns": [
    {}
  ],
  "contributors[].strengths": [
    {}
  ],
  "contributors[].pr_count": 123,
  "contributors[].commit_count": 123,
  "contributors[].last_seen_pr": 123
}

Overview

Retrieve comprehensive contributor profiles built from Mem0 AI memory, including developer patterns, strengths, and historical activity. This endpoint is designed for team leaders to understand their team’s expertise and contribution patterns.

Authentication

Requires a valid JWT token in the Authorization header:
Authorization: Bearer YOUR_JWT_TOKEN

Query Parameters

repo
string
required
Repository to query in owner/repo format (e.g., “acme/api-server”)
page
integer
default:"1"
Page number for pagination (1-indexed)
per_page
integer
default:"20"
Number of contributors per page (1-100)

Response

repo
string
Repository full name (owner/repo)
contributor_count
integer
Total number of contributors with AI memory
page
integer
Current page number
per_page
integer
Items per page
total_pages
integer
Total number of pages
contributors
array
Array of contributor profiles
contributors[].username
string
GitHub username
contributors[].profile_summary
string
AI-generated profile summary of the developer’s contribution style
contributors[].patterns
array
Array of identified developer patterns (coding habits, preferences, common approaches)
contributors[].strengths
array
Array of developer strengths (areas of expertise, technical skills)
contributors[].pr_count
integer
Total number of PRs submitted by this contributor
contributors[].commit_count
integer
Total number of commits by this contributor
contributors[].last_seen_pr
integer
Most recent PR number from this contributor

Example Request

curl -X GET "https://api.nectr.ai/api/v1/analytics/contributors?repo=acme/api-server&page=1&per_page=10" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Example Response

{
  "repo": "acme/api-server",
  "contributor_count": 12,
  "page": 1,
  "per_page": 10,
  "total_pages": 2,
  "contributors": [
    {
      "username": "johndoe",
      "profile_summary": "Experienced backend engineer focused on API design and database optimization. Consistently delivers well-tested, production-ready code with comprehensive documentation.",
      "patterns": [
        "Prefers comprehensive error handling with custom exception classes",
        "Always includes unit tests and integration tests for new features",
        "Favors async/await patterns for database operations"
      ],
      "strengths": [
        "Database schema design and optimization",
        "RESTful API architecture",
        "Performance profiling and optimization"
      ],
      "pr_count": 47,
      "commit_count": 312,
      "last_seen_pr": 42
    },
    {
      "username": "janedoe",
      "profile_summary": "Frontend specialist with strong TypeScript skills. Known for creating polished, accessible user interfaces with excellent attention to detail.",
      "patterns": [
        "Uses functional React components with hooks",
        "Implements comprehensive accessibility features (ARIA labels, keyboard navigation)",
        "Prefers composition over inheritance for component architecture"
      ],
      "strengths": [
        "TypeScript type safety and advanced patterns",
        "CSS-in-JS and responsive design",
        "State management with Redux and Context API"
      ],
      "pr_count": 38,
      "commit_count": 241,
      "last_seen_pr": 39
    }
  ]
}

Memory Types

The contributor data is built from three types of AI memories:

contributor_profile

High-level summary of the developer’s contribution style, generated from analyzing their PR history.

developer_pattern

Specific coding patterns and habits identified across multiple PRs:
  • Architectural preferences
  • Code organization style
  • Testing approaches
  • Common techniques

developer_strength

Technical areas where the developer excels:
  • Technology expertise
  • Problem-solving domains
  • Architectural skills

Error Responses

Repository Not Connected

{
  "detail": "Repo not connected or access denied"
}
HTTP Status: 403 Forbidden

Memory Layer Unavailable

{
  "repo": "acme/api-server",
  "contributor_count": 0,
  "contributors": [],
  "note": "Memory layer not configured"
}
HTTP Status: 200 OK (graceful degradation)

Use Cases

Team Overview Dashboard

data = get_contributors(repo="acme/api-server")

print(f"Team Overview - {data['repo']}")
print(f"Total Contributors: {data['contributor_count']}")
print()

for contributor in data['contributors'][:5]:
    print(f"👤 {contributor['username']}")
    print(f"   PRs: {contributor['pr_count']} | Commits: {contributor['commit_count']}")
    print(f"   Profile: {contributor['profile_summary']}")
    if contributor['strengths']:
        print(f"   Strengths: {', '.join(contributor['strengths'][:3])}")
    print()

Code Review Assignment

def suggest_reviewer(pr_files, contributors):
    """Suggest the best reviewer based on file expertise."""
    for contributor in contributors:
        for strength in contributor['strengths']:
            if any(tech in strength.lower() for tech in ['database', 'sql']):
                if any('db' in f or 'models' in f for f in pr_files):
                    return contributor['username']
    return contributors[0]['username']  # fallback to most active

data = get_contributors(repo="acme/api-server")
pr_files = ['app/models/user.py', 'app/db/migrations/001.sql']

reviewer = suggest_reviewer(pr_files, data['contributors'])
print(f"Suggested reviewer: {reviewer}")

Skill Gap Analysis

data = get_contributors(repo="acme/api-server")

all_strengths = {}
for contributor in data['contributors']:
    for strength in contributor['strengths']:
        all_strengths[strength] = all_strengths.get(strength, 0) + 1

print("Team Skills Coverage:")
for skill, count in sorted(all_strengths.items(), key=lambda x: x[1], reverse=True):
    coverage = (count / data['contributor_count']) * 100
    print(f"{skill}: {count} devs ({coverage:.0f}% coverage)")

Pagination Example

def get_all_contributors(repo):
    """Fetch all contributors across all pages."""
    all_contributors = []
    page = 1
    
    while True:
        data = get_contributors(repo=repo, page=page, per_page=20)
        all_contributors.extend(data['contributors'])
        
        if page >= data['total_pages']:
            break
        page += 1
    
    return all_contributors

Build docs developers (and LLMs) love