AI Connect/Reference/API Reference

API Reference

Ask AI about Vinkius

Reference the Vinkius client, fluent and low-level APIs, capability contract, errors, retries, hooks, and utilities.

Vinkius is the application-scoped entry point. Use its fluent handles for user, connector, credential, and capability workflows. Use the low-level clients when you need direct resource operations.

typescript
import { Vinkius } from '@vinkius/connect';

const vinkius = new Vinkius({
  appId: process.env.VINKIUS_APP_ID!,
  apiKey: process.env.VINKIUS_APP_KEY!,
});

const user = vinkius.user('alice_123'); // No request.
const github = user.connector('github'); // No request.

await github.connect();
await github.credentials.set({ GITHUB_TOKEN: process.env.GITHUB_TOKEN! });

const capabilities = await github.capabilities();

Package exports

Root package

Import these values from @vinkius/connect:

CategoryExports
Client and fluent handlesVinkius, UserContext, Connector, CredentialsHandle, Capability, CapabilitySet
Low-level clientsCatalogClient, AppUsersClient, ConnectionsClient, CredentialsClient, ExecutionClient
InfrastructureResolverCache, VERSION
ErrorsVinkiusError, ConfigError, AuthError, NotFoundError, ValidationError, RateLimitError, QuotaError, OverageError, ConnectorNotConnectedError, NotImplementedError, ConnectionError

The root also exports these types:

CategoryExports
Client and executionVinkiusOptions, RequestOptions, ExecuteOptions, Hooks, CapabilityExecutor, CapabilityQuery
Low-level inputsCreateAppUserInput, UpdateAppUserInput, CreateConnectionInput, SetCredentialsInput, ExecuteCapabilityInput
ResourcesAppUser, Connection, CatalogConnector, CatalogConnectorDetail, CredentialType, CredentialField, CredentialSchema, CredentialStatus
CapabilitiesConnectorStatus, ConnectorSummary, CapabilityResult, CapabilityData, JSONSchema
Pagination and primitivesPaginated, PageMeta, PageLinks, ISODate
ErrorsVinkiusErrorCode

HttpClient, retry internals, redaction helpers, and adapter-shared helpers are not root exports. Although the low-level client classes are exported, their constructors require the internal HttpClient type. Obtain instances through vinkius.catalog, vinkius.users, and the scoped factories described below.

Package subpaths

SubpathPublic exports
@vinkius/connect/openaitoOpenAITools, runOpenAIToolCall, OpenAIFunctionTool, OpenAIToolCall
@vinkius/connect/anthropictoAnthropicTools, runAnthropicToolUse, AnthropicTool, AnthropicToolUse
@vinkius/connect/ai-sdktoAISDKTools, AISDKTool, ToAISDKOptions
@vinkius/connect/geminitoGeminiTools, runGeminiFunctionCall, GeminiFunctionDeclaration, GeminiFunctionCall
@vinkius/connect/langchaintoLangChainTools, LangChainToolFactory, ToLangChainOptions
@vinkius/connect/json-schematoJSONSchemaTools, executeByName, JSONSchemaTool
@vinkius/connect/openai-agentstoOpenAIAgentsTools, OpenAIAgentsToolFactory, ToOpenAIAgentsOptions
@vinkius/connect/llamaindextoLlamaIndexTools, LlamaIndexToolFactory, ToLlamaIndexOptions
@vinkius/connect/workers-aitoWorkersAITools, WorkersAITool
@vinkius/connect/package.jsonPackage metadata

The package publishes ESM and CommonJS entry points, declares no side effects, and requires Node.js 18 or later.

Create a client

