Endpoint: GET /api/summary Authentication Required
Retrieve a monthly activity summary for the currently authenticated user. This endpoint generates a focused snapshot of GitHub activity for a specific month and year.
Authentication
This endpoint requires authentication. Users must be logged in via GitHub OAuth.
The endpoint:
Validates the user has an active session
Retrieves the GitHub access token from the session
Fetches the authenticated user’s GitHub profile
Generates a monthly wrapped summary
Request
Query Parameters
year
number
default: "Current year"
Year to generate summary for (2008 - current year) Example: 2024
month
number
default: "Current month"
Month to generate summary for (1-12) Example: 3 (March)
Optional GitHub personal access token override Note : Typically not needed as the session token is used automatically.
Validation Rules
year: Integer between 2008 and current year
month: Integer between 1 and 12
Response
User wrapped data scoped to the specified month The structure is similar to /api/wrapped/user but focused on a single month’s activity. See User Wrapped for the full data structure.
Examples
Specific Month Request
cURL
JavaScript
TypeScript with React
curl "https://your-domain.com/api/summary?year=2024&month=3" \
-H "Cookie: better-auth.session_token=..."
Current Month (Default)
# Defaults to current year and month
curl "https://your-domain.com/api/summary" \
-H "Cookie: better-auth.session_token=..."
Example Response
{
"data" : {
"user" : {
"username" : "octocat" ,
"avatar_url" : "https://avatars.githubusercontent.com/u/583231" ,
"name" : "The Octocat" ,
"bio" : "GitHub mascot" ,
"public_repos" : 8 ,
"followers" : 9500 ,
"total_stars" : 15420
},
"year" : 2024 ,
"overview" : {
"totalCommits" : 87 ,
"totalPRs" : 12 ,
"totalIssues" : 5 ,
"topLanguages" : [
{
"language" : "TypeScript" ,
"bytes" : 450000 ,
"percentage" : 62.5
},
{
"language" : "JavaScript" ,
"bytes" : 180000 ,
"percentage" : 25.0
}
],
"busiestMonth" : { "month" : "Mar" , "count" : 87 }
},
"hourlyActivity" : {
"9" : 8 ,
"10" : 12 ,
"14" : 15 ,
"15" : 18
},
"dailyActivity" : {
"Monday" : 18 ,
"Tuesday" : 15 ,
"Wednesday" : 12 ,
"Thursday" : 20 ,
"Friday" : 22
},
"streak" : {
"longest" : 15 ,
"totalActiveDays" : 22 ,
"mostActiveDay" : {
"date" : "2024-03-15" ,
"count" : 8
}
},
"topRepos" : [
{
"name" : "my-project" ,
"owner" : { "login" : "octocat" },
"description" : "A cool project" ,
"stars" : 450 ,
"language" : "TypeScript"
}
],
"generatedAt" : "2026-03-03T08:00:00Z"
}
}
Error Responses
400 Bad Request
401 Unauthorized
500 Internal Server Error
{
"error" : "Invalid parameters"
}
Use Cases
Monthly Activity Dashboard
function MonthlyActivity () {
const [ summaries , setSummaries ] = useState ([]);
const currentYear = 2024 ;
useEffect (() => {
// Fetch all 12 months
Promise . all (
Array . from ({ length: 12 }, ( _ , i ) => i + 1 ). map ( month =>
fetch ( `/api/summary?year= ${ currentYear } &month= ${ month } ` )
. then ( r => r . json ())
)
). then ( results => {
setSummaries ( results . map ( r => r . data ));
});
}, []);
return (
< div >
< h1 >{ currentYear } Monthly Activity </ h1 >
{ summaries . map (( summary , i ) => (
< MonthCard
key = { i }
month = {i + 1 }
commits = {summary.overview. totalCommits }
prs = {summary.overview. totalPRs }
/>
))}
</ div >
);
}
Current vs Previous Month Comparison
async function compareMonths () {
const now = new Date ();
const currentMonth = now . getMonth () + 1 ;
const currentYear = now . getFullYear ();
const previousMonth = currentMonth === 1 ? 12 : currentMonth - 1 ;
const previousYear = currentMonth === 1 ? currentYear - 1 : currentYear ;
const [ current , previous ] = await Promise . all ([
fetch ( `/api/summary?year= ${ currentYear } &month= ${ currentMonth } ` )
. then ( r => r . json ()),
fetch ( `/api/summary?year= ${ previousYear } &month= ${ previousMonth } ` )
. then ( r => r . json ())
]);
const commitChange =
current . data . overview . totalCommits - previous . data . overview . totalCommits ;
console . log ( `Commit change: ${ commitChange > 0 ? '+' : '' }${ commitChange } ` );
}
Activity Calendar
function ActivityCalendar () {
const [ monthData , setMonthData ] = useState ( null );
const [ selectedMonth , setSelectedMonth ] = useState ( new Date (). getMonth () + 1 );
const [ selectedYear , setSelectedYear ] = useState ( new Date (). getFullYear ());
useEffect (() => {
fetch ( `/api/summary?year= ${ selectedYear } &month= ${ selectedMonth } ` )
. then ( r => r . json ())
. then ( result => setMonthData ( result . data ));
}, [ selectedMonth , selectedYear ]);
return (
< div >
< MonthPicker
month = { selectedMonth }
year = { selectedYear }
onChange = {( m , y) => {
setSelectedMonth ( m );
setSelectedYear ( y );
}}
/>
{ monthData && (
<>
< ActivityHeatmap data = {monthData. dailyActivity } />
< TopRepos repos = {monthData. topRepos } />
< LanguageBreakdown languages = {monthData.overview. topLanguages } />
</>
)}
</ div >
);
}
Feature /api/summary/api/performanceScope Single month Full year Granularity Month + Year Year only Use Case Monthly tracking Annual review Data Depth Month-specific Year-wide trends
Implementation Details
The endpoint uses the generateUserWrappedForMonth analytics method:
const analytics = new AnalyticsEngine ( github );
const wrappedData = await analytics . generateUserWrappedForMonth (
ghUser . login ,
year ,
month
);
This method filters all user activity to the specified month, providing focused insights.
Caching
This endpoint does not cache responses because:
Data is user-specific and private
Monthly summaries are typically accessed for current/recent months
Users expect real-time data for their own accounts
Source Code
Implementation: app/api/summary/route.ts
User Performance Full year performance metrics
User Wrapped Query any user’s public wrapped data
User Repositories List authenticated user’s repositories
Authentication Learn about GitHub OAuth