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

@omniq/sdk

v0.1.0

Published

OMNIQ Platform SDK — typed API client for project management

Readme

@omniq/sdk

Typed SDK for the OMNIQ Platform API. Zero dependencies — uses native fetch.

Quick Start

npm install @omniq/sdk
# or
pnpm add @omniq/sdk
import { OmniqClient } from '@omniq/sdk';

const client = new OmniqClient({
  baseUrl: 'https://app.omniq.pro/api/v1',
  token: 'pat_abc123…',
});

const projects = await client.projects.list();
console.log(projects);

Authentication

Personal Access Token (recommended)

Create a PAT in Settings → Tokens and pass it to the client. Best for scripts, CI pipelines, and MCP servers.

const client = new OmniqClient({
  baseUrl: 'https://app.omniq.pro/api/v1',
  token: process.env.OMNIQ_TOKEN,
});

Cookie (server-side proxy)

When proxying through a backend that already holds a session cookie, forward the Cookie header instead:

const client = new OmniqClient({
  baseUrl: 'https://app.omniq.pro/api/v1',
  cookieHeader: req.headers.cookie,
});

Email / Password

Authenticate programmatically and receive a session. The login response sets an httpOnly cookie — use cookieHeader for subsequent calls.

const client = new OmniqClient({
  baseUrl: 'https://app.omniq.pro/api/v1',
});

const { user } = await client.auth.login({
  email: '[email protected]',
  password: 'secret',
});

Configuration

| Option | Type | Default | Description | | --- | --- | --- | --- | | baseUrl | string | — | API root URL (required) | | token | string | — | Personal Access Token for Bearer auth | | cookieHeader | string | — | Raw Cookie header value for server-side proxy | | maxRetries | number | 3 | Retry count for 5xx / network errors |

Resources

Auth — client.auth

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | login(data) | POST | /auth/login | LoginResponse | | refresh() | POST | /auth/refresh | { success: boolean } | | logout() | POST | /auth/logout | void | | logoutAll() | POST | /auth/logout-all | void | | me() | GET | /auth/me | { user: User } |

Projects — client.projects

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | list() | GET | /projects | Project[] | | get(id) | GET | /projects/:id | Project | | create(data) | POST | /projects | Project | | update(id, data) | PATCH | /projects/:id | Project | | delete(id) | DELETE | /projects/:id | void | | listMembers(projectId) | GET | /projects/:id/members | ProjectMember[] | | addMember(projectId, data) | POST | /projects/:id/members | void | | removeMember(projectId, userId) | DELETE | /projects/:id/members/:userId | void |

const project = await client.projects.create({
  name: 'Payments',
  key: 'PAY',
  description: 'Payment processing service',
});

Issues — client.issues

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | list(params?) | GET | /issues | PaginatedResponse<Issue> | | listAll(params?) | GET | /issues (auto-paginated) | AsyncGenerator<Issue> | | get(id) | GET | /issues/:id | Issue | | create(data) | POST | /issues | Issue | | update(id, data) | PATCH | /issues/:id | Issue | | delete(id) | DELETE | /issues/:id | void | | updateStatus(id, status) | POST | /issues/:id/status | Issue | | bulkUpdate(data) | POST | /issues/bulk | Issue[] | | addComment(issueId, data) | POST | /issues/:id/comments | Comment | | addLink(issueId, data) | POST | /issues/:id/links | IssueLink |

const issue = await client.issues.create({
  projectId: 'proj_1',
  title: 'Fix login bug',
  priority: 'high',
  type: 'bug',
});

await client.issues.updateStatus(issue.id, 'in_progress');

Sprints — client.sprints

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | list({ projectId }) | GET | /sprints | Sprint[] | | get(id) | GET | /sprints/:id | Sprint | | create(data) | POST | /sprints | Sprint | | update(id, data) | PATCH | /sprints/:id | Sprint | | delete(id) | DELETE | /sprints/:id | void | | start(id) | POST | /sprints/:id/start | Sprint | | close(id, transferToSprintId?) | POST | /sprints/:id/close | Sprint | | burndown(id) | GET | /sprints/:id/burndown | BurndownPoint[] | | velocity({ projectId }) | GET | /sprints/velocity | VelocityData |

const sprints = await client.sprints.list({ projectId: 'proj_1' });
const burndown = await client.sprints.burndown(sprints[0].id);
const velocity = await client.sprints.velocity({ projectId: 'proj_1' });

// Close sprint and transfer undone issues
await client.sprints.close(sprint.id, nextSprint.id);

Wiki — client.wiki

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | listSpaces({ projectId }) | GET | /wiki/spaces | WikiSpace[] | | createSpace(data) | POST | /wiki/spaces | WikiSpace | | listPages({ spaceId }) | GET | /wiki/pages | WikiPage[] | | createPage(data) | POST | /wiki/pages | WikiPage | | updatePage(id, data) | PATCH | /wiki/pages/:id | WikiPage | | pageVersions(id) | GET | /wiki/pages/:id/versions | WikiPageVersion[] | | restorePage(pageId, versionId) | POST | /wiki/pages/:id/restore/:versionId | WikiPage | | search({ projectId, q }) | GET | /wiki/search | WikiSearchResult[] | | templates() | GET | /wiki/templates | WikiTemplate[] |

const results = await client.wiki.search({
  projectId: 'proj_1',
  q: 'onboarding',
});

Calendar — client.calendar

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | listEvents({ start, end, projectId?, userId? }) | GET | /calendar/events | CalendarEvent[] | | createEvent(data) | POST | /calendar/events | CalendarEvent | | updateEvent(id, data) | PATCH | /calendar/events/:id | CalendarEvent | | deleteEvent(id) | DELETE | /calendar/events/:id | void | | listResources({ start, end, projectId? }) | GET | /calendar/resources | CalendarResourceEntity[] | | exportIcs({ start, end }) | GET | /calendar/export.ics | Response (raw) |

