SV APIDeveloper Referencev1
All systems operational
Command-line client

SV CLI

An open-source command-line client for agentic SEO and GEO workflows. Humans use friendly commands and aliases; scripts and AI agents use strict enum IDs and raw JSON. All 16 SV API endpoints available from your terminal.

pip
install sv-cli
sv
Executable name
16
API tools covered
MIT
License

01Install

Python 3.9+ required. Install from PyPI with pip. The executable is sv. No other dependencies needed for basic use.
$ install
pip install sv-cli

# Local dev setup
git clone https://github.com/seovendorco/sv-cli.git
cd sv-cli
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e '.[dev]'
sv --help

02API key setup

Keep your key secret. Send requests from your server, never from client-side code. Avoid --api-key in shared shells — shell history may store the value. Debug output automatically masks keys.

Config is stored in ~/.sv/config.json. The legacy path ~/.seovendor/config.json is still read as a migration fallback. New saves always go to ~/.sv.

Multi-agency profiles

Each profile stores a separate API key. Switch between agency accounts with a single flag.

$ profiles
sv profile create agency-a
sv --profile agency-a auth set
sv profile use agency-a
sv profile list
sv profile delete agency-a
$ auth
# Recommended: store once, use everywhere
sv auth set
sv auth status

# Or set the environment variable (preferred for CI and agents)
export SV_API_KEY="your-key-here"

# CI / non-interactive
sv seogpt generate --type 18 --keyword "white label seo" \
  --strict --format json --non-interactive

# Key resolution order:
# 1. --api-key flag (avoid in shared shells — history may store it)
# 2. SV_API_KEY environment variable
# 3. Stored profile: sv auth set
# 4. Interactive prompt (when allowed)
# Legacy: SEOVENDOR_API_KEY still accepted

03Quick start

Every API tool is available as a CLI command. These examples cover the most common operations across all 16 endpoints. Common enum IDs: seogpt --type 18 = Meta Description, --type 8 = Page Title, seo-image --type 33 = Blog Header Image, seogpt2 --type 0 = On-Page Blog Article. Always verify with sv options TOOL type before use.

$ sv <tool> <action>
# Keyword research
sv keywords research --keyword "white label seo"

# Generate a meta description (type 18)
sv meta --keyword "white label seo" --url https://seovendor.co

# Generate a title (type 8)
sv title --keyword "white label seo" --url https://seovendor.co

# GEO audit (async — --wait polls until complete)
sv geo-audit create-task \
  --url https://seovendor.co \
  --keyword "seo agency,white label seo" --wait

# Generate an SEO image (type 33 = Blog Header Image)
sv image generate --keyword "white label seo" --type 33

# Top 10 competing URLs for a keyword
sv top-competitors analyze --keyword "white label seo"

# Search marketplace services
sv marketplace-services search \
  --search "seo audit" --price 500 --category SEO

# Content quality check (HCU / E-E-A-T)
sv content-quality analyze \
  --keyword "white label seo" --url https://seovendor.co

04Tool reference

Every SV API endpoint maps to a CLI command. Use exact command names in scripts — aliases are human shortcuts only. Async tools return a task_id; use --wait or poll manually.

sv commandAliasesDefault actionRequired flagsAll actionsAPI page
seogpt
seo-gpt
generate --keyword --typegenerate, rawseogpt
seogpt2
seo-gpt2
create-task async--keyword (=Topic)create-task, get-task-status, get-result, rawseogpt2
content-transformer
transform
rewrite --textrewrite, rawcontent-transformer
seo-image
image
generate --keywordgenerate, rawseo-image
better-keywords
keywords
research --keywordresearch, filter, rawbetter-keywords
insight-igniter
insights
entities --urlentities, rawinsight-igniter
topical-authority
topical
topics --keywordtopics, content, rawtopical-authority
core-analysis
core
analyze (none)analyze, rawcore-analysis
preliminary-audit
prelim-audit
analyze --urlanalyze, rawpreliminaryaudit
geo-audit
geogpt-auditaudit
create-task async--url --keywordcreate-task, get-task-status, get-result, rawgeogptaudit
seogpt-compare
compare
create-task async--url --keywordcreate-task, get-task-status, get-result, rawseogptcompare
seo-mapping
mapping
create-task async--url --keywordcreate-task, get-task-status, get-result, rawseogptmapping
ranklensrank --keyword --urlrank, competitors, rawranklens
content-quality
qualityhcu-qualityeeat-quality
analyze --keyword --urlanalyze, rawcontent-quality
top-competitors
competitors
analyze --keywordanalyze, rawtop-competitors
marketplace-services
marketplaceservices
search --searchsearch, rawmarketplace-services

