API
Recipes
Complete examples: sync rankings to a warehouse, publish on a schedule, build a client dashboard.
List clients, then pull rankings for each
Node: nightly ranking sync
const BASE = process.env.AISOIQ_API_BASE;
const KEY = process.env.AISOIQ_API_KEY;
async function get(params) {
const res = await fetch(`${BASE}?${new URLSearchParams(params)}`, {
headers: { Authorization: `Bearer ${KEY}` },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return res.json();
}
async function allRows(resource, clientId) {
const rows = [];
let offset = 0;
for (;;) {
const page = await get({ resource, client_id: clientId, limit: 1000, offset });
rows.push(...page.data);
if (!page.pagination?.has_more) return rows;
offset += 1000;
}
}
const { data: clients } = await get({ resource: 'clients' });
for (const client of clients) {
const keywords = await allRows('keywords', client.id);
console.log(client.name, keywords.length);
// upsert into your warehouse here
}Generate and queue an article
Node: one article per keyword
async function action(body) {
const res = await fetch(BASE, {
method: 'POST',
headers: {
Authorization: `Bearer ${KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
const json = await res.json();
if (!res.ok || json.status !== 'success') {
throw new Error(json.error ?? `Action failed: ${res.status}`);
}
return json.data;
}
const keywords = ['tankless water heater repair austin', 'water softener install austin'];
for (const keyword of keywords) {
const article = await action({ action: 'generate_blog', client_id: CLIENT_ID, keyword });
console.log('drafted', article.id);
// drafts wait in the review queue, nothing is published here
}Read before you write
Build the read half of an integration first with a read-only key. Once the data shape is familiar, add a separate write key for the actions you actually need.
A small client dashboard
One snapshot per client
const [keywords, tasks, metrics, calls] = await Promise.all([
get({ resource: 'keywords', client_id: CLIENT_ID, limit: 1000 }),
get({ resource: 'seo_tasks', client_id: CLIENT_ID, filter_field: 'status', filter_value: 'pending' }),
get({ resource: 'domain_metrics', client_id: CLIENT_ID, limit: 1 }),
get({ resource: 'call_scores', client_id: CLIENT_ID, filter_field: 'lead_grade', filter_value: 'A' }),
]);
const snapshot = {
topTen: keywords.data.filter((k) => k.position && k.position <= 10).length,
openTasks: tasks.pagination.total,
domainAuthority: metrics.data[0]?.domain_authority ?? null,
gradeALeads: calls.pagination.total,
};