typescript
new Vinkius(options: VinkiusOptions)
OptionDefaultBehavior
appIdRequiredMust be a string beginning with vk_app_, but not vk_app_sk_. Sent as x-vinkius-app-id.
apiKeyRequiredMust be a string beginning with vk_app_sk_. Sent as a Bearer token. Keep it server-side.
baseUrlhttps://api.vinkius.comParsed as a URL and normalized without trailing slashes. An invalid URL throws ConfigError. Non-local http:// emits a console warning but is not rejected.
timeoutMs30000Timeout for the fetch portion of each attempt. It is not a total operation deadline.
maxRetries2Maximum additional attempts for retry-safe requests.
fetchglobalThis.fetchCustom fetch implementation. A missing global or custom function throws ConfigError.
userAgentnoneAppended to the SDK user agent.
hooksnoneSynchronous, redacted request and response callbacks.
namespaceCapability(connector, name) => \${connector}__\${name}`Produces each capability's display name.

Requests include Authorization: Bearer <apiKey>, x-vinkius-app-id, Accept: application/json, and the SDK user agent. Requests with a body also include Content-Type: application/json.

Create a lazy user handle

typescript
const user = vinkius.user('alice_123');

user() makes no request. externalId must be your application's stable user ID, not a Vinkius internal ID beginning with vk_app_user_. It must contain 1 to 255 characters and cannot contain whitespace, /, or backslashes. Invalid values throw ConfigError.

Request options

Most request-making methods accept RequestOptions. Capability execution accepts ExecuteOptions.

typescript
interface RequestOptions {
  signal?: AbortSignal;
}

interface ExecuteOptions extends RequestOptions {
  idempotencyKey?: string;
}

UserContext.ensure(metadata?) is the exception: it does not accept RequestOptions. Adapter dispatch helpers and adapter-generated callbacks also do not accept ExecuteOptions.

Use a non-empty, stable idempotencyKey for the same logical capability execution, and reuse it only when manually repeating that same operation.

Fluent API

Lazy resolution

typescript
const user = vinkius.user('alice_123');
const connector = user.connector('github');
const credentials = connector.credentials;

These statements make no requests. A Connector resolves its connection only when an operation needs it, matching connection.slug or connection.id against the handle's slug. The resolved connection ID is memoized on that handle only. connect() stores the returned connection ID; disconnect() clears it after deletion.

UserContext

typescript
class UserContext {
  readonly externalId: string;

  ensure(metadata?: Record<string, unknown>): Promise<AppUser>;
  get(options?: RequestOptions): Promise<AppUser>;
  connector(slug: string): Connector;
  connectors(options?: RequestOptions): Promise<ConnectorSummary[]>;
  capabilities(options?: CapabilityQuery): Promise<CapabilitySet>;
}

ensure() performs the idempotent user upsert; calling user() alone does not create a user. connectors() returns existing connections only ({ slug, status, connectionId? }).

A non-empty include array in capabilities() is sent to the server as one comma-separated connector query value; exclude is applied client-side after the response. The returned capabilities are executable and carry the connector and connection ID supplied by the aggregated endpoint.

Connector

typescript
class Connector {
  readonly slug: string;
  readonly credentials: CredentialsHandle;

  connect(options?: RequestOptions): Promise<Connection>;
  disconnect(options?: RequestOptions): Promise<void>;
  status(options?: RequestOptions): Promise<ConnectorStatus>;
  capabilities(options?: RequestOptions): Promise<CapabilitySet>;
}

connect() is explicitly retry-safe and memoizes the returned connection ID. status() returns not_connected instead of throwing when no connection exists. disconnect() and capabilities() require a connection and throw ConnectorNotConnectedError when resolution finds none.

ConnectorStatus is derived as follows:

ValueCondition
not_connectedNo matching connection exists.
readyconnection.status === 'active' and connection.ready === true.
needs_credentialsconnection.status === 'active' and connection.ready !== true.
disabledconnection.status !== 'active'.

CredentialsHandle

typescript
class CredentialsHandle {
  schema(options?: RequestOptions): Promise<CredentialSchema>;
  status(options?: RequestOptions): Promise<CredentialStatus>;
  set(
    values: Record<string, string>,
    options?: RequestOptions,
  ): Promise<CredentialStatus>;
}

schema() reads the catalog entry and does not require an existing connection. status() and set() never connect implicitly: they resolve an existing connection first and throw ConnectorNotConnectedError when none exists.

Credential values are write-only. Credential responses contain a schema and configured-key booleans, never credential values:

typescript
interface CredentialStatus {
  schema: CredentialSchema;
  configured: Record<string, boolean>;
}

The fluent set() accepts a flat map and wraps it in the low-level { credentials: values } envelope. The client does not validate the values against the schema before sending them.

Capabilities

CapabilitySet

CapabilitySet extends Array<Capability>. Standard array methods are available.

typescript
class CapabilitySet extends Array<Capability> {
  static fromCapabilities(
    capabilities: readonly Capability[],
  ): CapabilitySet;

  forConnector(slug: string): CapabilitySet;
  findCapability(name: string): Capability | undefined;
}

forConnector() uses an exact connector-slug match. findCapability() returns the first exact match against either the namespaced display name or the raw connector name. Raw names can collide across connectors; prefer display names, or scope first:

typescript
const issue = capabilities
  .forConnector('github')
  .findCapability('create_issue');

Capability

typescript
class Capability {
  readonly connector: string;
  readonly connectionId: string;
  readonly name: string;
  readonly rawName: string;
  readonly title: string | null;
  readonly description: string;
  readonly inputSchema: JSONSchema;

  execute(
    args?: Record<string, unknown>,
    options?: ExecuteOptions,
  ): Promise<CapabilityResult>;
}
PropertyMeaning
connectorConnector slug associated with the capability.
connectionIdConnection used for execution routing.
nameDisplay name produced by namespaceCapability.
rawNameName exposed by the connector and sent for execution.
titleOptional title, normalized to null.
descriptionDescription, normalized to an empty string when absent.
inputSchemaInput JSON Schema, normalized to {} when absent.

Execution always routes with connectionId and rawName, not the display name. Capability is exported, but its constructor's initialization interface is not a package export: treat capabilities as SDK-produced objects instead of constructing them manually.

typescript
interface CapabilityResult {
  content: Array<{ type: string; text: string }>;
  isError: boolean;
}

isError: true is a returned capability result, not a thrown exception. HTTP, transport, configuration, connector-resolution, and adapter-dispatch failures can still throw.

Low-level clients

Use the exposed instances and factories:

typescript
const catalog = vinkius.catalog;
const users = vinkius.users;
const connections = users.connections('alice_123');
const credentials = connections.credentials(connectionId);
const execution = connections.execution(connectionId);

Factory calls are request-free. Low-level methods return resource or raw capability shapes rather than fluent handles unless stated otherwise.

CatalogClient

typescript
class CatalogClient {
  list(
    options?: { page?: number } & RequestOptions,
  ): Promise<Paginated<CatalogConnector>>;

  get(
    slug: string,
    options?: RequestOptions,
  ): Promise<CatalogConnectorDetail>;

  search(
    query: string,
    options?: RequestOptions,
  ): Promise<CatalogConnector[]>;
}

list() is page-based. get() accepts a connector slug or catalog ID and returns credential_schema. search() sends q and returns the normalized data array; filtering depends on server support for q.

AppUsersClient

typescript
class AppUsersClient {
  create(
    input: CreateAppUserInput,
    options?: RequestOptions,
  ): Promise<AppUser>;

  get(externalId: string, options?: RequestOptions): Promise<AppUser>;

  update(
    externalId: string,
    patch: UpdateAppUserInput,
    options?: RequestOptions,
  ): Promise<AppUser>;

  delete(externalId: string, options?: RequestOptions): Promise<void>;

  list(
    options?: { status?: string; page?: number } & RequestOptions,
  ): Promise<Paginated<AppUser>>;

  capabilities(
    externalId: string,
    options?: { connectors?: string[] } & RequestOptions,
  ): Promise<CapabilityData[]>;

  connections(externalId: string): ConnectionsClient;
}

create() is an explicitly retry-safe upsert by external ID. capabilities() returns raw CapabilityData[], not executable Capability objects; use user.capabilities() for the fluent executable form.

ConnectionsClient

typescript
class ConnectionsClient {
  list(options?: RequestOptions): Promise<Connection[]>;

  create(
    input: CreateConnectionInput,
    options?: RequestOptions,
  ): Promise<Connection>;

  get(
    connectionId: string,
    options?: RequestOptions,
  ): Promise<Connection>;

  delete(
    connectionId: string,
    options?: RequestOptions,
  ): Promise<void>;

  credentials(connectionId: string): CredentialsClient;
  execution(connectionId: string): ExecutionClient;
}

create() is an explicitly retry-safe get-or-create operation. list() returns a plain array.

CredentialsClient

typescript
class CredentialsClient {
  status(options?: RequestOptions): Promise<CredentialStatus>;

  set(
    input: SetCredentialsInput,
    options?: RequestOptions,
  ): Promise<CredentialStatus>;
}

interface SetCredentialsInput {
  credentials: Record<string, string>;
}

The low-level method requires the envelope that the fluent handle adds for you:

typescript
await connections.credentials(connection.id).set({
  credentials: { GITHUB_TOKEN: process.env.GITHUB_TOKEN! },
});

ExecutionClient

typescript
class ExecutionClient {
  list(options?: RequestOptions): Promise<CapabilityData[]>;

  execute(
    input: ExecuteCapabilityInput,
    options?: ExecuteOptions,
  ): Promise<CapabilityResult>;
}

interface ExecuteCapabilityInput {
  name: string;
  arguments?: Record<string, unknown>;
}

name is the raw connector capability name. This is the only low-level method that accepts ExecuteOptions.

Input and resource types

typescript
interface CreateAppUserInput {
  external_id: string;
  status?: string;
  metadata?: Record<string, unknown>;
}

interface UpdateAppUserInput {
  status?: string;
  metadata?: Record<string, unknown>;
}

interface CreateConnectionInput {
  connector: string;
}

interface SetCredentialsInput {
  credentials: Record<string, string>;
}

interface ExecuteCapabilityInput {
  name: string;
  arguments?: Record<string, unknown>;
}

type ISODate = string;
type JSONSchema = Record<string, unknown>;

interface AppUser {
  id: string;
  external_id: string;
  status: string;
  metadata: Record<string, unknown> | null;
  application_id?: string;
  mcp_count?: number;
  created_at: ISODate;
  updated_at: ISODate;
}

interface Connection {
  id: string;
  slug: string | null;
  name: string;
  description: string | null;
  status: string;
  ready: boolean;
  tokens_count?: number;
  created_at: ISODate;
}

interface CatalogConnector {
  id: string;
  slug: string;
  title: string;
  short_description: string | null;
  publisher_type: string;
  listing_type: string;
  requires_buyer_auth: boolean;
  server_type?: string;
  tools_count?: number;
}

interface CatalogConnectorDetail extends CatalogConnector {
  credential_schema: CredentialSchema;
}

type CredentialType =
  | 'api_key'
  | 'token'
  | 'password'
  | 'connection_string'
  | 'string'
  | 'number'
  | 'email'
  | 'url'
  | 'select'
  | 'boolean'
  | 'oauth2';

interface CredentialField {
  type: CredentialType;
  label?: string;
  required?: boolean;
  group?: string;
  docs_url?: string;
  placeholder?: string;
  allowed?: string[];
}

type CredentialSchema = Record<string, CredentialField>;

interface CapabilityData {
  name: string;
  title?: string | null;
  description?: string | null;
  input_schema?: JSONSchema | null;
  annotations?: unknown;
  connector?: string;
  connection_id?: string;
}

interface Paginated<T> {
  data: T[];
  meta?: PageMeta;
  links?: PageLinks;
}

interface PageMeta {
  current_page: number;
  from: number | null;
  last_page: number;
  path: string;
  per_page: number;
  to: number | null;
  total: number;
}

interface PageLinks {
  first: string | null;
  last: string | null;
  prev: string | null;
  next: string | null;
}

Plain-list endpoints accept either a bare array or an object with data; unexpected shapes normalize to an empty array. Paginated endpoints expect { data, meta?, links? }, normalize a missing or non-array data field to an empty array, and retain truthy meta and links values.

Hooks and redaction

typescript
interface Hooks {
  onRequest?: (info: {
    method: string;
    url: string;
    headers: Record<string, string>;
  }) => void;

  onResponse?: (info: {
    status: number;
    url: string;
    requestId?: string;
    body: unknown;
  }) => void;
}

Hooks run synchronously and are not awaited; if a hook throws, that exception propagates and stops the request flow.

Request hook. onRequest runs before every attempt with the full request URL and a copied header map. It does not receive the request body, and URLs are not redacted. Header names are matched exactly, case-insensitively; these values become [REDACTED]: authorization, idempotency-key, cookie, set-cookie. No other header is redacted by heuristic.

Response hook. onResponse runs for every attempt that returns an HTTP response, including a transient response that will be retried. It does not run for a fetch failure or timeout without a response. An empty body is undefined; valid JSON is parsed; non-JSON text remains a string. Response object keys are matched exactly, case-insensitively; these become [REDACTED]: authorization, apikey, api_key, token, access_token, refresh_token, mcp_url, credentials, password, secret, client_secret. There is no substring or shape-based secret detection. Objects at depth 6 become [TRUNCATED]; repeated or circular references become [CIRCULAR]. Redaction creates a copy for hooks and does not rewrite VinkiusError.details.

Timeouts, retries, and idempotency

Timeout scope. Each attempt gets a new timeoutMs timer covering the fetch promise. It is cleared before response-body reading and does not cover response.text() or retry backoff, so retries do not share one total deadline. Pass signal for caller-controlled cancellation: a caller abort during fetch is not retried and normally becomes ConnectionError.

Retry policy. With defaults, a retry-safe operation makes at most three attempts. An operation is retry-safe when its HTTP method is GET, PUT, or DELETE, or when the SDK explicitly marks it retry-safe: user creation, connection creation, or capability execution with a defined idempotencyKey. Retry-safe operations retry after a network error, a per-attempt timeout, or HTTP 429, 502, 503, or 504. PATCH and ordinary POST requests are not retried.

Backoff uses full jitter over an exponential window: 250 ms initially, capped at 4,000 ms. Retry-After (delta-seconds or an HTTP date) takes precedence, also capped at 4,000 ms. maxRetries changes the retry count, not these delay values.

Errors and request IDs

typescript
class VinkiusError extends Error {
  readonly status: number;
  readonly code: VinkiusErrorCode;
  readonly requestId: string | undefined;
  readonly details: unknown;
}

Client-side and transport errors use status 0. Terminal HTTP failures include the parsed API response in details.

ClasscodeSourceExtra fields
ConfigErrorconfig_errorInvalid client configuration or external IDnone
AuthErrorauth_errorHTTP 401 or 403none
NotFoundErrornot_foundHTTP 404none
ValidationErrorvalidation_errorHTTP 422errors: Record<string, string[]>
RateLimitErrorrate_limitHTTP 429 without the capability quota shaperetryAfterMs?: number
QuotaErrorquota_exceededHTTP 429 with isError: true or an upgrade_urlupgradeUrl?: string
OverageErroroverage_blockedHTTP 402upgradeUrl?: string
ConnectorNotConnectedErrorconnector_not_connectedA fluent operation requires a missing connectionnone
ConnectionErrorconnection_errorNetwork failure, timeout, or caller abort during fetchnone
VinkiusErrorapi_errorOther non-success HTTP statusnone

For HTTP responses, the client reads the first non-empty request ID from x-request-id, then x-vinkius-request-id. The value reaches onResponse and the final mapped HTTP error; successful resource values do not include it. Client-side and transport errors normally have no request ID. See Error handling for control-flow patterns.

ResolverCache

ResolverCache is a standalone in-memory TTL cache for non-secret, stable data. The client does not use it internally.

typescript
class ResolverCache {
  constructor(ttlMs?: number); // Default: 5 minutes.

  get<V>(key: string): V | undefined;
  set<V>(key: string, value: V): void;
  delete(key: string): void;
  clear(): void;
  resolve<V>(key: string, compute: () => Promise<V>): Promise<V>;
}
typescript
import { ResolverCache } from '@vinkius/connect';

const cache = new ResolverCache(10 * 60 * 1000);
const schema = await cache.resolve('github:schema', () =>
  user.connector('github').credentials.schema(),
);

Expired entries are deleted on get(). resolve() computes and stores a missing value only after the promise fulfills; rejections are not cached, and concurrent misses are not coalesced. A cached undefined is indistinguishable from a miss. Do not cache credentials, tokens, authorization headers, or other secrets: the cache is an optimization, not an authorization source.

Adapter reference

All adapters accept readonly Capability[] and use capability display names in generated definitions. An empty input schema is normalized to { type: 'object', properties: {} }. Adapters do not validate capability arguments locally; validation belongs to the called service.

Dispatch helpers and generated execution callbacks call capability.execute(args) without ExecuteOptions: they cannot receive a signal or idempotency key. Call Capability.execute(args, options) or ExecutionClient.execute(input, options) directly when you need cancellation or retry-safe execution.

  • toOpenAITools(capabilities) returns OpenAIFunctionTool[]; runOpenAIToolCall(capabilities, call) matches the display name only. Empty, malformed, null, or primitive JSON argument strings become {}; an unknown name throws plain Error.
  • toAnthropicTools / runAnthropicToolUse: display-name matching only; unknown names throw plain Error.
  • toAISDKTools(capabilities, { jsonSchema? }) returns a record keyed by display name; a duplicate display name overwrites the previous entry. Without the injected wrapper, parameters is the raw normalized JSON Schema. Each generated execute(args) returns CapabilityResult.
  • toGeminiTools / runGeminiFunctionCall: missing arguments become {}; unknown names throw plain Error.
  • toLangChainTools(capabilities, { tool }) and toOpenAIAgentsTools(capabilities, { tool }) require the caller's factory and are generic over its return type. Their generated callbacks join result text parts with a newline and do not preserve isError or content-part types. The Agents adapter passes normalized raw JSON Schema with strict: false.
  • toLlamaIndexTools(capabilities, { tool }) accepts raw JSON Schema, so no Zod is required.
  • toWorkersAITools(capabilities) returns plain objects with bound execution functions.
  • toJSONSchemaTools(capabilities) emits { name, description, parameters }; executeByName(capabilities, name, args) matches display or raw name, with first-match ambiguity for duplicate raw names. Unknown names throw plain Error.

Next steps