SEO Ops Agency onboarding

Get your first property live in five steps

SEO Ops turns Google Search Console data into deduped work items your team can act on — via API, optional webhooks, and client digests from SEO Ops <reports@seo-ops.com>.

Pilot auth: paste your agency-scoped API key into Swagger Authorize (key only — no fake login page). It cannot access another agency and is never the SEO Ops admin key.

Add the GSC service account

In Search Console → property → Settings → Users and permissions → Add user. Permission: Full (Owner not required).

gsc-analyzer-sa@kite-479022.iam.gserviceaccount.com

Paste what you see in the GSC property switcher — you do not need the sc-domain: prefix. The API normalizes bare domains.

What GSC showsSend / pasteStored as
Domain icon + example.com example.com sc-domain:example.com
URL-prefix https://www.example.com/ Same (trailing / ensured)

Open docs & Authorize

Base URL: https://api.seo-ops.com (fallback: the Cloud Run *.run.app host).

  1. Open /docs
  2. Click Authorize
  3. Paste your API key only — Swagger adds Bearer
  4. Try GET /v1/properties — expect 200

Full markdown runbook: docs/agency-onboarding.md in the repo (same steps, more curl detail).

Create a property

POST /v1/properties — save the returned id.

# Replace YOUR_KEY and site_url
curl -sS -X POST "https://api.seo-ops.com/v1/properties" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "site_url": "https://www.example.com/",
    "label": "Example Client",
    "active": true,
    "days": 90,
    "rows": 500
  }'

Recipients & optional webhook

Add digest emails (as many as you need):

curl -sS -X POST "https://api.seo-ops.com/v1/properties/prop_YOUR_ID/recipients" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "client@example.com"}'

Optional: set webhook_url on the property for run-complete POSTs. ContentEngine / PM poll of work items can wait until week two.

First run — promote smoke or live

Smoke (no GSC): POST /v1/properties/{id}/promote with a small fixture opportunities payload — proves auth, items, and delivery.

Live: POST /v1/properties/{id}/runs — GSC → Claude → work items (sync; wait for the response).

curl -sS -X POST "https://api.seo-ops.com/v1/properties/prop_YOUR_ID/runs" \
  -H "Authorization: Bearer YOUR_KEY"

Then list and update items:

GET  /v1/properties/{id}/items?status=backlog
PATCH /v1/items/{item_id}  →  {"status": "in_progress"}
backlog in_progress done ignored

Digests send after successful runs when recipients exist. Stuck? Reply to Ryan with property id, exact site_url, and error body (redact the key).