Skip to main content

Overview

The analyze endpoint performs a comprehensive AI-powered analysis of a GitHub repository, returning insights about code quality, architecture, security, dependencies, and improvement suggestions. Key Features:
  • Real-time streaming with Server-Sent Events (SSE)
  • Multi-layer caching for instant results
  • In-flight request deduplication
  • Branch-specific analysis
  • Daily tiered rate limiting

Endpoint

POST /api/analyze

Request

Headers

Content-Type
string
required
Must be application/json

Body Parameters

url
string
required
Full GitHub repository URLFormat: https://github.com/{owner}/{repo}Example: https://github.com/vercel/next.js
branch
string
Branch name to analyze. Defaults to the repository’s default branch (usually main or master)Example: canary, develop, main

Example Request

curl -X POST https://repolyze.ossium.live/api/analyze \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com/vercel/next.js",
    "branch": "canary"
  }'

Response

The endpoint returns a streaming response using Server-Sent Events (SSE). Events are sent as they become available during analysis.

Response Headers

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
X-RateLimit-Remaining: 9

Stream Event Types

The response stream contains multiple event types, each with a specific purpose:

1. Metadata Event

Sent first with repository information, file tree, and branch data.
type
string
"metadata"
data
object
Example:
{
  "type": "metadata",
  "data": {
    "metadata": {
      "name": "next.js",
      "fullName": "vercel/next.js",
      "description": "The React Framework",
      "stars": 120000,
      "forks": 25000,
      "language": "TypeScript",
      "defaultBranch": "canary",
      "owner": {
        "login": "vercel",
        "avatarUrl": "https://avatars.githubusercontent.com/u/14985020"
      }
    },
    "fileStats": {
      "totalFiles": 1250,
      "totalDirectories": 180,
      "languages": {
        "TypeScript": 980,
        "JavaScript": 150,
        "CSS": 45
      }
    },
    "branch": "canary",
    "availableBranches": [
      {
        "name": "canary",
        "commit": { "sha": "abc123", "url": "..." },
        "protected": true,
        "isDefault": true
      }
    ]
  }
}

2. Scores Event

Contains calculated quality scores and detailed breakdown.
type
string
"scores"
data
object
Example:
{
  "type": "scores",
  "data": {
    "overall": 92,
    "codeQuality": 95,
    "documentation": 90,
    "security": 88,
    "maintainability": 94,
    "testCoverage": 85,
    "dependencies": 90,
    "breakdown": {
      "codeQuality": {
        "score": 95,
        "factors": ["TypeScript strict mode", "Consistent formatting"]
      }
    }
  }
}

3. Automations Event

Suggested automation opportunities (issues, workflows).
type
string
"automations"
data
array
Array of automation suggestions
Example:
{
  "type": "automations",
  "data": [
    {
      "id": "auto-1",
      "type": "workflow",
      "title": "Add CI/CD Pipeline",
      "description": "Set up automated testing on push/PR",
      "body": "Add GitHub Actions workflow for CI",
      "labels": ["ci", "automation"],
      "priority": "high",
      "category": "DevOps",
      "estimatedEffort": "30 min",
      "files": [".github/workflows/ci.yml"]
    }
  ]
}

4. Refactors Event

Suggested code refactoring opportunities.
type
string
"refactors"
data
array
Array of refactoring suggestions
Example:
{
  "type": "refactors",
  "data": [
    {
      "id": "ref-1",
      "title": "Enable TypeScript strict mode",
      "description": "Better type safety with strict: true",
      "impact": "high",
      "effort": "medium",
      "category": "Type Safety",
      "files": ["tsconfig.json"]
    }
  ]
}

5. Content Event

Streamed AI-generated analysis content (text chunks).
type
string
"content"
data
string
Text chunk of AI-generated analysis
Example:
{"type":"content","data":"This is a well-structured"}
{"type":"content","data":" Next.js application with"}
{"type":"content","data":" comprehensive TypeScript support."}

6. Tier Event

User tier information for UI display.
type
string
"tier"
data
string
User tier: "anonymous", "free", or "pro"
Example:
{"type":"tier","data":"free"}

7. Done Event

Signals that the analysis is complete.
type
string
"done"
Example:
{"type":"done"}

8. Error Event

Sent if an error occurs during streaming.
type
string
"error"
data
string
Error message describing what went wrong
Example:
{"type":"error","data":"Repository not found"}

Error Responses

Non-streaming errors return standard JSON error responses:

400 Bad Request

{
  "error": "Invalid JSON in request body"
}

413 Payload Too Large

{
  "error": "Request body too large"
}

429 Too Many Requests (Burst)

