SeoPrimo inside your tools.
A REST API with a public OpenAPI spec, an MCP server for Claude, Cursor and n8n, signed webhooks and three n8n workflows to download. The same functions as the panel, with the same credits.
Four doors,
one engine.
Public /api/v1 API
- Sites, audits, keywords, rankings, backlinks, Score, reports
- Examples in curl, Python and JavaScript
- Uniform errors and dry_run for the price
MCP server for agents
- 11 ready tools for Claude, Cursor and n8n
- Streamable HTTP, no sessions
- Same key and credits as the API
n8n workflows
- HTTP Request node, MCP Client node or Webhook
- Three JSON workflows to download
- Credentials by name, no secrets in the file
Outgoing events
- audit.completed, score.changed, rank.changed
- report.ready, credits.low, agent.completed
- HMAC-SHA256 signature and retries with growing delays
From the key to your first call.
- Create a key. In the panel open seoprimo.it/app/integrations/keys (Integrations, API keys), pick a name and the scopes:
readto read,writeto start operations and add sites. For normal use you need both. The key looks likesp_live_…and is shown only once: copy it right away. We only store its hash. - Make your first call. The credit balance is free and proves the key works.
- Ask for the price before spending. Add
?dry_run=trueto any POST: the answer is the estimate, nothing runs and nothing is charged.
export SEOPRIMO_KEY="sp_live_..."
# 1. your credit balance (free)
curl -sS https://seoprimo.it/api/v1/credits \
-H "Authorization: Bearer $SEOPRIMO_KEY"
# 2. the price of a quick audit, without running it
curl -sS -X POST "https://seoprimo.it/api/v1/sites/<site_id>/audits?dry_run=true" \
-H "Authorization: Bearer $SEOPRIMO_KEY"
# {"estimated_credits": 10}
import os
import httpx
api = httpx.Client(
base_url="https://seoprimo.it/api/v1",
headers={"Authorization": f"Bearer {os.environ['SEOPRIMO_KEY']}"},
timeout=30,
)
print(api.get("/credits").json())
# the price of a quick audit, without running it
print(api.post("/sites/<site_id>/audits", params={"dry_run": "true"}).json())
# {'estimated_credits': 10}
// Node 18+ (global fetch)
const headers = { Authorization: `Bearer ${process.env.SEOPRIMO_KEY}` };
const API = "https://seoprimo.it/api/v1";
console.log(await (await fetch(`${API}/credits`, { headers })).json());
// the price of a quick audit, without running it
const dry = await fetch(`${API}/sites/<site_id>/audits?dry_run=true`, { method: "POST", headers });
console.log(await dry.json()); // { estimated_credits: 10 }
The whole path (site, quick audit, waiting for the result, Score) is in the API guide.
Credits, limits and security.
- The same credits as the panel. Paid calls spend your account's credits; without credits the answer is
402withneededandavailable. Failed jobs give the credits back. - 60 requests per minute per key, shared between the REST API and MCP. Above the limit the answer is
429with aRetry-Afterheader. - Up to 20 active keys per account and 10 webhooks. Keys and webhooks are managed from the panel (owner or administrator) and revoked with one click.
- A key only sees its own account. A site of another account answers
404, as if it did not exist. - HTTPS only. The key travels in the
Authorizationheader, never in the URL. Keep it in environment variables or a secrets manager, not in your code.
For an agent that only needs to read, create a key with the read scope only: it can neither add sites nor spend credits.
Interactive documentation.
The API is described by a public OpenAPI 3.1 spec: you can read it, import it into Postman, Insomnia or a client generator, or try the calls in the browser.
- /api/v1/docs: Swagger UI, with "Authorize" to enter the key and "Try it out" on every endpoint
- /api/v1/redoc: the same documentation in ReDoc, for reading
- /api/v1/openapi.json: the OpenAPI spec in JSON
Swagger UI and ReDoc load their files from a CDN: the documentation needs internet in your browser, the API does not.
Create the key.
The rest is code.
Keys are created from the panel, under Integrations. If you do not have an account yet, write to us.