JavaScript SDK

The @yorkyy/sdk npm package — a zero-dependency fetch wrapper with typed responses, automatic retries, and a consistent error class. Works in Node 18+, Bun, Deno, Cloudflare Workers, and modern browsers.

What you can build

The SDK turns yorkyy from a website you log into a service your code can talk to. There are two halves:

  • Read your data with the authenticated Yorkyy client — list forms and pull responses to feed your own dashboards, exports, CRMs, or data pipelines.
  • Push submissions in with the keyless ingest function — send data from your ownform, app, or script and get yorkyy's real-time alerts, no hosted form required.

A few things people build:

  • A custom-branded form on their own site that still pings the team's Slack the instant someone submits.
  • A nightly job that pulls every response into Airtable, a warehouse, or a Google Sheet.
  • A mobile or CLI app that submits to yorkyy and leans on it for the “new lead!” notification.
  • A backup script that archives all submissions across every form.

Bring your own form, keep the real-time alerts

This is the SDK's most powerful move. Already have a form you love — your own design, your own validation, your own frontend? You don't have to switch to a yorkyy-hosted form to get yorkyy's notification engine. Just ingest the submission and yorkyy fires the same real-time Telegram, Slack, Discord, WhatsApp, and email alerts as if it came from a hosted form.

ingestneeds no API key — it posts to a form's public ingest endpoint. Pass the endpoint (the publicId from your form's share settings, or the full endpoint URL). Safe to call from a server; for browser use, see the spam-protection note below.

import { ingest } from "@yorkyy/sdk";

// Your own custom form's submit handler:
async function handleSubmit(formData) {
  const result = await ingest({
    endpoint: "aB3xK9mQ",        // form's publicId (or full endpoint URL)
    data: {
      name: formData.name,
      email: formData.email,
      message: formData.message,
    },
  });

  // result.submission_id is the new submission's id. The moment this resolves,
  // your team's Telegram/Slack/email alert is already on its way.
  return result;
}

That's the whole integration. Your frontend stays exactly as it is; yorkyy becomes the response store and the alert pipeline behind it. See Ingest endpoints for the underlying HTTP API, field mapping, and spam-protection options.

Read responses into your own systems

The authenticated client is for pulling your account's data into code — build a custom dashboard, sync to another tool, or run scheduled exports. The full method reference is below; here's the shape of it:

import { Yorkyy } from "@yorkyy/sdk";

const yorkyy = new Yorkyy({ apiKey: process.env.YORKYY_API_KEY! });

// Every response to a form, paginated — pipe it anywhere you like.
const { data, pagination } = await yorkyy.forms.submissions(formId, { limit: 100 });
for (const submission of data) {
  await syncToAirtable(submission.data);
}

Installation

npm install @yorkyy/sdk
pnpm add @yorkyy/sdk
bun add @yorkyy/sdk
deno add npm:@yorkyy/sdk

Initialization

import { Yorkyy } from "@yorkyy/sdk";

const yorkyy = new Yorkyy({ apiKey: process.env.YORKYY_API_KEY! });

Options

OptionTypeDefaultNotes
apiKeystringRequired.
baseUrlstringhttps://yorkyy.comOverride for self-hosted.
fetchfunctionglobal fetchCustom fetch (e.g. undici).
retriesnumber30 to disable.
retryDelayMsnumber250Doubles each attempt.
timeoutMsnumber30000Per-request timeout.

Methods

yorkyy.me()

Returns the authenticated user. Use it to verify a key works.

const user = await yorkyy.me();
// { id: "01h...", email: "you@example.com", name: "Your Name" }

yorkyy.forms.list()

Returns up to 200 of your forms.

const forms = await yorkyy.forms.list();
console.log(forms.map(f => f.title));

yorkyy.forms.submissions(formId, options?)

Returns paginated submissions. Pass cursor to fetch the next page.

const first = await yorkyy.forms.submissions("01h...", { limit: 50 });

let cursor = first.pagination.next_cursor;
while (cursor) {
  const next = await yorkyy.forms.submissions("01h...", { limit: 50, cursor });
  // ... process next.data ...
  cursor = next.pagination.next_cursor;
}

Error handling

All errors are instances of YorkyyError:

import { Yorkyy, YorkyyError } from "@yorkyy/sdk";

try {
  await yorkyy.forms.submissions("invalid-id");
} catch (err) {
  if (err instanceof YorkyyError) {
    console.log(err.status); // 404
    console.log(err.code);   // "form_not_found"
    console.log(err.message); // "Form not found."
  }
}

Retry behavior

  • 4xx (except 429): not retried — auth or validation errors won't resolve on retry
  • 429: retried with exponential backoff up to retries times
  • 5xx: retried with exponential backoff
  • Network errors / timeouts: retried with exponential backoff

TypeScript

Every method is fully typed. Hover any return value in your editor to see the shape.

import type { Form, Submission, PaginatedResponse } from "@yorkyy/sdk";

function processSubmissions(page: PaginatedResponse<Submission>) {
  for (const s of page.data) {
    s.created_at; // string (ISO 8601)
    s.data;       // Record<string, unknown>
  }
}