{
  "error": "Too many requests. Please try again later."
}
Headers:
Retry-After: 60

429 Too Many Requests (Daily Limit)

{
  "error": "Daily limit reached. Sign in to get more analyses.",
  "code": "DAILY_LIMIT_REACHED",
  "limit": 1,
  "remaining": 0,
  "tier": "anonymous"
}

500 Internal Server Error

{
  "error": "Analysis failed. Please try again."
}

503 Service Unavailable

{
  "error": "Server is not properly configured."
}

Code Examples

JavaScript/TypeScript (Browser)

interface StreamEvent {
  type: 'metadata' | 'scores' | 'content' | 'automations' | 'refactors' | 'tier' | 'done' | 'error';
  data: any;
}

async function analyzeRepository(url: string, branch?: string) {
  const response = await fetch('https://repolyze.ossium.live/api/analyze', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ url, branch })
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error);
  }

  const reader = response.body!.getReader();
  const decoder = new TextDecoder();
  let buffer = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split('\n');
    buffer = lines.pop() || '';

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const event: StreamEvent = JSON.parse(line.slice(6));
        
        switch (event.type) {
          case 'metadata':
            console.log('Repository:', event.data.metadata.fullName);
            break;
          case 'scores':
            console.log('Overall score:', event.data.overall);
            break;
          case 'content':
            process.stdout.write(event.data);
            break;
          case 'done':
            console.log('\nAnalysis complete!');
            break;
          case 'error':
            console.error('Error:', event.data);
            break;
        }
      }
    }
  }
}

// Usage
analyzeRepository('https://github.com/vercel/next.js', 'canary');

Node.js

const https = require('https');

function analyzeRepository(url, branch) {
  const postData = JSON.stringify({ url, branch });
  
  const options = {
    hostname: 'repolyze.ossium.live',
    path: '/api/analyze',
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Content-Length': Buffer.byteLength(postData)
    }
  };

  const req = https.request(options, (res) => {
    let buffer = '';
    
    res.on('data', (chunk) => {
      buffer += chunk.toString();
      const lines = buffer.split('\n');
      buffer = lines.pop() || '';
      
      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const event = JSON.parse(line.slice(6));
          console.log(event.type, event.data);
        }
      }
    });
    
    res.on('end', () => {
      console.log('Stream ended');
    });
  });

  req.on('error', (error) => {
    console.error('Error:', error);
  });

  req.write(postData);
  req.end();
}

analyzeRepository('https://github.com/vercel/next.js', 'canary');

Python

import requests
import json

def analyze_repository(url: str, branch: str = None):
    endpoint = 'https://repolyze.ossium.live/api/analyze'
    payload = {'url': url}
    
    if branch:
        payload['branch'] = branch
    
    response = requests.post(
        endpoint,
        json=payload,
        stream=True,
        headers={'Content-Type': 'application/json'}
    )
    
    if response.status_code != 200:
        error = response.json()
        raise Exception(error.get('error', 'Unknown error'))
    
    for line in response.iter_lines():
        if line.startswith(b'data: '):
            event = json.loads(line[6:])
            event_type = event['type']
            event_data = event.get('data')
            
            if event_type == 'metadata':
                print(f"Repository: {event_data['metadata']['fullName']}")
            elif event_type == 'scores':
                print(f"Overall score: {event_data['overall']}")
            elif event_type == 'content':
                print(event_data, end='', flush=True)
            elif event_type == 'done':
                print("\nAnalysis complete!")
            elif event_type == 'error':
                print(f"Error: {event_data}")

# Usage
analyze_repository('https://github.com/vercel/next.js', 'canary')

Caching Behavior

The analyze endpoint implements sophisticated caching:

1. Analysis Result Cache

Full analysis results are cached in memory by {owner}/{repo}:{branch}. Subsequent requests for the same repository and branch receive instant cached responses. Cache Duration: In-memory, cleared on server restart

2. In-Flight Deduplication

If a repository is currently being analyzed, concurrent requests wait for the first analysis to complete and then receive the cached result. This prevents duplicate AI calls for the same repository.

3. GitHub Data Cache

Repository metadata, tree, and branches are cached server-side to reduce GitHub API calls.

Rate Limit Details

See the API Overview for complete rate limit information.

Health Check

You can check if the service is available:
curl https://repolyze.ossium.live/api/analyze
Response:
{
  "status": "ok",
  "timestamp": "2026-03-03T10:30:00.000Z",
  "services": {
    "openrouter": "configured",
    "github": "configured"
  }
}
For detailed type definitions, see Analysis Response Types.

Build docs developers (and LLMs) love