Quickstart
Add your first workflow run around the business logic you already have.
Before you start
You need a running Flowmark API, a project server-write key, and the SDK.
The published @flowmarkdev/node README is the implementation contract for
adding markers in an existing app.
npm i @flowmarkdev/nodeThat pulls @flowmarkdev/core automatically. Password reset is not available
yet. For local services, read local development.
1. Configure the server
Set these in your server environment, not in browser-visible variables:
FLOWMARK_API_KEY=<your-project-server-write-key>
FLOWMARK_API_URL=https://api.flowmark.devThe URL is the API origin, not /v1/events. Use your own deployment address
when self-hosting. Production requires an explicit URL. See
configuration for defaults and overrides.
2. Create one shared client
// lib/flowmark.ts (server only)
import { createFlowmark } from "@flowmarkdev/node"
export const flowmark = createFlowmark()Using Next.js? Import from @flowmarkdev/node/next instead and follow the
Next.js guide for automatic request-lifecycle delivery.
3. Add markers to an existing function
loadInvoices, saveValidInvoices, and logger below are your application's
existing helpers, not SDK APIs. No business work moves into Flowmark.
import { flowmark } from "./lib/flowmark"
async function importInvoices(batchId: string) {
const run = flowmark.workflow("invoice.import", {
properties: { batchId },
})
try {
const invoices = await loadInvoices(batchId)
run.step("source-loaded", { properties: { count: invoices.length } })
const result = await saveValidInvoices(invoices)
run.done({ result: { imported: result.imported, skipped: result.skipped } })
return result
} catch (error) {
run.fail({ code: "IMPORT_FAILED" })
logger.error({ batchId, error }, "Import failed")
throw error
}
}Four markers: start, checkpoint, completion, failure. workflow() starts an
independent run; step() records a milestone; done() attaches a bounded
business summary; fail() reports failure without throwing. Your function
keeps ownership of its return value and original exception.
4. Drain delivery at a process boundary
Markers queue delivery automatically. In a plain Node.js script or worker, drain the client before the process exits:
try {
await flowmark.shutdown()
} catch (error) {
console.error("Flowmark delivery failed", error)
}Do this once at the job/process boundary, not inside every shared function.
For a long-running process, use flush() without closing the client.
An explicit drain can reject; handle that separately from the business result.
The Next.js adapter handles draining after the response.
5. Inspect the run
Open your dashboard connected to the same project. Find invoice.import,
then open the run. You should see the source checkpoint, a completed or failed
outcome, and a result summary on successful completion.
If it is missing, follow troubleshooting. A missing terminal event is not proof the business operation failed.
Where to go next
- Workflows and runs: names, IDs, and lifecycle.
- Business results: choose useful outcome summaries.
- SDK reference: signatures, parameters, and behavior.
- Delivery and diagnostics: shutdown, errors, and limits.