05Enum resolution

Always discover before calling. Never guess enum values for --type, --language, --engine, --theme, etc. Run sv options TOOL FIELD first. In agent/script context use --strict --no-fuzzy to require exact ID or slug and prevent unintended matches.

Discovery commands

$ discover options
# Discover all option fields for a tool
sv options seogpt

# List all values for a specific field
sv options seogpt type

# Filter by keyword
sv options seogpt type --search meta

# Tool-specific shorthand (where available)
sv seogpt types
sv seogpt types --search meta
sv seogpt languages
sv seogpt engines
sv image types
sv image themes --search wild
sv seogpt2 types
sv seogpt2 lengths
sv seogpt2 tones
sv seogpt2 engines
sv geo-audit languages
sv ranklens engines
sv topical-authority modes
sv marketplace-services series
sv marketplace-services categories

Resolution & agent-safe mode

$ resolve & strict mode
# All of these resolve to Meta Description (id 18):
sv seogpt generate --type 18
sv seogpt generate --type meta-description
sv seogpt generate --type "Meta Description"
sv seogpt generate --type "meta desc"

# Options output columns — use id or slug with --strict:
# label             slug              id
# ----------------  ----------------  ---
# Meta Description  meta-description  18
# Meta Keywords     meta-keywords     180

# Agent-safe: require exact ID or slug, no guessing
sv seogpt generate \
  --type 18 \
  --keyword "white label seo" \
  --strict --no-fuzzy --non-interactive --format json

06Async tasks

Four tools run as background tasks: GEO Audit, SEO GPT 2, SEO Strategist, and SEO Mapping. Use --wait for the simplest flow; poll manually for long-running jobs or when you need to store the task_id between steps.

Pattern 1 — --wait (simplest)

$ --wait
# --wait polls automatically (default timeout 600s)
sv geo-audit create-task \
  --url https://seovendor.co \
  --keyword "seo agency,white label seo" \
  --wait --strict --no-fuzzy --non-interactive --format json

# Override timeout and poll interval
sv seogpt2 create-task \
  --keyword "White Label SEO for Agencies" --type 0 \
  --wait --timeout 300 --poll-interval 10 \
  --strict --no-fuzzy --non-interactive --format json

Pattern 2 — Manual 3-step poll

$ manual poll
# Step 1 — create task
sv geo-audit create-task \
  --url https://seovendor.co --keyword "seo agency" \
  --non-interactive --format json
# → parse: response["data"]["task_id"]

# Step 2 — poll status (repeat until done)
sv --format json task status TASK_ID --tool geo-audit
# done when: status is "done|complete|completed|success|finished|ready"

# Step 3 — get result
sv --format json task result TASK_ID --tool geo-audit

# Direct tool polling (same result)
sv geo-audit get-task-status --task_id TASK_ID --format json
sv geo-audit get-result --task_id TASK_ID --format json

# --tool required if task not created in current session
# (not found in ~/.sv/tasks.json)

07Response shapes

All responses use the standard envelope (success, application, action, data, meta, error). The data field shape varies by endpoint type.

ShapeReturned byParse
Contentseogpt generate, content-transformer rewrite, sv meta, sv titleresponse["data"]["text"]
Listbetter-keywords research, top-competitors analyze, marketplace-services search, topical-authority topicsresponse["data"] — array of objects
Async createdgeo-audit create-task, seogpt2 create-task, seogpt-compare create-task, seo-mapping create-taskresponse["data"]["task_id"]
Task statusany get-task-statusresponse["data"]["status"]
Audit / analysiscore-analysis, preliminary-audit, content-quality, ranklensresponse["data"] — nested object
data shapes
// Content
{ "data": { "text": "generated content here" } }

// List
{ "data": [ { "keyword": "...", "volume": 1000 }, ... ] }

// Async task created
{ "data": { "task_id": "wFEGe...", "status": "pending",
            "stage": "queued", "percent_complete": 1 } }

