nectr

API Documentation

Convert any web page or PDF into clean, LLM-ready markdown over a simple REST API.

Quick start

  1. Create an API key in your account settings. Keys are prefixed nct_ and available on every plan.
  2. Send the key as a Bearer token on every request.
  3. POST a URL and receive markdown in the response.
curl -X POST "https://nectr.ch/api/v1/conversions" \
  -H "Authorization: Bearer nct_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/article"}'

Authentication

All authenticated requests use the Authorization header with your API key as a Bearer token:

Authorization: Bearer nct_your_api_key

Keep keys secret — they carry your account's quota and access. Revoke a key any time from settings.

Base URL

https://nectr.ch/api/v1

Endpoints

POST/conversionsConvert a URL or PDF to markdown
GET/conversionsList your conversions (paginated)
GET/conversions/{id}Fetch a single conversion
GET/conversions/by-urlResolve by URL + short id (auto-refreshes)
DELETE/conversions/{id}Delete a conversion
GET/projectsList projects
POST/projectsCreate a project

POST /conversions accepts a JSON body: { "url": "…", "force_refresh": false }. A successful, uncached crawl counts as one conversion against your monthly quota; cache hits do not. Set force_refresh: true to bypass the cache and re-crawl now (this also counts toward your quota).

GET /conversions supports pagination and sorting: page (≥ 1), limit (1–100, default 20), search, sort_by (fetched_at · word_count · status) and sort_dir (asc · desc).

GET /conversions/by-url requires the url and short_idquery parameters, and re-crawls the source automatically once it is past your plan's freshness interval.

Example response

{
  "id": "8f3c…",
  "url": "https://example.com/article",
  "title": "Example article",
  "markdown_content": "# Example article\n\n...",
  "word_count": 1240,
  "status": "completed",
  "fetched_at": "2026-05-25T10:00:00Z",
  "short_id": "ab12-cd34-ef56",
  "cached": false
}

Extraction modes & formats

Reads are free — no crawl, no quota — so you can request different views of a stored conversion. Add mode and format query params to GET /conversions/{id} or GET /conversions/by-url. Unknown values fall back to the default.

modeReturns
contentBest extraction (default) — full markdown.
cleanClean article extraction — boilerplate stripped.
fullFull-page extraction — keeps structural links and sections.
outlineHeading hierarchy only, as a nested list.
tablesOnly the tables.
listsOnly the lists.

format is markdown (default) or json. With format=json, the response includes a structured object: { title, url, headings, links, tables, lists, word_count, markdown }.

# Heading map (outline) as markdown
curl "https://nectr.ch/api/v1/conversions/{id}?mode=outline" \
  -H "Authorization: Bearer nct_your_api_key"

# Structured JSON — headings, links, tables, lists
curl "https://nectr.ch/api/v1/conversions/{id}?format=json" \
  -H "Authorization: Bearer nct_your_api_key"

Permanent share links accept the same params, so no API key is needed for a public conversion — e.g. /raw/{short_id}/{url}?mode=tables.

Code examples

Python

import httpx

resp = httpx.post(
    "https://nectr.ch/api/v1/conversions",
    headers={"Authorization": "Bearer nct_your_api_key"},
    json={"url": "https://example.com/article"},
)
data = resp.json()
print(data["markdown_content"])

JavaScript

const res = await fetch("https://nectr.ch/api/v1/conversions", {
  method: "POST",
  headers: {
    "Authorization": "Bearer nct_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://example.com/article" }),
});
const data = await res.json();
console.log(data.markdown_content);

Rate limits & quota

API requests share your account's monthly conversion quota — there is no separate API pool. A per-minute rate limit (per key) protects against bursts:

PlanRate limitConversions / month
Free10 / min100
Builder60 / min2,000

Error codes

401Missing or invalid API key.
402Monthly conversion limit reached — upgrade or wait for reset.
422Invalid request, or the URL could not be converted.
429Rate limit exceeded — retry after the Retry-After header.
503Converter temporarily at capacity — retry after a few seconds.

Markdown output

Each conversion returns a title heading, a metadata block (source URL, conversion time, refresh interval), and the cleaned content — navigation, ads, and boilerplate stripped, with links and images preserved. Authenticated links auto-refresh on access once they pass your plan's freshness interval.