Docs · v1

Shipseo API & packages

Public REST API for the workspace-scoped Pro plan, plus quickstarts for the three npm packages. Everything is curl-first, no proprietary SDK required.

Contenido

Quickstart

Get an API key from your dashboard at /team → API keys. Then your first call:

curl https://shipseo.dev/api/v1/sites \
  -H "Authorization: Bearer sk_live_..."
bash

Response is JSON: { sites: [...] }. All responses are UTF-8 JSON, always. Errors follow the shape { error, message, ... } — see Error codes.

Authentication

Every request to /api/v1/* must carry an Authorization: Bearer sk_live_... header. Keys are workspace-scoped — one key = one workspace.

Plan gate
API keys can only be created on the Pro plan or higher. FREE / STARTER workspaces see a Pro upsell in the dashboard. Existing keys stop resolving if the workspace is downgraded below Pro — no surprise "my scripts kept working after I cancelled" bill.

Keys are hashed with SHA-256 in the database — the plaintext is shown once at creation. If you lose it, revoke and mint a new one from the dashboard.

Rate limits

Hourly rolling window per key. When you hit the ceiling you get a 429 with a Retry-After header (seconds).

PlanRequests / hourNotes
FREE / STARTER0API not included
PRO100~72k/mo steady state
AGENCY500~360k/mo steady state
ENTERPRISEunlimitedContact us

POST /audits also consumes your workspace's monthly audit budget (auditsPerMonth) — PRO gets 4/mo, AGENCY gets 30/mo. A curl loop can't burn the whole month's budget in seconds.

Endpoints

Three endpoints today. More coming as we validate what real integrations need.

GET/api/v1/sites

List all sites in the caller's workspace.

curl https://shipseo.dev/api/v1/sites \
  -H "Authorization: Bearer sk_live_..."
bash

Response:

{
  "sites": [
    {
      "id": "site_cmt61a2340004o98zuxl8xitc",
      "name": "Acme Marketing",
      "url": "https://acme.com",
      "domain": "acme.com",
      "createdAt": "2026-08-01T00:00:00.000Z"
    }
  ]
}
json
POST/api/v1/audits

Trigger a full-site audit on one of your sites. Synchronous — waits for the audit to complete (~10-30s typical) before responding.

curl -X POST https://shipseo.dev/api/v1/audits \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_cmt61a2340004o98zuxl8xitc"}'
bash

Response (200):

{
  "auditId": "audit_cmt6bkcho0001pockb25ef4hv",
  "score": 82,
  "issueCount": 6,
  "pagesCrawled": 15,
  "durationMs": 12500
}
json

Consumes 1 from your monthly auditsPerMonth budget. Returns 403 plan_limit when the cap is hit.

GET/api/v1/audits/:auditId

Fetch a single audit and its detected issues.

curl https://shipseo.dev/api/v1/audits/audit_... \
  -H "Authorization: Bearer sk_live_..."
bash

Response (200):

{
  "audit": {
    "id": "audit_...",
    "status": "COMPLETED",
    "score": 82,
    "startedAt": "2026-08-23T21:00:00.000Z",
    "completedAt": "2026-08-23T21:00:12.500Z",
    "site": {
      "id": "site_...",
      "name": "Acme Marketing",
      "url": "https://acme.com"
    },
    "issues": [
      {
        "id": "issue_...",
        "category": "meta",
        "type": "missing_meta_description",
        "severity": "HIGH",
        "title": "Falta meta description",
        "description": "Sin meta description...",
        "affectedUrl": null,
        "affectedUrls": ["https://acme.com/pricing"],
        "value": null,
        "recommended": "Meta description única de 120-160 caracteres"
      }
    ]
  }
}
json

Returns 404 audit_not_found if the audit doesn't belong to your workspace — same response as a real unknown id, so cross-tenant existence isn't leaked.

Error codes

All errors follow the shape { error: "<slug>", message: "<human>" }. Slugs are stable — branch on error, display message.

HTTPerror slugWhen
400invalid_jsonBody was not valid JSON
400missing_site_idPOST /audits without siteId
401missing_authNo Authorization header
401unauthorizedKey unknown, revoked, expired, or plan downgraded
403plan_not_includedWorkspace plan doesn't include the API
403plan_limitMonthly quota reached (e.g. audits/mo)
404site_not_foundSite doesn't exist or belongs to another workspace
404audit_not_foundSame, for audits
429rate_limitedHourly cap hit — respect Retry-After
502audit_failedTarget site crawl failed (DNS, timeout, 5xx)

Admin API

Cross-tenant REST for platform admins. Distinct from the workspace-scoped v1 API above — this one uses sk_admin_* keys and can read/write across every workspace. All calls are logged to AdminApiCallLog.

Platform-admin only

These endpoints require an sk_admin_* key, which only a PlatformAdmin user can create. There is no UI for creating one — a real admin runs the mint script server-side:

pnpm --filter @shipseo/web exec tsx scripts/create-admin-api-key.ts \
  --email admin@yourcompany.com --label "support-ops"
bash

Also available: generic tRPC dispatcher at POST /api/admin/trpc/<namespace>.<procedure> for anything not wrapped in v1 yet.

GET/api/admin/v1/overview

Platform metrics: workspace counts by status, plan distribution, activity, cost roll-ups over the last 30d.

curl https://shipseo.dev/api/admin/v1/overview \
  -H "Authorization: Bearer sk_admin_..."
bash
GET/api/admin/v1/workspaces

Cross-tenant workspace list with search + filters + pagination.

curl "https://shipseo.dev/api/admin/v1/workspaces?plan=PRO&status=ACTIVE&page=0&pageSize=25" \
  -H "Authorization: Bearer sk_admin_..."
bash

Query params: search (name/slug/owner email), plan, status, page, pageSize (max 100).

GET/api/admin/v1/workspaces/:workspaceId

Full workspace detail: billing, members, sites, integration health.

curl https://shipseo.dev/api/admin/v1/workspaces/cmt61a2340001o98zmlvj9cv0 \
  -H "Authorization: Bearer sk_admin_..."
bash
PATCH/api/admin/v1/workspaces/:workspaceId

Unified update. Include any combination of plan, status, trialEndsAt plus a required reason (≥5 chars, logged for the audit trail).

curl -X PATCH https://shipseo.dev/api/admin/v1/workspaces/cmt61a234... \
  -H "Authorization: Bearer sk_admin_..." \
  -H "Content-Type: application/json" \
  -d '{
    "plan": "PRO",
    "status": "ACTIVE",
    "reason": "manual upgrade after PayPal reconciliation"
  }'
bash

Fields apply sequentially. If one fails and others succeed, the response is 207 Multi-Status with a { applied: [{ field, ok, error? }] } array so you know exactly what landed.

GET/api/admin/v1/action-log

Cross-tenant audit trail. Every plan override / status flip / trial extension is captured with the acting admin + reason.

curl "https://shipseo.dev/api/admin/v1/action-log?targetId=cmt61a234...&pageSize=50" \
  -H "Authorization: Bearer sk_admin_..."
bash

Query params: adminUserId, action (workspace.update_plan | workspace.set_status | workspace.extend_trial),targetId, page, pageSize.

Packages

Three MIT-licensed dev-facing packages, all installable without a Shipseo account. Point of entry depends on what you're building.

@shipseo/mcp
v0.4 · 10 tools
npm

MCP server for Cursor / Claude Desktop / VS Code (Copilot Chat) / Windsurf. Your editor's LLM audits, tracks history, and lists pending fixes without leaving the IDE.

// ~/.cursor/mcp.json  ·  claude_desktop_config.json
// .vscode/mcp.json  (VS Code + Copilot Chat)
{
  "mcpServers": {
    "shipseo": {
      "command": "npx",
      "args": ["-y", "@shipseo/mcp"]
    }
  }
}
json
@shipseo/next
v0.1
npm

Next.js SDK. Resolves per-route SEO metadata from the dashboard at render time, with a local fallback so a Shipseo outage never breaks your <head>.

// app/layout.tsx
import { shipseoMetadata } from '@shipseo/next';

export async function generateMetadata() {
  return shipseoMetadata({
    route: '/',
    fallback: { title: 'My app' },
  });
}
tsx
@shipseo/init
v0.1
npm

One-shot scaffolder. Detects Next.js App/Pages Router and writes sitemap.ts, robots.ts, and metadata boilerplate — with backup if files existed.

# In your Next.js project
npx @shipseo/init
bash
Source on GitHub

Everything above — the API code, the packages, the docs page itself — is in the same monorepo, MIT licensed. File an issue or PR if something's off.

Open GitHub
Docs — Shipseo