npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@moreflow/api

v0.2.0

Published

Generated, typed ESM client for the Moreflow public operations API.

Readme

@moreflow/api

The generated, typed ESM client for moreflow's public operations API. The client includes every canonical public operation, including the credential management operations selected by the admin scope. It derives input, output, stability, idempotency, pagination, and error types from the reviewed contract snapshots, and each method's editor documentation comes from the operation's registry description, examples, and declared errors.

SERVER-ONLY: use this package in a trusted server runtime. Never ship the API token or OAuth access token in browser code, a client bundle, or page source. Use the public browser SDKs for embeds.

Quickstart

import { createMoreflowApiClient } from '@moreflow/api';

const moreflow = createMoreflowApiClient({
  // A static bearer token or an OAuth access token is sent as Bearer auth.
  token: process.env.MOREFLOW_API_TOKEN
});

const clients = await moreflow.clientsList({ query: 'Weber', limit: 25 });
const created = await moreflow.clientsCreate({ firstName: 'Ada', lastName: 'Lovelace' });

for await (const client of moreflow.iterate('clients.list', { status: 'lead' })) {
  console.log(client.id);
}

Successful calls return the operation output directly. For example, clientsList() returns { items, nextCursor } at the top level; the API does not add an { success: true, data } envelope. Each operation is also available through the generic invoke(operationId, input, options) method.

Credentials and scopes

Create an account-bound integration token on the API token settings page (Settings → Integrations → API tokens). Choose a read or write scope bundle, review its operation picker, and create the token. A token grants exact operation ids, never prefixes or wildcards; the bundle is resolved to those ids when the token is issued, so changing a bundle later never changes an existing token. Discover what a token may call with operationsList() and operationsDescribe({ id }).

The token selects the account: no method accepts accountId. X-Moreflow-Account-Id may select another authorized membership through the client headers option. Headless agents can mint narrower tokens with apiTokensAgentCreate() from a credential that holds the admin:tokens bundle; scopes never widen. Hosted clients can use OAuth 2.1 with PKCE instead and pass the access token.

Pass either credential through token; it is sent as an HTTP Authorization: Bearer token. Pass fetchImpl to use a custom runtime or a local test server. These are the only credential and fetch option names.

Environments

The client calls production, https://api.moreflow.io, by default. Pass baseUrl for another environment:

const development = createMoreflowApiClient({
  baseUrl: 'https://dev-api.moreflow.io',
  token: process.env.MOREFLOW_DEV_API_TOKEN
});

baseUrl: '' produces relative /v1/operations/... URLs, consistent with the browser SDKs. A server has no page origin: use this only with a custom fetchImpl that resolves relative URLs to a trusted origin. The default Node fetch needs an absolute base URL.

Errors and recovery

Failed calls throw MoreflowApiError:

import { MoreflowApiError } from '@moreflow/api';

try {
  await moreflow.dealsUpdate({ dealId, expectedVersion: 3, amountCents: 520000 });
} catch (error) {
  if (!(error instanceof MoreflowApiError)) throw error;
  error.status;           // HTTP status, or undefined when no response arrived
  error.category;         // ApiErrorCategory, e.g. 'ABORTED'
  error.code;             // the operation's declared codes, e.g. 'VERSION_CONFLICT'
  error.requestId;        // quote it when contacting support
  error.declaredRecovery; // { operation: 'deals.get', args } — the next call to make
  error.retryable;        // whether the same request may succeed later
}

error.error is the typed error body of that operation: { category, code, message, recovery, details, requestId }. recovery names the operation (and arguments) that resolves the failure; declaredRecovery falls back to the recovery the contract declares for the code when the server sent none. Every operation's declared errors are in publicApiOperationMetadata[operationId].errors.

