TypeScript SDK
The @misar/seo TypeScript client — a typed wrapper over every api.misar.io/seo endpoint.
@misar/seo is the official TypeScript client. It wraps every api.misar.io/seo/* endpoint behind typed resource namespaces so you are not hand-building URLs and headers.
Private registry
@misar/seo is published to the Misar package registry, not public npm. Scope the @misar org to it in your .npmrc before installing.
Install
@misar:registry=https://git.misar.io/api/packages/misaradmin/npm/
//git.misar.io/api/packages/misaradmin/npm/:_authToken=${NPM_TOKEN}pnpm add @misar/seonpm install @misar/seoyarn add @misar/seoCreate a client
import { MisarSeoClient } from "@misar/seo";
export const seo = new MisarSeoClient({
apiKey: process.env.MISARSEO_API_KEY!,
// baseUrl defaults to https://api.misar.io/seo
});Prop
Type
Create a key from your MisarSEO account — see Authentication.
Resource namespaces
The client exposes one namespace per API area.
| Namespace | Covers |
|---|---|
projects | Projects |
crawl | Site audit — start, status, stream |
keywords | Keyword research and saved sets |
rankTracking | Rank tracking — configs, keywords, runs |
domain | Domain overview |
backlinks | Backlinks |
competitors | Competitors |
local | Local SEO |
gsc | Google Search Console |
aiSearch | AI search — brand radar and prompt explorer |
account | Account export and deletion |
Example
import { seo } from "./client";
// Projects
const { projects } = await seo.projects.list();
const projectId = projects[0].id;
// Kick off a crawl
const { jobId } = await seo.crawl.start({
projectId,
startUrl: "https://acme.com",
maxPages: 500,
});
// Poll until it finishes
let status;
do {
await new Promise((r) => setTimeout(r, 5000));
status = await seo.crawl.status(jobId, { projectId });
} while (status.status !== "done" && status.status !== "failed");
// Keyword research
const research = await seo.keywords.research({
projectId,
keywords: ["seo audit tool", "rank tracker"],
locationCode: 2840,
languageCode: "en",
});Error handling
The client surfaces the API's error contract — branch on code, never on the message.
try {
await seo.backlinks.overview({ projectId, target: "acme.com" });
} catch (err: any) {
switch (err.code) {
case "SEO_DATA_UNAVAILABLE":
// No honest data source in this deployment's data mode — degrade the feature.
break;
case "BACKLINKS_NOT_ENABLED":
// Prompt an upgrade.
break;
case "RATE_LIMITED":
// Honour err.retryAfter.
break;
default:
throw err;
}
}See Errors for the full code table and Rate limits for the per-route budgets.
When not to use the SDK
Driving MisarSEO from an AI assistant?
Use the MCP server instead. It exposes the same capabilities as tools an assistant can call directly, with no client code to write.