// Task status
{ "data": { "task_id": "...", "status": "processing",
             "percent_complete": 75 } }

// Done when status is one of:
// "done" | "complete" | "completed" | "success" | "finished" | "ready"

// Audit / analysis
{ "data": { ... nested analysis object ... } }

08Critical field exceptions

A handful of fields do not map to standard CLI flags. Get these wrong and the call fails silently or returns unexpected results.

seogpt2 — --keyword maps to Topic, not kw

seogpt2’s required field is Topic (an article title or subject). The CLI maps --keyword to Topic internally — no other flag does this.

seogpt — --contenttype is an alias for --type

Both flags select the content type integer. Use whichever is clearer; --type 18 and --contenttype meta-description are equivalent.

$ field mapping
# CORRECT — --keyword sends value as the "Topic" API field
sv seogpt2 create-task \
  --keyword "White Label SEO for Agencies" \
  --type 0 --wait \
  --strict --no-fuzzy --non-interactive --format json

# --contenttype is an alias for --type on seogpt
sv seogpt generate \
  --keyword "white label seo" \
  --contenttype meta-description \
  --strict --no-fuzzy --non-interactive --format json

better-keywords filter — requires data array

The filter action AI-filters a keyword list for relevance. No CLI flag maps to the data field — you must pass the keyword array from a prior research call via a raw JSON call.

$ better-keywords filter
# better-keywords filter requires a data array from a prior research call.
# No CLI flag maps to data — must use a raw call.

# Step 1 — research to get keyword array
sv keywords research --keyword "white label seo" \
  --non-interactive --format json
# → parse response["data"]  (array of keyword objects)

# Step 2 — filter using that array via raw call
sv --format json call better-keywords \
  --json '{"action":"filter","kw":"white label seo","data":[{"keyword":"...","volume":1000}]}'

ranklens competitors — requires mgptid

The competitors action needs the mgptid returned by a prior rank call. No CLI flag exists for this field — use a raw call.

$ ranklens competitors
# ranklens competitors action requires mgptid from a prior rank response.
# No CLI flag maps to mgptid — must use a raw call.

# Step 1 — get MGPTID from rank response
sv ranklens rank --keyword "white label seo" \
  --url https://seovendor.co --format json
# → parse response["data"]["MGPTID"]

# Step 2 — pass MGPTID via raw call
sv --format json call ranklens \
  --json '{"action":"competitors","mgptid":"MGPTID_VALUE","web":"https://seovendor.co","kw":"white label seo"}'

09Output formats

Six output formats. --format placement differs between tool commands and global commands (sv call, sv task, sv TOOL raw) — for those, --format must come before the subcommand.

Response typeRecommended format
list results (keywords, competitors, services)table, csv
content / articles / generated texttext, markdown
audit / analysis / nested datajson, markdown
async task ID responsespretty (default)
any responsejson (always safe)
$ formats
# --format anywhere on tool commands
sv seogpt generate --keyword "white label seo" --type 18 --format json

# --format MUST come BEFORE sv call / sv task / sv TOOL raw
sv --format json call seogpt --json '{"action":"generate","kw":"white label seo","type":18}'
sv --format json task status TASK_ID
sv --format json task result TASK_ID
sv --format json seogpt raw --json '{"action":"generate","kw":"white label seo","type":18}'

# Save output to file
sv keywords research --keyword "white label seo" --format csv --output keywords.csv
sv geo-audit create-task --url https://seovendor.co \
  --keyword "seo agency" --wait --format markdown --output audit.md

10Raw API calls

The call and per-tool raw subcommands pass a JSON payload directly to the API, injecting your key as k automatically. Only the endpoint URL is resolved from definitions; the rest of the payload is passed through unchanged. Use sv definitions show TOOL to inspect all API input fields before building raw payloads.

$ raw calls
# Pass raw JSON directly — API key injected automatically
sv --format json call seogpt \
  --json '{"action":"generate","kw":"white label seo","type":18}'

# From file
sv --format json call seogpt --file payload.json

# From stdin
cat payload.json | sv --format json call seogpt --stdin

# Per-tool raw subcommand (same behavior)
sv --format json seogpt raw \
  --json '{"action":"generate","kw":"white label seo","type":18}'

# Inspect all input fields before building a payload
sv definitions show seogpt

11Common errors

