@linkeq/sdk
v0.6.0
Published
Minimal TypeScript client for the LinkEQ API
Readme
LinkEQ SDK
TypeScript client for the LinkEQ API. Fewer tokens than raw HTTP for agents.
npm i @linkeq/sdkDefault base URL: https://api.linkeq.co
Override for local: new LinkEQ({baseUrl: 'http://127.0.0.1:8787'})
Auth
All authenticated calls use Authorization: Bearer lq_….
API key (steady state)
- Copy
lq_…from the LinkEQ landing page - Set
LINKEQ_API_KEYor passapiKeyto the constructor
import {LinkEQ} from '@linkeq/sdk'
const linkeq = new LinkEQ() // uses LINKEQ_API_KEYOTP bootstrap (first-time / agent)
When the human only has email access:
const linkeq = new LinkEQ()
await linkeq.auth.otp('[email protected]')
const {api_key} = await linkeq.auth.verify('[email protected]', '123456')
// save api_key → LINKEQ_API_KEY for next runsverify returns the key once and stores it on the client. No device-code flow.
SDK surface
| | |
|---|---|
| auth.otp(email) | send 6-digit code |
| auth.verify(email, code) | → api_key |
| accounts.me() | current account |
| accounts.regen() | rotate key |
| sites.create({domain, verifiedMethod, includePaths?, excludePaths?}) | register site (dns | file) |
| sites.verify(id) / sites.list() / sites.get(id) | verify & read (status is a string) |
| sites.pages(id) / sites.ingest(id, url) / sites.unindex(id, url) | page inventory |
| sites.update(id, {includePaths?, excludePaths?, status?}) | pause (inactive) or crawl paths |
| sites.recrawl(id) / sites.delete(id) | recrawl / remove |
| sites.internalLinks(id, {url?, urls?, limit?, direction?}) | main helper — url or urls (max 50). Prefer urls → {ready, pages:[{source_url\|target_url, ready, links}]}. Single url → {ready, links: [{source_url, target_url, suggested_anchor, relevance}]}. direction: 'inbound' = who should link here; ready: false (202) if embeddings not ready |
| matches.list(siteId, {url?, min_relevance?, limit?, category?, min_dr?, language?}) | partners; url → partner pages |
| exchanges.create({requester_site_id, target_site_id, mode?, requester_url?, target_url?}) | reciprocal only; 400 if pair already open |
| exchanges.list({status?, site_id?, role?}) / get(id) / accept(id) / reject(id) | manage (cancelled is a status) |
| exchanges.cancel(id) | requester, pending → cancelled |
| exchanges.placement(id) | HTML/anchor for your side |
| exchanges.verify(id, placement_url) | live <a href> to destination; both sides |
| exchanges.health(id) | re-check; may set failed |
Agent happy path (internal links)
import {LinkEQ} from '@linkeq/sdk'
const linkeq = new LinkEQ()
const siteId = 1
await linkeq.sites.ingest(siteId, 'https://example.com/article')
const {ready, pages} = await linkeq.sites.internalLinks(siteId, {
urls: ['https://example.com/article', 'https://example.com/other'],
})
if (!ready) { /* retry later — embeddings not ready */ }
// place <a href={pages[0].links[0].target_url}>{pages[0].links[0].suggested_anchor}</a> on pages[0].source_url
// single page (same shape as before):
const {source_url, links} = await linkeq.sites.internalLinks(siteId, {
url: 'https://example.com/article',
})
// who should link here:
await linkeq.sites.internalLinks(siteId, {
url: 'https://example.com/article',
direction: 'inbound',
})Same flow as https://api.linkeq.co/llms.txt — the SDK is the typed wrapper around those routes.
