The TypeScript SDK (@fivexer/sdk) is the reference implementation for the /v1 API. It has zero runtime dependencies and runs anywhere with fetch.
Install
bashnpm install @fivexer/sdk
Quickstart
typescriptimport { Fivexer } from '@fivexer/sdk'; const client = new Fivexer({ baseUrl: 'https://api.fivexer.com', apiKey: 'sk_test_...', }); await client.workers.upsert({ id: 'agent_1', tags: ['english', 'billing'] }); const task = await client.tasks.create({ tags: ['english', 'billing'], priority: 90 }); console.log(task.id, task.status);
Hand work off and wait for the result
Give the task your own id so a retry cannot create a second one, say what a finished result must
look like, and wait for it. outcome returns as soon as the task is done or the wait (up to 25
seconds) runs out; the SDK raises its own read timeout to cover the wait.
typescriptawait client.tasks.create({ id: 'audit-2026-10-10', tags: ['seo'], title: 'Audit the pricing page', resultContract: { schema: { type: 'object', required: ['url'], properties: { url: { type: 'string' } } }, acceptanceCriteria: 'A link to the published report.', }, }); let outcome = await client.tasks.outcome('audit-2026-10-10', { waitMs: 25_000 }); while (!outcome.done) outcome = await client.tasks.outcome('audit-2026-10-10', { waitMs: 25_000 }); console.log(outcome.status, outcome.workerId, outcome.result);
A result that misses the schema is refused with result_invalid and stays with the worker to
fix; a worker who cannot do the job completes with success: false, which always goes through.
See the MCP agent toolset for the same flow over MCP.
Errors and quotas
typescriptimport { FivexerApiError } from '@fivexer/sdk'; try { await client.tasks.create({ tags: ['english'] }); } catch (e) { if (e instanceof FivexerApiError) { console.log(e.status, e.code); console.log(e.quota?.taskRateRemaining); } }
Worker portal
The worker client is flat — session, queue, and task actions are all methods on the client itself:
typescriptimport { FivexerWorker } from '@fivexer/sdk'; const worker = new FivexerWorker({ baseUrl: 'https://api.fivexer.com' }); await worker.login({ workspaceId: 'ws_1', workerId: 'agent_1', pin: '4821' }); const queue = await worker.queue(); await worker.accept(queue.taskIds[0]); await worker.complete(queue.taskIds[0], { outcome: 'resolved' });
Breaks, availability, skills, and metrics live on the same client (worker.startBreak(),
worker.setAvailability(false), worker.setSkills([...]), worker.metricsToday()), with
worker.comments, worker.devices, and worker.push grouped as namespaces.
For React Native, @fivexer/expo wraps this client with SecureStore session
persistence, a live queue WebSocket, and hooks.
Supervisor
FivexerSupervisor is the crew-lead plane. Unlike the worker client, its actions are grouped:
typescriptimport { FivexerSupervisor } from '@fivexer/sdk'; const sv = new FivexerSupervisor({ baseUrl: 'https://api.fivexer.com' }); await sv.acceptInvite({ token: tokenFromLink }); const board = await sv.overview(); await sv.tasks.assign(board.parked[0].id, board.crew[0].workerId);
See the supervisor plane for the full surface.
Webhooks
Webhook verification is Node-only and lives at the @fivexer/sdk/webhook subpath so browser bundles don't pull node:crypto:
typescriptimport { verifyWebhookSignature, SIGNATURE_HEADER } from '@fivexer/sdk/webhook'; const ok = verifyWebhookSignature(secret, header, await request.text());