Error messageCauseFix
Could not resolve --type "X" in strict modeValue is not a valid slug or IDRun sv options TOOL type → use the id or slug column
Could not resolve --type "X"No match found at any resolution levelRun sv options TOOL type --search X to find the closest match
Topic is requiredseogpt2 called without --keywordAdd --keyword "your topic title"
task_id is invalidTask has expired on the serverCreate a new task
No local tool mapping found for taskTask not in ~/.sv/tasks.jsonAdd --tool TOOL_NAME explicitly
API authentication failed: HTTP 401Bad or missing API keyCheck SV_API_KEY environment variable
API rate limit exceededToo many requestsWait and retry — add delay between calls
No such option: --format--format placed after call/task/rawMove --format before the subcommand: sv --format json call ...
Action must be rewriteWrong action for content-transformerOnly rewrite is supported
Data must be a JSON arraybetter-keywords filter called without dataPass keyword array from prior research call via raw JSON (see section 08)

12Quick reference

For AI agents and scripts: always include --strict --no-fuzzy --non-interactive --format json. Set SV_API_KEY as an environment variable — never use sv auth set in agent context (it’s interactive). Verify enum IDs with sv options TOOL FIELD before use; the IDs listed here are from the live API at time of writing.
$ one call per tool
# All 16 tools — agent-safe one-liners
# Replace values as needed. Verify enum IDs with sv options first.

sv keywords research --keyword "white label seo" --strict --no-fuzzy --non-interactive --format json
sv --format json call better-keywords --json '{"action":"filter","kw":"white label seo","data":[{"keyword":"white label seo","volume":1000}]}'
sv content-transformer rewrite --text "SEO services for agencies" --keyword "white label seo" --strict --no-fuzzy --non-interactive --format json
sv core-analysis analyze --url https://example.com --keyword "white label seo" --strict --no-fuzzy --non-interactive --format json
sv geo-audit create-task --url https://example.com --keyword "white label seo" --wait --strict --no-fuzzy --non-interactive --format json
sv insight-igniter entities --url https://example.com --keyword "white label seo" --strict --no-fuzzy --non-interactive --format json
sv preliminary-audit analyze --url https://example.com --strict --no-fuzzy --non-interactive --format json
sv ranklens rank --keyword "white label seo" --url https://example.com --strict --no-fuzzy --non-interactive --format json
sv seo-image generate --keyword "white label seo" --type 33 --strict --no-fuzzy --non-interactive --format json
sv seogpt generate --keyword "white label seo" --type 18 --strict --no-fuzzy --non-interactive --format json
sv seogpt2 create-task --keyword "White Label SEO for Agencies" --type 0 --wait --strict --no-fuzzy --non-interactive --format json
sv seogpt-compare create-task --url https://example.com --keyword "white label seo" --wait --strict --no-fuzzy --non-interactive --format json
sv seo-mapping create-task --url https://example.com --keyword "white label seo" --wait --strict --no-fuzzy --non-interactive --format json
sv topical-authority topics --keyword "white label seo" --strict --no-fuzzy --non-interactive --format json
sv top-competitors analyze --keyword "white label seo" --strict --no-fuzzy --non-interactive --format json
sv marketplace-services search --search "seo audit" --category SEO --strict --no-fuzzy --non-interactive --format json
sv content-quality analyze --keyword "white label seo" --url https://example.com --strict --no-fuzzy --non-interactive --format json

13Definitions cache

The CLI discovers available tools from the SV API root and fetches each tool’s definitions endpoint at runtime. Definitions are cached locally at ~/.sv/cache/definitions.json for speed and refreshed automatically after 24 hours.

$ definitions
sv definitions refresh    # re-fetch from live API
sv definitions list       # show all cached tools
sv definitions show seogpt  # inspect a single tool’s full schema
sv definitions clear      # wipe the cache
sv options list           # all tools with option-set counts

# Cache location
~/.sv/cache/definitions.json

# Default behaviour:
# - Use local cache when present
# - Auto-refresh if cache > 24 hours old
# - Use stale cache with warning if refresh fails
# - Error clearly if no cache and API unreachable

# Legacy path still read as fallback
~/.seovendor/config.json  →  migrated to  ~/.sv/config.json
SV API
Base URL https://ai.seovendor.co/api  ·  All requests are POST · JSON in, JSON out · © 2026 SEO Vendor. Built for agencies since 2004.