const events = await client.calendar.listEvents({
  start: '2025-06-01',
  end: '2025-06-30',
  projectId: 'proj_1',
});

const icsResponse = await client.calendar.exportIcs({
  start: '2025-06-01',
  end: '2025-06-30',
});
const ics = await icsResponse.text();

AI — client.ai

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | chat(data) | POST | /ai/chat | AiChatResponse | | chatStream(data) | POST | /ai/chat/stream | Response (raw SSE stream) | | generate(data) | POST | /ai/generate | { content, tokensUsed } | | estimate(data) | POST | /ai/estimate | AiEstimateResponse | | plan(data) | POST | /ai/plan | { content, tokensUsed } | | summarize(data) | POST | /ai/summarize | { content, tokensUsed } | | insights({ projectId }) | GET | /ai/insights | { content, tokensUsed } |

const estimate = await client.ai.estimate({
  title: 'Add OAuth2 login',
  description: 'Support Google and GitHub OAuth2 flows',
});
console.log(`${estimate.storyPoints} SP (${estimate.confidence}% confidence)`);

const reply = await client.ai.chat({
  message: 'Summarize the current sprint progress',
  projectId: 'proj_1',
});
console.log(reply.content);

Notifications — client.notifications

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | list({ unreadOnly? }?) | GET | /notifications | { data: Notification[], unreadCount } | | markRead(id) | POST | /notifications/:id/read | void | | markAllRead() | POST | /notifications/read-all | void |

const { data: notifications, unreadCount } = await client.notifications.list({
  unreadOnly: true,
});

for (const n of notifications) {
  await client.notifications.markRead(n.id);
}

Tokens — client.tokens

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | list() | GET | /tokens | PersonalAccessToken[] | | create(data) | POST | /tokens | CreatedToken | | delete(id) | DELETE | /tokens/:id | void |

const { token } = await client.tokens.create({
  name: 'CI pipeline',
  scopes: ['issues:read', 'issues:write'],
  expiresAt: '2026-12-31T23:59:59Z',
});
// Store `token` securely — it is only shown once.

GitLab — client.gitlab

| Method | HTTP | Path | Returns | | --- | --- | --- | --- | | listActivity(projectId) | GET | /git/events | GitLabEvent[] | | linkCommit(issueId, sha, url?) | POST | /git/commits/link | void |

const events = await client.gitlab.listActivity('proj_1');

await client.gitlab.linkCommit('issue_1', 'abc123def', 'https://gitlab.com/…/commit/abc123def');

Pagination

Methods returning PaginatedResponse<T> include data, total, page, and limit fields. For convenience, listAll() methods return an AsyncGenerator that handles page fetching automatically:

for await (const issue of client.issues.listAll({ projectId: 'proj_1' })) {
  console.log(issue.key, issue.title);
}

// With filters
for await (const issue of client.issues.listAll({
  projectId: 'proj_1',
  status: 'in_progress',
  assigneeId: 'user_1',
})) {
  process.stdout.write(`${issue.key} `);
}

The paginator fetches 50 items per page and stops when all items are consumed.

Error Handling

All API errors throw OmniqApiError with status, statusText, and body properties:

import { OmniqClient, OmniqApiError } from '@omniq/sdk';

try {
  await client.projects.get('nonexistent');
} catch (error) {
  if (error instanceof OmniqApiError) {
    console.error(error.status);     // 404
    console.error(error.statusText); // "Not Found"
    console.error(error.body);       // parsed JSON error body
  }
}

Automatic retries — Server errors (5xx) and network failures are retried up to maxRetries times (default 3) with exponential backoff (1 s → 2 s → 4 s, capped at 10 s). Client errors (4xx) are never retried and throw immediately.

TypeScript

The SDK is fully typed. All entity types, input types, enums, and utility types are exported from the package root:

import { OmniqClient } from '@omniq/sdk';
import type {
  Issue,
  CreateIssueInput,
  IssueStatus,
  IssuePriority,
  StoryPoints,
  PaginatedResponse,
} from '@omniq/sdk';

async function moveToReview(client: OmniqClient, issueId: string): Promise<Issue> {
  return client.issues.updateStatus(issueId, 'review');
}

Enums / UnionsRole, IssueStatus, IssuePriority, IssueType, StoryPoints, SprintStatus, CalendarEventType, CalendarEventStatus, ContentFormat, CommentSource, NotificationType, EntityType

EntitiesUser, Project, Issue, Sprint, Comment, IssueLink, WikiSpace, WikiPage, WikiPageVersion, WikiTemplate, CalendarEvent, CalendarResourceEntity, Notification, PersonalAccessToken, CreatedToken, ProjectMember, GitLabEvent, GitLabCommitLink

InputsLoginInput, CreateProjectInput, AddMemberInput, CreateIssueInput, UpdateIssueInput, BulkUpdateIssueInput, CreateCommentInput, CreateIssueLinkInput, IssueListParams, CreateSprintInput, UpdateSprintInput, CreateWikiSpaceInput, CreateWikiPageInput, UpdateWikiPageInput, CreateCalendarEventInput, UpdateCalendarEventInput, CreateTokenInput, AiChatInput, AiGenerateInput, AiEstimateInput

ResponsesLoginResponse, AuthTokens, AiChatResponse, AiEstimateResponse, PaginatedResponse<T>, BurndownPoint, VelocityEntry, VelocityData, WikiSearchResult

Resource classesAuthResource, ProjectsResource, IssuesResource, SprintsResource, WikiResource, CalendarResource, AIResource, NotificationsResource, TokensResource, GitLabResource

License

MIT