GEOly Data API
Pull GEOly's raw AI-visibility data over HTTP with an API key. One tool, one endpoint, one synchronous JSON response — the same catalog, parameters, and prices as GEOly MCP, with no agent in between.
The GEOly Data API gives you the raw data behind GEOly: prompts, AI answers, citations, competitors, trends, audits, and (on plans that include it) public industry intelligence. Every GEOly data tool is an HTTP endpoint. You send the tool's arguments as JSON and get the tool's result back as JSON — no model, no agent, no MCP client in between. It is built for your own scripts, BI pipelines, and backends.
The catalog is the same one GEOly MCP serves: identical tool names, parameters, metric definitions, and prices. If you already use GEOly MCP from an AI client, every tool you know works here with the same arguments.
How it relates to the Agent API and MCP
| What runs the reasoning | Best for | |
|---|---|---|
Data API (POST /api/v1/tools/{tool}) | Nobody — you get the raw data | Your own scripts, BI, and backends over plain HTTP |
| GEOly MCP | Your own model or agent, calling the same tools | Claude, Cursor, Codex, and other AI clients |
Agent API (POST /api/v1/agent/runs) | GEOly's hosted GEO agent | A finished, sourced answer to a question |
All three accept the same API keys and work on the same brands, permissions, and credits. The Data API and GEOly MCP charge the same per-call prices; the Agent API charges per run.
Quick start
- In GEOly, go to Settings → Developers → API keys, click Create secret key, pick the brand, and copy the key (it starts with
geom_). - List the tools your key can call:
curl -sS https://app.geoly.ai/api/v1/tools \
-H "Authorization: Bearer geom_…"
- Call one:
curl -sS https://app.geoly.ai/api/v1/tools/get_prompt_list \
-H "Authorization: Bearer geom_…" \
-H "Content-Type: application/json" \
-d '{"page_size": 20, "platform": "chatgpt"}'
The response is { "data": …, "meta": … } where data is the tool's result. Nothing else to set up.
Authentication
Every request carries an API key:
Authorization: Bearer geom_…
Keys are created in GEOly under Settings → Developers → API keys (organization owners and admins only). When you create one you choose:
- The brand. A key is bound to exactly one brand; create one key per brand.
- Permissions, per resource (brand, prompts, citations, competitors, audits, public industry data, …), each None / Read / Write. The tool list you get back (
GET /api/v1/tools) contains only the tools your key is allowed to call. - Expiry: never, or 30, 90, or 365 days.
The full key is shown only once. GEOly stores a hash; if you lose a key, revoke it and create a new one. A key stops working when it is revoked, expires, its brand is deleted, or the person who created it leaves the organization. The same key also works with GEOly MCP and the Agent API.
Keys that are not bound to a brand (older tokens, CLI sign-ins) are not accepted here and return 403 API_KEY_BRAND_REQUIRED.
Endpoints
Base URL: https://app.geoly.ai
| Method and path | Purpose |
|---|---|
GET /api/v1/tools | The tools this key can call: name, description, argument schema, price, timeout |
POST /api/v1/tools/{tool} | Call one tool; the JSON body is its arguments; the result comes back synchronously |
GET /api/v1/openapi.json | An OpenAPI 3.1 document generated from your tool list — feed it to an SDK generator |
Versioning follows the same policy as the Agent API: the version is in the path, each version stays available, and breaking changes only ever ship as a new version. Within v1, new tools, new optional arguments, and new response fields can appear at any time — ignore fields you do not recognize.
List your tools
GET /api/v1/tools
Authorization: Bearer geom_…
{
"data": {
"tools": [
{
"name": "get_prompt_list",
"description": "…what it returns and how to use it…",
"input_schema": { "type": "object", "properties": { "page_size": { "type": "number" }, "…": {} }, "additionalProperties": false },
"cost": { "tier": "standard", "base": 3, "unit": "call" },
"timeout_ms": 45000
}
]
},
"meta": { "request_id": "…", "duration_ms": 120 }
}
input_schemais JSON Schema.additionalProperties: falseis real: unknown arguments are rejected, not ignored.costis the price in credits (see Credits);nullmeans the tool is free.timeout_msis the server-side limit for one call; set your client timeout above it.
The list depends on the key: resources set to None are left out, and public industry tools appear only on plans that include them (Grow and above).
Call a tool
POST /api/v1/tools/get_prompt_list
Authorization: Bearer geom_…
Content-Type: application/json
{ "page_size": 20, "platform": "chatgpt", "time_range": "30d" }
- The body is a JSON object of the tool's arguments, exactly as described by
input_schema. An empty body means "no arguments". - Numeric arguments also accept numeric strings (
"20"), so values from query strings and spreadsheets work unchanged. - You never send
org_idorbrand_id: the key already names them.
A successful call returns 200:
{
"data": {
"_quota": { "cost": 3, "remaining": 2997, "resets_at": "2026-11-01T00:00:00.000Z" },
"prompts": [ … ],
"total": 128
},
"meta": { "request_id": "req_…", "tool": "get_prompt_list", "duration_ms": 812 }
}
data is the tool's raw result — the same object a GEOly MCP client receives. The _quota receipt inside it tells you what the call cost and what is left. Large results are capped at about 60,000 characters; when a result is cut, it says so and names the arguments to narrow (page_size, limit, a platform, a time range).
Errors
Errors are JSON with a machine-readable code:
{
"error": { "code": "QUOTA_EXCEEDED", "message": "…", "details": { } },
"meta": { "request_id": "req_…", "tool": "get_prompt_list" }
}
| HTTP | error.code | Meaning and what to do |
|---|---|---|
| 400 | INVALID_BODY | The body is not a JSON object. |
| 400 | INVALID_ARGUMENT | The arguments do not match input_schema (unknown argument, wrong type, missing required). Not charged. |
| 400 | TOOL_ERROR | The tool rejected the call — an id that is not yours, a missing locale, nothing matching your filters. message explains. Not charged. |
| 401 | UNAUTHORIZED | Missing, invalid, revoked, or expired key, or the key's brand was deleted / its creator left the organization. Create a new key. |
| 402 | SUBSCRIPTION_INACTIVE | The organization has no active subscription. |
| 402 | QUOTA_EXCEEDED | The organization's credits for this period are used up. details has what is left and when it resets. |
| 402 | ORG_NOT_ELIGIBLE | The plan does not include this tool (for example public industry data below Grow). |
| 403 | API_KEY_BRAND_REQUIRED | The credential is not a brand-bound API key. |
| 404 | TOOL_NOT_FOUND | No such tool, or your key cannot call it. Check GET /api/v1/tools. Tool names retired from GEOly MCP are not served here. |
| 410 | TOOL_REMOVED | The tool was retired; message names its replacement. |
| 422 | other codes | The tool refused the call for a reason it explains in message (for example QUERY_TOO_EXPENSIVE: narrow the time range). |
| 429 | RATE_LIMITED | Too many requests per minute for this key. Wait for Retry-After seconds. |
| 429 | BUSY, GUARDED_RATE_LIMITED | Too many calls in flight, or a heavy tool called too often. Wait for Retry-After, or run fewer calls in parallel. |
| 503 | TOOL_TIMEOUT, OVERLOADED, CIRCUIT_OPEN, TOOL_FAILED | Not charged; retry after Retry-After when present. TOOL_TIMEOUT means the tool did not finish within timeout_ms — error.message / error.details say what to narrow. (502 and 504 are never used.) |
Match on error.code; show error.message to a person. meta.request_id identifies the call if you need to ask about it.
Credits
Data API calls draw on your organization's MCP credits — the same pool, prices, and receipts as GEOly MCP.
- Each tool has a fixed price per call (
cost.basein the tool list: light 1, standard 3, deep 10 credits). Some tools price by the amount returned;costsays which. - Navigation tools are free:
get_quota,get_brand_context,get_topic_list,get_current_date, and others whosecostisnull. So are audits, your own GA4 / Cloudflare traffic data, and the source overview tools. - Calls rejected before running (
INVALID_ARGUMENT,TOOL_ERROR) and calls that fail with503(timeout, overload, breaker, read failure) are not charged. POST /api/v1/tools/get_quotareturns what is left at any time; every charged result carries_quotaas well.
Rate limits and timeouts
- Each key has a per-minute request limit shared with GEOly MCP, and a limit on calls in flight at the same time. Over either you get
429withRetry-After. - Heavy tools are capped per organization per minute (
GUARDED_RATE_LIMITED). - One call runs for at most
timeout_ms(20–45 seconds depending on the tool). Set your HTTP client timeout to at least 60 seconds.
Example: Python
import os
import requests
API = "https://app.geoly.ai/api/v1/tools"
HEADERS = {"Authorization": f"Bearer {os.environ['GEOLY_API_KEY']}"}
def call(tool: str, **args):
r = requests.post(f"{API}/{tool}", json=args, headers=HEADERS, timeout=90)
body = r.json()
if r.status_code != 200:
err = body["error"]
raise RuntimeError(f"{tool}: {err['code']} — {err['message']}")
return body["data"]
overview = call("get_brand_overview", time_range="30d")
prompts = call("get_prompt_list", page_size=50, platform="chatgpt")
print(overview["_quota"], len(prompts["prompts"]))
Example: generate a client from OpenAPI
curl -sS https://app.geoly.ai/api/v1/openapi.json \
-H "Authorization: Bearer geom_…" > geoly-openapi.json
npx openapi-typescript geoly-openapi.json -o geoly.d.ts
The document is generated from your tool list, so it only contains tools your key can call. Each operation carries x-geoly-cost and x-geoly-timeout-ms.
Integration tips
- One key per brand and per system, with only the permissions it needs; keep it in a secret manager and revoke it when the system is retired.
- Start from the tool list. Read
input_schemaandcostbefore wiring a tool into a job; the description says what each view returns. - Narrow before you page. Filters (platform, topic, time range) are cheaper and faster than paging through everything.
- Respect
Retry-Afteron429and503; do not retry400responses without changing the request. A503 TOOL_TIMEOUTusually means the query is too wide — narrow it before retrying. - Read
_quotaand alert before the organization runs out of credits. - Ignore unknown fields so that additive changes within v1 never break your parser.
Limits and boundaries
- Scope follows the key. A key reaches exactly one brand in one organization, with the permissions chosen when it was created.
- Write tools (creating prompts, topics, competitors, tagging, archiving, running monitoring on demand) are available only when the key has Write on that resource. Running monitoring on demand (
trigger_prompt) charges monitoring credits, as it does over MCP. - Plans. An active subscription is required. Public industry tools need Grow and above.
- Synchronous only. Every call returns within
timeout_ms; there are no background jobs or webhooks. - Metric definitions (mention rate, citation rate, AIGVR, Share of Model) are the same as in the GEOly app and in GEOly MCP; see the GEOly MCP User Guide for how each tool defines them.
Related
- GEOly MCP User Guide — the same tools from Claude, Cursor, Codex, and other AI clients.
- GEOly Agent API — ask a question and get a finished answer instead of raw data.
- GEOly CLI —
geoly callruns these same tools from a terminal.
GEOLY Docs