How to Integrate Open-SEO with Other Tools: A Complete Integration Guide
Open-SEO exposes its core functionality through automatically routed HTTP endpoints, allowing any external system to programmatically access SEO data, rank tracking, audits, and billing via authenticated API calls.
Integrating Open-SEO with external tools unlocks powerful automation workflows—from CI pipelines that trigger SEO audits on every deploy to custom dashboards that pull real-time ranking data. As implemented in every-app/open-seo, the integration surface is built on TanStack React Start's createServerFn architecture, which transforms server functions into type-safe JSON RPC endpoints.
Core Integration Architecture
Understanding Open-SEO's layered architecture helps you choose the right integration approach for your use case.
| Layer | Purpose | Key Source Files |
|---|---|---|
| HTTP Entry Point | Cloudflare Workers fetch handler routes UI requests, OAuth flows, and chat endpoints |
src/server.ts |
| Authentication | ensureUser middleware validates JWTs, Cloudflare Access headers, and project permissions |
src/middleware/ensureUser.ts |
| Server Functions | createServerFn exports from src/serverFunctions/*.ts become HTTP endpoints |
src/serverFunctions/projects.ts |
| Routing | TanStack Router's routeTree maps paths to RPC endpoints at /api/* |
src/routeTree.gen.ts |
| Data Layer | Drizzle ORM provides type-safe database access for projects, audits, and tracking data | src/db/schema.ts |
According to the Open-SEO source code, every business operation you see in the UI has a corresponding server function that external tools can call directly.
Authentication Methods for External Integration
Before making API calls, you need valid credentials. Open-SEO supports three authentication patterns for programmatic access.
JWT / Cloudflare Access Token
The UI stores session state in an open-seo.session cookie containing a JWT. External tools can:
- Extract and reuse this cookie for browser-automation scenarios
- Generate their own JWT using the server's signing secret (for service accounts)
The token validation logic lives in src/middleware/ensureUser.ts, which parses the JWT, resolves the user's organization, and validates project-level access.
OAuth 2.0 / MCP Delegation
For third-party SaaS integrations, use the Open-SEO OAuth provider at /oauth/... endpoints to obtain access tokens on behalf of users. This enables scenarios where your application acts with the user's explicit permission without handling their primary credentials.
Project-Scoped API Keys
Long-lived tokens tied to specific projects can be created via the Projects API. The createProject function in src/serverFunctions/projects.ts returns a projectId that, combined with an organization-scoped JWT, enables fine-grained access control.
Integration Options Compared
| Method | Best For | Implementation Complexity |
|---|---|---|
| Direct HTTP calls | Server-side scripts, Python/Go/Java services, low-code platforms | Low—standard REST patterns |
| TanStack React Start client | TypeScript/React frontends already using Open-SEO components | Minimal—automatic type safety |
| WebSocket agents | Real-time chat features, streaming onboarding flows | Medium—requires Agents SDK |
| OAuth/MCP delegation | Third-party SaaS integrations, marketplace apps | Higher—full OAuth flow required |
Code Examples for Common Integration Scenarios
Node.js / TypeScript: Direct HTTP Integration
The most flexible approach for backend services. First obtain a JWT, then call any server function at its /api/ endpoint:
import fetch from 'node-fetch';
// Obtain JWT via client_credentials flow
async function getJwt(): Promise<string> {
const resp = await fetch('https://your-open-seo.example.com/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'client_credentials',
client_id: process.env.OPEN_SEO_CLIENT_ID,
client_secret: process.env.OPEN_SEO_CLIENT_SECRET,
}),
});
const data = await resp.json();
return data.access_token;
}
// Call createProject server function
async function createProject(name: string) {
const token = await getJwt();
const resp = await fetch(
'https://your-open-seo.example.com/api/createProject',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ name, domain: 'example.com', market: 'US' }),
},
);
if (!resp.ok) {
const err = await resp.text();
throw new Error(`Open-SEO error: ${resp.status} – ${err}`);
}
return await resp.json();
}
// Usage
createProject('Acme Corp')
.then((proj) => console.log('Created project:', proj))
.catch(console.error);
The createProject function is defined in src/serverFunctions/projects.ts and automatically exposed at POST /api/createProject.
React / TypeScript: Type-Safe Client Integration
For React applications already in the Open-SEO ecosystem, import server functions directly:
import { createProject } from '@/serverFunctions/projects';
async function onCreate() {
const project = await createProject({
name: 'New Startup',
domain: 'startup.io',
market: 'US',
});
console.log('Project created:', project);
}
The TanStack React Start client handles serialization, HTTP transport, and response typing automatically. The generated stub in src/routeTree.gen.ts ensures your calls stay synchronized with the server implementation.
Python: Using Requests Library
Python services can integrate without any Open-SEO-specific SDK:
import os
import requests
API_BASE = "https://your-open-seo.example.com"
TOKEN = os.getenv("OPEN_SEO_JWT")
def create_project(name, domain, market):
url = f"{API_BASE}/api/createProject"
payload = {"name": name, "domain": domain, "market": market}
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
r = requests.post(url, json=payload, headers=headers)
r.raise_for_status()
return r.json()
proj = create_project("Python SaaS", "python-saas.com", "US")
print("Created:", proj)
This pattern works with any language that can make HTTP requests and parse JSON responses.
Real-Time Chat: WebSocket Agents SDK
For conversational features like the Onboarding Chat or SAM assistant, connect to Durable Objects at /agents/*:
async function startOnboarding(projectId: string, token: string) {
const ws = new WebSocket(
`wss://your-open-seo.example.com/agents/ONBOARDING_CHAT/${projectId}`,
{
headers: { Authorization: `Bearer ${token}` },
},
);
ws.onopen = () => ws.send(JSON.stringify({ type: 'START' }));
ws.onmessage = (msg) => console.log('Chat:', msg.data);
}
The authorizeOnboardingChat function in src/server.ts enforces that the JWT belongs to the organization owning projectId, rejecting unauthorized connections with 401/403 status codes.
Required Environment Configuration
For full functionality, configure these environment variables in your Cloudflare Worker as defined in worker-configuration.d.ts:
| Variable | Purpose |
|---|---|
DATAFORSEO_API_KEY |
Required for SEO data generation, rank tracking, and keyword research |
OPENROUTER_API_KEY |
Powers AI-driven content and analysis features |
JWT_SECRET |
Signs and verifies authentication tokens |
The server validates DATAFORSEO_API_KEY presence in src/serverFunctions/config.ts before executing any SEO data operations.
Key Source Files for Integration Development
When building custom integrations, reference these files for authoritative implementation details:
src/serverFunctions/**/*.ts— Complete inventory of available API endpoints; eachcreateServerFnexport is callable via HTTPsrc/middleware/ensureUser.ts— JWT parsing, organization resolution, and project authorization logicsrc/server.ts— Entry point showing OAuth routing and/agents/*WebSocket upgrade handlingsrc/db/schema.ts— Database schema for direct querying or advanced reportingsrc/server/lib/dataforseo/core.ts— External API integration patterns for SEO data providers
Summary
Integrating Open-SEO with external tools leverages its TanStack React Start foundation to expose type-safe, authenticated JSON RPC endpoints:
- Any HTTP-capable system can call server functions at
/api/<function-name>with a valid JWT - React/TypeScript frontends get automatic type safety through the TanStack client
- Real-time features use WebSocket connections to Durable Objects with the same authentication middleware
- OAuth delegation enables secure third-party SaaS integrations without credential sharing
The integration surface mirrors the UI exactly—every feature available to users can be accessed programmatically by authenticating through src/middleware/ensureUser.ts and calling the corresponding function from src/serverFunctions/.
Frequently Asked Questions
What authentication token do I need for Open-SEO API calls?
You need either a JWT from the open-seo.session cookie, a service account JWT signed with the server's secret, or an OAuth access token obtained through the /oauth/... endpoints. The ensureUser middleware in src/middleware/ensureUser.ts validates all three types and resolves your organization and project permissions.
Can I use Open-SEO server functions from languages other than TypeScript?
Yes. The server functions are standard HTTP endpoints accepting JSON POST requests and returning JSON responses. The Python example above demonstrates calling createProject from Python using the requests library. Any language with HTTP capabilities—Go, Java, Rust, or low-code platforms—can integrate directly.
How do I find the correct URL for a specific server function?
Check src/routeTree.gen.ts for the auto-generated routing table, which maps server functions to /api/* paths. The convention follows the function name: createProject in src/serverFunctions/projects.ts becomes POST /api/createProject. You can also inspect network requests in the Open-SEO UI to discover endpoint patterns.
What happens if I call an Open-SEO endpoint without proper authentication?
The ensureUser middleware returns HTTP 401 for missing or invalid JWTs, and HTTP 403 when your token lacks the required organization or project scope. For WebSocket connections to /agents/*, unauthorized upgrade requests are rejected before the Durable Object is instantiated.
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 →