isMoreflowError(error), exported by this package, recognizes the shared Symbol.for('moreflow.error') brand across separately bundled @moreflow/forms, @moreflow/chatbots, @moreflow/meetings and @moreflow/api. It narrows a caught value to the common error shape below. Use instanceof MoreflowApiError when you also need API-specific fields such as operationId, category, error, response, declaredRecovery or retryAfterSeconds.

| Field | Type | Meaning | | --- | --- | --- | | code | string | Stable failure code; branch on this, including newer server codes. | | message | string | Developer explanation, using the server's message when available. | | status | number \| undefined | HTTP status; undefined when no response arrived. | | retryable | boolean | Whether the same request may succeed later: HTTP 408, 425, 429, 5xx, network failures or a server-declared retryable failure. Caller cancellation (ABORTED) is not retryable. | | recovery | { operation, args?, requiredFields? } \| undefined | The operation that resolves the failure, its known arguments and input still needed. | | details | Record<string, unknown> | Structured server context; {} when absent. Operation context is merged into it. | | requestId | string \| undefined | Server request id to quote when contacting support. | | responseBody | unknown | Raw response body, unchanged. |

When no structured error body was received, the client reports NETWORK_ERROR, REQUEST_TIMEOUT, ABORTED (caller cancellation), or REQUEST_FAILED (an HTTP error without a code). REQUEST_TIMEOUT is also retryable.

Retries and timeouts

The client retries up to maxRetries times (default 2) after HTTP 408, 425, 429, 5xx, IDEMPOTENCY_IN_PROGRESS, a timeout, a network failure, or a server-declared retryable failure. It waits for Retry-After when the API sends it, otherwise for an exponential backoff with jitter; a requested wait above 60 seconds is returned to you as the error instead. Queries and writes that require an idempotency key are retried with the same key, so the API replays a completed write instead of running it again. The few writes without a required key are retried only after a 429, which the API answers before running the operation.

timeoutMs bounds each attempt; there is no default timeout. A signal you pass cancels the request and any pending retry delay. All three can be set on the client and overridden per call:

const moreflow = createMoreflowApiClient({ token, maxRetries: 3, timeoutMs: 30_000 });
await moreflow.clientsList({}, { maxRetries: 0, timeoutMs: 5_000, signal });

Idempotency

Operations with publicApiOperationMetadata[operationId].idempotencyRequired need an idempotency key. The client generates one per call when you pass none and sends it as the Idempotency-Key header. Pass your own key when a retry from your side (after a crash, or from a queue) must replay the stored result instead of repeating the write:

await moreflow.dealsUpdate(
  { dealId, expectedVersion: 3, amountCents: 520000 },
  { idempotencyKey: `deal-update:${dealId}:3` }
);

Reusing a key with a different request returns IDEMPOTENCY_CONFLICT. The key is sent only as a header; it stays in the JSON body only when the operation's input schema declares an idempotencyKey field. withIdempotency(input, key) still works but is deprecated in favour of the idempotencyKey request option.

Pagination

List operations return { items, nextCursor }. Pass nextCursor back as cursor for the next page, or let the client follow it:

for await (const page of moreflow.iteratePages('clients.list', { limit: 100 })) {
  console.log(page.items.length);
}

for await (const note of moreflow.iterate('clients.notes.list', { clientId })) {
  console.log(note.id);
}

iterate and iteratePages require the input when the operation has required fields (here clientId). Cursors are opaque; a malformed or expired cursor returns INVALID_CURSOR.

Confirmation

Some writes declare that a person must approve them. Set confirm: true only after explicit user confirmation, when a prior call returned CONFIRMATION_REQUIRED.

Issues and contributing

Bug reports and feature requests are welcome in this repository's issue tracker. The published source is generated in the moreflow monorepo from the public operation registry and its committed contract snapshots.

Stable v1

The client is generated from the v1 contract freeze. Integrations use /v1/operations/<operationId>. Each entry in publicApiOperationMetadata publishes stability and contract version. Stable operations have a 180-day deprecation window; beta operations have 30 days.