Endpoint: GET /api/validate
Validate whether a GitHub repository exists and retrieve basic repository information. This endpoint is useful for form validation before generating wrapped data.
Request
Query Parameters
Repository owner (username or organization name) Example: vercel, facebook, microsoft
Repository name Example: next.js, react, vscode
Response
Success Response
Whether the repository exists and is accessible
Repository metadata (only included if valid is true) Show RepositoryInfo structure
Full repository name (owner/repo)
Primary programming language
Error Response
false when repository doesn’t exist
Error message explaining why validation failed
Examples
Valid Repository
curl "https://your-domain.com/api/validate?owner=vercel&repo=next.js"
Response:
{
"valid" : true ,
"repository" : {
"owner" : "vercel" ,
"repo" : "next.js" ,
"name" : "vercel/next.js" ,
"description" : "The React Framework" ,
"stars" : 125000 ,
"forks" : 26800 ,
"language" : "TypeScript"
}
}
Invalid Repository
curl "https://your-domain.com/api/validate?owner=invalid&repo=does-not-exist"
Response (404):
{
"valid" : false ,
"error" : "Repository not found"
}
Private Repository (Authenticated)
cURL with Session
JavaScript with Session
curl "https://your-domain.com/api/validate?owner=myorg&repo=private-repo" \
-H "Cookie: better-auth.session_token=..."
Response:
{
"valid" : true ,
"repository" : {
"owner" : "myorg" ,
"repo" : "private-repo" ,
"name" : "myorg/private-repo" ,
"description" : "Internal project" ,
"stars" : 12 ,
"forks" : 3 ,
"language" : "JavaScript"
}
}
Missing Parameters
curl "https://your-domain.com/api/validate?owner=vercel"
Response (400):
{
"error" : "Missing owner or repo parameter"
}
Authentication Behavior
Unauthenticated Requests
Can validate public repositories only
Private repositories will return valid: false
Authenticated Requests
Can validate both public and private repositories
Uses session cookie or GitHub token for authentication
Private repository metadata is not cached
Caching Behavior
Validation results are cached to reduce GitHub API calls:
Public repositories : Cached for 24 hours
Private repositories : Never cached
Failed validations : Cached for 24 hours
Cache key format: validation:{owner}:{repo}
Cache Invalidation
Authenticated users bypass cache for private repositories:
// If logged in, ignore invalid cache (might be private repo that failed for anon)
if ( ! githubToken || cached . valid ) {
return cached ;
}
Use Cases
function RepositoryForm () {
const [ owner , setOwner ] = useState ( '' );
const [ repo , setRepo ] = useState ( '' );
const [ validation , setValidation ] = useState ( null );
const validateRepo = async () => {
const response = await fetch (
`/api/validate?owner= ${ owner } &repo= ${ repo } `
);
const result = await response . json ();
setValidation ( result );
};
return (
< form >
< input value = { owner } onChange = { ( e ) => setOwner ( e . target . value ) } />
< input value = { repo } onChange = { ( e ) => setRepo ( e . target . value ) } />
< button onClick = { validateRepo } > Validate </ button >
{ validation && (
validation . valid ? (
< div > ✓ Repository found: { validation . repository . name } </ div >
) : (
< div > ✗ { validation . error } </ div >
)
) }
</ form >
);
}
Pre-flight Check
async function generateWrappedSafely ( owner , repo , year ) {
// First validate the repository exists
const validation = await fetch (
`/api/validate?owner= ${ owner } &repo= ${ repo } `
). then ( r => r . json ());
if ( ! validation . valid ) {
throw new Error ( validation . error );
}
// Now generate wrapped data
const wrapped = await fetch (
`/api/wrapped?owner= ${ owner } &repo= ${ repo } &year= ${ year } `
). then ( r => r . json ());
return wrapped . data ;
}
Error Handling
400 Bad Request
404 Not Found
500 Internal Server Error
{
"error" : "Missing owner or repo parameter"
}
Source Code
Implementation: app/api/validate/route.ts
Repository Wrapped Generate wrapped data after validation
Authentication Learn about authenticating for private repos