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
Yorkyyclient — list forms and pull responses to feed your own dashboards, exports, CRMs, or data pipelines. - Push submissions in with the keyless
ingestfunction — 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/sdkInitialization
import { Yorkyy } from "@yorkyy/sdk";
const yorkyy = new Yorkyy({ apiKey: process.env.YORKYY_API_KEY! });Options
| Option | Type | Default | Notes |
|---|---|---|---|
apiKey | string | — | Required. |
baseUrl | string | https://yorkyy.com | Override for self-hosted. |
fetch | function | global fetch | Custom fetch (e.g. undici). |
retries | number | 3 | 0 to disable. |
retryDelayMs | number | 250 | Doubles each attempt. |
timeoutMs | number | 30000 | Per-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
retriestimes - 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>
}
}