Seni SEO Agent
Ask an SEO question; Seni calls Seonio's data tools and answers.
curl -X POST https://seonio.com/api/v1/seni/chat \ -H "Content-Type: application/json" \ -H "X-API-Key: $SEONIO_API_KEY" \ -d '{"message": "What is the search intent of these keywords: standing desk, best standing desk, standing desk benefits, buy standing desk, standing desk vs sitting, flexispot standing desk?"}'
{
"conversation_id": "01a15f2c-8d41-7b3e-9c52-4e7f0a6b1d93",
"status": "done",
"answer": "Most of these are **commercial or transactional**: people are close to buying a desk.\n\n| Keyword | Intent |\n|---|---|\n| standing desk | commercial |\n| best standing desk | commercial |\n| standing desk benefits | informational |\n| buy standing desk | transactional |\n| standing desk vs sitting | informational |\n| flexispot standing desk | navigational |\n\nFor a store, target *buy standing desk* and *best standing desk* with product and comparison pages; answer *benefits* and *vs sitting* in a guide that links to them.",
"error": null,
"tools": [
{
"name": "keywords_intent",
"args": {
"keywords": [
"standing desk",
"best standing desk",
"standing desk benefits",
"buy standing desk",
"standing desk vs sitting",
"flexispot standing desk"
]
},
"ok": true,
"cost_usd": 0.006
}
],
"usage": {
"input_tokens": 9412,
"output_tokens": 1187
},
"cost": {
"model_usd": 0.013,
"tools_usd": 0.006,
"total_usd": 0.019
}
}What to send and what comes back
Seni, Seonio's SEO agent, answers an SEO question in Markdown by calling Seonio's data tools itself (keyword metrics, Google results, traffic, rankings, backlinks, page audits). One call is one message and a new conversation, saved to your Seni chats on seonio.com, where you can continue it; put everything Seni needs in the message. The answer comes back whole, usually in 10 to 40 seconds (at most about 90). Price: $1 per million input tokens and $3 per million output tokens for the model, plus each data tool it calls at its normal price; at most $0.20 model + $0.50 data per message. You pay what is used: the model part settles to the tokens of this message, and each data tool call is its own charge, listed in `tools`. A message that cannot start is refused before anything is charged: 402 (balance), 403 (account), 422 (empty, over 4,000 characters, or a field other than message), 429 (rate limit, with Retry-After), 503 (unavailable); "detail" says why (a string; an object for 402, a list for a malformed request's 422). Once it ran, the answer is a 200, also when Seni could not answer: then `status` is "failed", the model part was not charged, and data tools that ran stay charged.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
message |
string | required | The question, 1 to 4,000 characters. |
Response
| Field | Type | Description |
|---|---|---|
conversation_id |
string | The new conversation this message started (in your Seni chats on seonio.com). |
status |
string | "done", "failed" (no answer: the model part was not charged) or "interrupted". |
answer |
string | The answer in Markdown (empty when failed). An answer cut by the time limit ends with a note saying it may be incomplete. |
error |
string | Why there is no answer, else null. |
tools |
array | The data tools Seni called, in order: each {"name", "args", "ok", "cost_usd"}; a call that failed is free. |
usage |
object | The model's tokens for this message: input_tokens, output_tokens (reasoning included); both null when the model did not report them (then the model part was free). |
cost |
object | What this message cost in US dollars: model_usd, tools_usd, total_usd. |
Copy, paste, add your key
The same request in cURL, Python and Node.js.
curl -X POST https://seonio.com/api/v1/seni/chat \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"message": "What is the search intent of these keywords: standing desk, best standing desk, standing desk benefits, buy standing desk, standing desk vs sitting, flexispot standing desk?"}'
import requests
resp = requests.post(
"https://seonio.com/api/v1/seni/chat",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"message": "What is the search intent of these keywords: standing desk, best standing desk, standing desk benefits, buy standing desk, standing desk vs sitting, flexispot standing desk?"},
)
print(resp.json())
const resp = await fetch("https://seonio.com/api/v1/seni/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({"message": "What is the search intent of these keywords: standing desk, best standing desk, standing desk benefits, buy standing desk, standing desk vs sitting, flexispot standing desk?"}),
});
console.log(await resp.json());
Run a real request
Send this request from your browser with your API key, or leave the key empty to see the sample response.
A successful run costs $1 / M input tokens + $3 / M output tokens + data tools. With no key, you see the sample response and nothing is charged.
{
"answer": "Most of these are **commercial or transactional**: people are close to buying a desk.\n\n| Keyword | Intent |\n|---|---|\n| standing desk | commercial |\n| best standing desk | commercial |\n| standing desk benefits | informational |\n| buy standing desk | transactional |\n| standing desk vs sitting | informational |\n| flexispot standing desk | navigational |\n\nFor a store, target *buy standing desk* and *best standing desk* with product and comparison pages; answer *benefits* and *vs sitting* in a guide that links to them.",
"conversation_id": "01a15f2c-8d41-7b3e-9c52-4e7f0a6b1d93",
"cost": {
"model_usd": 0.013,
"tools_usd": 0.006,
"total_usd": 0.019
},
"error": null,
"status": "done",
"tools": [
{
"args": {
"keywords": [
"standing desk",
"best standing desk",
"standing desk benefits",
"buy standing desk",
"standing desk vs sitting",
"flexispot standing desk"
]
},
"cost_usd": 0.006,
"name": "keywords_intent",
"ok": true
}
],
"usage": {
"input_tokens": 9412,
"output_tokens": 1187
}
}
What developers build with it
- SEO answers in your own app or chatbot, backed by real data.
- Agents that hand a whole SEO question to Seni instead of picking tools.
The same contract on every endpoint
Error responses are JSON with a "detail" field. It is a message string unless the row above says otherwise.
| Code | When |
|---|---|
200 | Success. The lookup completed and was charged, even if the response is empty. /keywords/global charges only the keywords it looked up. |
401 | Missing or unknown API key. |
402 | Not enough balance. "detail" is an object with "error", "message", "balance_required" and "balance_available". Requests still running hold their price until they finish, so a retry can succeed once they do. |
403 | The account is not verified yet, or it is locked. |
422 | Invalid request (wrong shape or types, a keyword over 200 characters, a URL the page checker cannot audit, a domain that does not exist, or a bare public suffix such as co.uk that groups many websites) — never charged. "detail" is usually a list of validation errors; an answer that retrying cannot change (such as a domain without a DNS record) is a message string with an X-Outcome header naming it: missing, unsupported, too_large or refused_input. |
429 | Rate limit exceeded, never charged. Requests per second per account by plan: 5 on a free account, 10 on Starter, 15 on Pro and 20 on Business; retry after the Retry-After header. Also the page checker's provider limit. |
503 | A data provider failed or timed out (X-Outcome: temporary). Nothing was charged; retry after the seconds in the Retry-After header. |
Questions, answered
Simple answers for developers using the API.
Every endpoint has a published USD price or formula. Requests draw from the same testing, included and Extra Usage balance as website and MCP actions: testing first, then included usage, then Extra Usage expiring soonest.
API actions require a verified account with a free $1 balance or an active subscription balance. Create and manage API keys from your account, then send the key in the X-API-Key header.
Yes. Your account shows API usage and remaining balance, so you can track costs while building and running automated workflows.
REST API and MCP requests per second depend on your plan: 5 on a free account, 10 on Starter, 15 on Pro and 20 on Business. Website data requests from the same account count toward the same second. Requests above the limit return HTTP 429 with a Retry-After header and are not charged; wait a second and retry.
Turn search insights into measurable growth
Start your SEO research in seconds.