@kernprotocol/sdk
v0.2.0
Published
Official Kern TypeScript SDK
Readme
@kernprotocol/sdk
Official TypeScript SDK for Kern API (Node 18+, fetch-based).
Install
npm install @kernprotocol/sdk5-minute Quickstart
Set env vars:
export KERN_BASE_URL="https://api.kernprotocol.com"
export KERN_API_KEY="<your-api-key>"1) Initialize client + create task
import { KernClient } from "@kernprotocol/sdk";
const client = new KernClient({
baseUrl: process.env.KERN_BASE_URL!,
apiKey: process.env.KERN_API_KEY!,
});
const created = await client.tasks.create({
title: "Storefront verification",
instructions: "Upload one clear photo of the storefront",
location: { lat: -12.0464, lng: -77.0428, radius_m: 75 },
});
const taskId = created.id ?? created.task_id;2) Get upload URL
const workerId = "worker-quickstart-001";
const uploadMeta = await client.tasks.getEvidenceUploadUrl({
taskId,
workerId,
contentType: "image/jpeg",
});
// uploadMeta: { upload_url, object_key, expires_in_seconds }3) Upload file (Node)
import fs from "node:fs/promises";
const bytes = await fs.readFile("./proof.jpg");
const putRes = await fetch(uploadMeta.upload_url, {
method: "PUT",
headers: { "Content-Type": "image/jpeg" },
body: bytes,
});
if (!putRes.ok) throw new Error(`Upload failed: ${putRes.status}`);4) Upload file (Browser)
// file: File from <input type="file" />
const putRes = await fetch(uploadMeta.upload_url, {
method: "PUT",
headers: { "Content-Type": file.type || "application/octet-stream" },
body: file,
});
if (!putRes.ok) throw new Error(`Upload failed: ${putRes.status}`);5) Submit evidence
await client.tasks.submitEvidence({
taskId,
workerId,
objectKey: uploadMeta.object_key,
lat: -12.0464,
lng: -77.0428,
timestampIso: new Date().toISOString(),
});6) Wait for final decision
const finalTask = await client.tasks.waitForFinalDecision({
taskId,
timeoutMs: 5 * 60_000,
pollIntervalMs: 2_000,
});
console.log("Final status:", finalTask.status); // COMPLETED | REJECTED | CANCELEDCore API
new KernClient({ baseUrl, apiKey, timeoutMs?, maxRetries?, retryOnStatuses? })tasks.create(...)tasks.get(taskId)tasks.events(taskId)tasks.getEvidenceUploadUrl(...)tasks.submitEvidence(...)tasks.waitForFinalDecision(...)
Existing worker lifecycle methods are still available (worker.token/claim/start/evidence/complete).
Error handling
SDK throws KernError:
statuscodemessagerequestId(fromX-Request-Idresponse header)details
Backward compatibility: raw remains as a deprecated alias of details.
Retries, timeout, idempotency
- Default timeout: 20s per request.
- Retries default to 429/503, with exponential backoff + jitter.
Retry-Afterheader is respected when present.- Retries are only attempted for safe/idempotent requests:
- safe methods (
GET,HEAD,OPTIONS) OR - requests with
Idempotency-Key.
- safe methods (
- Unsafe calls should include
Idempotency-Keyfor safe retries.
