Your first API request
Create a key, list your domains and read your visibility, in curl, Python or Node.
YOUR_API_KEY with a key from Settings → API and MCP. Keys are shown once when you create them.What you'll learn
- How to create and send an API key
- How to find a domain and read its metrics
- How to read a rate, its sample size and its 95% range
Want to try before creating a key? Every page in the API reference has a Try it panel that runs real requests, against the demo workspace or, once you sign in, your own data.
1. Create a key
In the dashboard, open Settings → API and MCP and create a key. You need the admin role. Choose read unless you'll add prompts through the API. Onym shows the key once; it starts with onym_. Keys made before October 2026 start with nod_ and keep working.
Keys belong to the workspace, so one key reads every domain in it. Keep keys on your server. Don't put them in front-end code or commit them.
2. List your domains
curl https://getonym.com/api/v1/domains \
-H "Authorization: Bearer YOUR_API_KEY"import requests
API = "https://getonym.com/api/v1"
H = {"Authorization": "Bearer YOUR_API_KEY"}
domains = requests.get(f"{API}/domains", headers=H).json()["domains"]
print([d["host"] for d in domains])const API = "https://getonym.com/api/v1";
const H = { Authorization: "Bearer YOUR_API_KEY" };
const { domains } = await (await fetch(`${API}/domains`, { headers: H })).json();
console.log(domains.map((d) => d.host));Every endpoint takes a domain's host or its id. Save one for the next step.
3. Read its metrics
curl -G https://getonym.com/api/v1/domains/acme.example/metrics \
-H "Authorization: Bearer YOUR_API_KEY" \
-d range=30dm = requests.get(f"{API}/domains/acme.example/metrics", headers=H, params={"range": "30d"}).json()
vis = m["kpis"]["visibility"]
print(f"Named in {vis['k']} of {vis['n']} answers: {vis['rate']:.0%} "
f"(95% range {vis['low']:.0%} to {vis['high']:.0%})")const m = await (await fetch(`${API}/domains/acme.example/metrics?range=30d`, { headers: H })).json();
const v = m.kpis.visibility;
console.log(`Named in ${v.k} of ${v.n} answers (${Math.round(v.rate * 100)}%)`);The response looks like this, shortened:
{
"domain": "acme.example",
"filters": { "range": "30d", "surface": null, "topic": null, "branded": "unbranded" },
"kpis": {
"visibility": {
"k": 167, "n": 444, "rate": 0.376, "low": 0.332, "high": 0.422,
"change": { "delta": 0.194, "significant": true, "direction": "up", "pairs": 111 }
},
"answers": 444, "prompts": 19, "runs": 4
}
}kandnare the counts: 167 of 444 answers named the brand.rateisk / n, from 0 to 1.lowandhighare the 95% range.change.significantis true only when this period's range and the previous one don't overlap.
4. Narrow it down
Every analytics endpoint takes the same filters: range, surface, topic and branded. For example, surface=chatgpt_app:chat counts only ChatGPT. The response lists the surfaces and topics you can pass.