Main API Routes in Open-SEO: Complete Guide to the Every-App SEO Platform Endpoints
Open-SEO defines five primary API routes using TanStack React Router's file-based routing system, including health checks, OAuth callbacks for Google Search Console and Google Analytics 4, plus dynamic routes for Autumn integration and authentication providers.
Open-SEO is an open-source SEO platform built by every-app that exposes a clean REST API for health monitoring, third-party integrations, and OAuth authentication. This guide walks through each endpoint defined in the src/routes/api/ directory, explains their implementation, and provides working code examples you can run against any Open-SEO instance.
How Open-SEO Routes Are Structured
Unlike traditional Express or FastAPI servers, Open-SEO uses TanStack React Router's file-based routing. Each .ts file under src/routes/api/ automatically maps to a URL path matching its directory structure. The routeTree.gen.ts file (auto-generated at build time) registers these routes for server-side resolution.
Dynamic segments use the $ filename convention. For example, src/routes/api/autumn/$.ts matches /api/autumn/:slug where :slug captures any path segment after /api/autumn/.
GET /api/health — Service Health Check
The simplest route, located at src/routes/api/health.ts, provides a lightweight liveness probe.
// src/routes/api/health.ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/api/health')({
loader: async () => {
return { ok: true }
},
})
This endpoint returns a static JSON payload with no external dependencies, making it ideal for load balancers, Kubernetes health probes, and uptime monitoring.
curl -s https://your-instance.com/api/health | jq
# Output: { "ok": true }
Google Search Console OAuth: GET /api/gsc/oauth/callback
The src/routes/api/gsc/oauth/callback.ts file handles the OAuth 2.0 callback from Google Search Console. After a user authorizes Open-SEO to access their GSC data, Google redirects to this route with an authorization code query parameter.
The route implementation exchanges this code for an access token and stores it for subsequent API calls to the Google Search Console API. This enables Open-SEO to fetch search analytics, sitemap data, and indexing status on behalf of connected users.
# Example callback URL after user authorization
curl -s "https://your-instance.com/api/gsc/oauth/callback?code=4%2F0A...&state=xyz" | jq
Google Analytics 4 OAuth: GET /api/ga4/oauth/callback
Mirroring the GSC flow, src/routes/api/ga4/oauth/callback.ts handles OAuth callbacks for Google Analytics 4. This separate endpoint exists because GA4 and GSC use different OAuth scopes and token management requirements.
The route parses the authorization grant, exchanges it for GA4-specific credentials, and persists them for reporting features. Having distinct callback URLs prevents scope collisions and simplifies debugging authentication failures.
Dynamic Routes with Path Parameters
Open-SEO implements two dynamic routes using the TanStack $ splat convention:
Autumn Integration: GET /api/autumn/:slug
The file src/routes/api/autumn/$.ts creates a catch-all route matching /api/autumn/<any-segment>. The "Autumn" integration appears to be a custom or partner service where :slug resolves to a project token, identifier, or configuration key.
// Example client call with dynamic slug
const slug = 'my-project-token';
const response = await fetch(`https://your-instance.com/api/autumn/${slug}`);
const data = await response.json();
console.log('Autumn integration result:', data);
The route handler likely uses TanStack's params.slug to branch logic based on the specific identifier provided.
Authentication Providers: GET /api/auth/:provider
The src/routes/api/auth/$.ts file implements a unified authentication entry point. The :provider segment selects which identity provider to invoke—common values include github, google, or other configured SSO sources.
This design centralizes auth initialization without requiring separate files per provider. The handler inspects params.provider and delegates to the appropriate OAuth or SAML flow.
# Initiate GitHub authentication
curl -s https://your-instance.com/api/auth/github
# Initiate Google authentication
curl -s https://your-instance.com/api/auth/google
Complete Route Reference Table
| URL Path | Source File | Purpose | Auth Required |
|---|---|---|---|
/api/health |
src/routes/api/health.ts |
Liveness probe | No |
/api/gsc/oauth/callback |
src/routes/api/gsc/oauth/callback.ts |
GSC OAuth completion | No (receives token) |
/api/ga4/oauth/callback |
src/routes/api/ga4/oauth/callback.ts |
GA4 OAuth completion | No (receives token) |
/api/autumn/:slug |
src/routes/api/autumn/$.ts |
Dynamic Autumn integration | Varies by slug |
/api/auth/:provider |
src/routes/api/auth/$.ts |
Provider-specific auth initiation | No |
Working with the API Programmatically
Here's a complete TypeScript client showing all five endpoints:
interface HealthResponse {
ok: boolean;
}
class OpenSeoClient {
private baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl.replace(/\/$/, '');
}
async health(): Promise<HealthResponse> {
const res = await fetch(`${this.baseUrl}/api/health`);
if (!res.ok) throw new Error(`Health check failed: ${res.status}`);
return res.json();
}
async autumn<T = unknown>(slug: string): Promise<T> {
const res = await fetch(`${this.baseUrl}/api/autumn/${encodeURIComponent(slug)}`);
if (!res.ok) throw new Error(`Autumn request failed: ${res.status}`);
return res.json();
}
getAuthUrl(provider: 'github' | 'google'): string {
return `${this.baseUrl}/api/auth/${provider}`;
}
// GSC/GA4 callbacks are typically invoked by Google, not called directly
}
// Usage
const client = new OpenSeoClient('https://api.example.com');
const healthy = await client.health();
console.log('Service healthy:', healthy.ok);
const autumnData = await client.autumn('project-123');
Summary
- Five main API routes power Open-SEO's external interface: health checks, GSC OAuth, GA4 OAuth, Autumn integration, and provider-based authentication.
- File-based routing via TanStack React Router eliminates manual route registration—files automatically map to URL paths.
$.tsfiles create dynamic segments for extensible integrations like Autumn and multi-provider auth.- Zero health-check dependencies make
/api/healthsuitable for infrastructure monitoring without risk of cascading failures.
Frequently Asked Questions
How do I add a new API route to Open-SEO?
Create a new file under src/routes/api/ following the directory conventions. Static paths use literal filenames (analytics.ts → /api/analytics). Dynamic paths use $ (reports/$.ts → /api/reports/:id). Run npm run dev or your build command to regenerate routeTree.gen.ts with the new route.
Why are GSC and GA4 OAuth callbacks separate routes instead of a unified handler?
Separate routes allow distinct error handling, token storage logic, and scope validation for each Google service. GSC and GA4 maintain different API contracts and permission models—unified handling would complicate debugging and increase the blast radius of authentication bugs.
What authentication is required to call these API routes?
The health endpoint requires no authentication. OAuth callback routes receive bearer tokens from Google, not the caller. The Autumn and auth routes may enforce session or API key validation depending on the specific slug or provider configuration—check the implementation in autumn/$.ts and auth/$.ts for your deployment.
Can I use Open-SEO's API routes from a server-side application?
Yes. All routes return JSON and accept standard HTTP methods. For server-to-server calls, instantiate OpenSeoClient with your instance URL. Note that OAuth callbacks expect specific query parameters from Google's authorization server—direct server calls to these endpoints without a valid code will fail.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →