openvibe-sdk/exchange
Generated at from
openvibe-contracts v0.419.0 and
openvibe-sdk v0.161.0.
From types/exchange.d.ts (server only). Declarations are shown verbatim.
class ExchangeError
OpenVibe.Exchange: the buyer side (chat, models, offers, presets, usage, receipts) and the seller side.
export declare class ExchangeError extends Error {
constructor(message: string, init?: { status?: number | null; code?: string | null; body?: unknown; retryAfter?: number | null });
status: number | null;
code: string | null;
body: unknown;
retryAfter: number | null;
/** No status, 5xx, 429 or 401. */
readonly retryable: boolean;
}type ExchangePaths
Where each call goes; a deployment may point another one at these paths.
export type ExchangePaths = {
chat?: string;
models?: string;
receipts?: string;
presets?: string;
catalog?: string;
catalogModels?: string;
usage?: string;
platformUsage?: string;
sell?: string;
sellerOffers?: string;
offerReport?: string;
offerList?: string;
computePrices?: string;
};type ExchangeOptions
export type ExchangeOptions = {
/** The Network developer key (Bearer) the buyer side speaks with. */
developerKey?: string;
/** The key used on the Network's origin when the seller side reports an offer; defaults to the developer key. */
networkKey?: string;
/** The Exchange's origin; default https://api.openvibe.exchange. */
baseUrl?: string;
/** The Network's origin, where the user-owned AI offers live; default https://api.openvibe.network. */
networkUrl?: string;
/** Exchange's public site, where the compute price book lives; default https://openvibe.exchange. */
siteUrl?: string;
fetchImpl?: typeof fetch;
/** Per request, default 60000. */
timeoutMs?: number;
/** How many times a 429 or a 5xx is retried, default 3. */
maxRetries?: number;
/** The first backoff before the jitter, in ms; default 250. */
retryBaseMs?: number;
/** The seller subject (usr_...), used by the seller side when a call names no other owner. */
owner?: string;
paths?: ExchangePaths;
/** The User-Agent the calls carry. */
agent?: string;
};type ComputePriceKind
export type ComputePriceKind = 'cpu' | 'gpu';interface ComputePrice
export interface ComputePrice {
id: string;
provider: string;
region?: string | null;
kind: ComputePriceKind;
cpu?: number | null;
ram_mb?: number | null;
gpu?: string | null;
gpu_mb?: number | null;
currency: string;
hourly: number;
per_second: number;
billing_seconds?: number | null;
promotion?: string | null;
promotion_expires?: string | null;
interruptible?: boolean;
checked_at: string;
/** Epoch milliseconds. */
expires_at: number;
source: string;
[field: string]: unknown;
}interface ComputePriceBook
export interface ComputePriceBook {
checked_at: string;
prices: ComputePrice[];
[field: string]: unknown;
}interface ComputePriceOptions
export interface ComputePriceOptions {
/** Only this kind: a computer (cpu) or a GPU. */
kind?: ComputePriceKind;
}interface ComputePriceClient
export interface ComputePriceClient {
computePrices(query?: ComputePriceOptions, opts?: { signal?: AbortSignal }): Promise<ComputePriceBook>;
}type ExchangeChatRequest
export type ExchangeChatRequest = {
model: string;
messages: { role: string; content: string | unknown[] | null; [field: string]: unknown }[];
stream?: boolean;
stream_options?: { include_usage?: boolean };
temperature?: number;
max_tokens?: number;
max_completion_tokens?: number;
tools?: unknown[];
tool_choice?: unknown;
[field: string]: unknown;
};type ExchangeUsage
export type ExchangeUsage = {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};type ExchangeChatCompletion
export type ExchangeChatCompletion = {
id: string;
object: 'chat.completion' | string;
created: number;
model: string;
choices: { index: number; message: { role: string; content: string | null; tool_calls?: unknown[] }; finish_reason: string | null }[];
usage: ExchangeUsage;
system_fingerprint?: string | null;
x_openvibe?: { run_id: string; provider?: string; fallback_used?: boolean; cost_usd?: number; synthetic?: boolean };
};type ExchangeChatChunk
export type ExchangeChatChunk = {
id: string;
object: 'chat.completion.chunk' | string;
created: number;
model: string;
choices: { index: number; delta: { role?: string; content?: string | null; tool_calls?: unknown[] }; finish_reason: string | null }[];
usage?: ExchangeUsage;
x_openvibe?: { run_id: string; provider?: string; fallback_used?: boolean; cost_usd?: number; synthetic?: boolean };
};type ExchangeModel
export type ExchangeModel = { id: string; object: 'model' | string; created?: number; owned_by?: string; [field: string]: unknown };type ExchangeModelList
export type ExchangeModelList = { object: 'list'; data: ExchangeModel[] };type ExchangeOffer
export type ExchangeOffer = {
provider: string;
provider_name?: string;
model: string;
id?: string | null;
trust: 'community' | 'first-party' | string;
access?: string;
free?: boolean;
price?: { in: number; out: number; cached?: number; per: string; currency: string } | null;
speed?: { p50_ms: number | null; p95_ms: number | null };
uptime?: number | null;
requests_7d?: number;
requests_today?: number;
data_policy?: { trains: boolean | null; retention_days: number | null; region: string | null } | null;
updated_at?: string | null;
[field: string]: unknown;
};type ExchangeModelDoc
export type ExchangeModelDoc = {
slug: string;
canonical: string;
name: string;
family?: string;
type?: string;
context?: number | null;
max_output?: number | null;
capabilities?: { tools: boolean; json: boolean; vision: boolean; stream: boolean };
modalities?: string[];
community?: boolean;
priced?: boolean;
offers: ExchangeOffer[];
[field: string]: unknown;
};type ExchangeCatalog
export type ExchangeCatalog = {
generated_at: string;
window_days: number;
count: number;
families?: { name: string; models: number; offers: number }[];
models: ExchangeModelDoc[];
};type ExchangePresetPolicy
export type ExchangePresetPolicy = {
objective?: 'cheapest' | 'fastest' | 'balanced' | 'private';
floor?: 'fast' | 'balanced' | 'strong' | 'frontier';
ceiling?: number;
max_price?: number;
quantization?: string[];
region?: string[];
data_policy?: 'private' | 'anonymized' | 'community';
community?: boolean;
adult?: boolean;
[field: string]: unknown;
};type ExchangePreset
export type ExchangePreset = {
name: string;
description?: string | null;
policy: ExchangePresetPolicy;
builtin?: boolean;
[field: string]: unknown;
};type ExchangeUsageAggregate
export type ExchangeUsageAggregate = {
generated_at: string;
days: number;
from: string;
to: string;
today: { requests: number; tokens_in: number; tokens_out: number; cost_usd: number };
totals: { requests: number; tokens_in: number; tokens_out: number; cost_usd: number };
by_day: { day: string; requests: number; tokens_in: number; tokens_out: number; cost_usd: number }[];
by_model: { provider: string; model: string | null; requests: number; tokens_in: number; tokens_out: number; cost_usd: number }[];
by_product: { product: string; requests: number; tokens_in: number; tokens_out: number; cost_usd: number; models?: unknown[] }[];
[field: string]: unknown;
};type ExchangeReceipt
export type ExchangeReceipt = {
id: string;
run_id?: string;
offer?: { provider: string; model: string | null; deployment?: string | null; access?: string; provider_access?: string | null; local?: boolean; community?: 'machine' | 'endpoint' | null };
price?: { in: number | null; out: number | null; cached?: number | null; source?: string | null };
tokens?: { tokens_in: number; tokens_out: number; tokens_cached?: number; tokens_cache_write?: number; tokens_reasoning?: number };
latency_ms?: number | null;
why?: string[];
fallbacks?: { offer: string; provider?: string | null; model?: string | null; why?: string | null; status?: string; reason?: string | null }[];
paid_by?: { paid_by: string; detail?: string | null; fee_rate?: number | null };
privacy?: { label: string; [field: string]: unknown } | string;
preset?: string | null;
created_at?: string;
[field: string]: unknown;
};type ExchangeOfferDocument
The offer document the Network's user-owned AI offers registry validates.
export type ExchangeOfferDocument = {
offer_id: string;
machine_id: string;
owner: string;
models: string[];
hours: { start: string; end: string; tz: string };
concurrency: number;
price: { in_per_million: number; out_per_million: number };
audience: 'everyone' | 'followers' | 'group';
group?: string;
ready: boolean;
health: { status: 'up' | 'degraded' | 'down'; checked_at: string };
};type ExchangeOfferInput
export type ExchangeOfferInput = {
/** The model served; models may name several. */
model?: string;
models?: string[];
/** Credits per million tokens: a number for both sides, or {in_per_million, out_per_million}. */
price: number | { in_per_million?: number; out_per_million?: number; in?: number; out?: number };
/** The local window the offer is open: {start, end, tz}; start == end is all day. */
hours: { start: string; end: string; tz?: string };
/** How many answers may run at once, 1 to 8. */
concurrency: number;
/** The OpenAI-compatible server that serves the model. */
endpoint?: string;
/** The key the endpoint needs, when it needs one. */
endpointKey?: string;
/** The machine the offer belongs to (dev_...). */
machineId: string;
/** The owner (usr_...); defaults to the client's owner. */
owner?: string;
audience?: 'everyone' | 'followers' | 'group';
/** The group id, required for the group audience. */
group?: string;
ready?: boolean;
health?: { status: 'up' | 'degraded' | 'down'; checked_at?: string };
/** The reporter name; the registry keeps one set of offers per source. */
source?: string;
/** Whether the endpoint is asked for its model list first; default true. */
probe?: boolean;
};type ExchangeOfferResult
export type ExchangeOfferResult = {
offer: ExchangeOfferDocument;
report: { source: string; offers: number; marked_down: number; generated_at?: string };
endpoint: { url: string; models: string[] | null } | null;
};type ExchangeEndpointOfferInput
A standalone OpenAI-compatible server registered on the Exchange's public seller API. The key names the owner.
export type ExchangeEndpointOfferInput = {
/** The https base URL, e.g. https://my-server.example/v1; /chat/completions is appended. */
endpoint: string;
/** The model served; models may name several. */
model?: string;
models?: string[];
/** Credits per million tokens: a number for both sides, or {in_per_million, out_per_million}; 0 volunteers. */
price: number | { in_per_million: number; out_per_million: number };
/** The local window the offer is open: {start, end, tz}; start == end is all day. */
hours: { start: string; end: string; tz?: string };
/** How many answers may run at once, 1 to 8. */
concurrency: number;
audience?: 'everyone' | 'followers' | 'group';
/** The group id, required for the group audience. */
group?: string;
/** A label for the seller's own dashboard. */
name?: string;
/** The key the endpoint needs for the probe, when it needs one. AI sends no key. */
endpointKey?: string;
/** Whether the endpoint is asked for its model list first; default true. */
probe?: boolean;
};type ExchangeEndpointOffer
export type ExchangeEndpointOffer = {
id: string;
offer_id: string;
name: string | null;
base_url: string;
models: string[];
hours: { start: string; end: string; tz: string };
concurrency: number;
price: { in_per_million: number; out_per_million: number };
audience: 'everyone' | 'followers' | 'group';
group: string | null;
created_at?: string;
updated_at?: string;
verification?: ExchangeSellerVerification | null;
reputation?: number;
free_only?: boolean;
verified?: boolean;
};type ExchangeEndpointOfferResult
export type ExchangeEndpointOfferResult = {
offer: ExchangeEndpointOffer;
endpoint: { url: string; models: string[] | null };
};type ExchangeSellerVerification
export type ExchangeSellerVerification = {
status: 'new' | 'verified' | 'failed' | 'paused' | string;
canary_passes: number;
canary_failures: number;
spot_runs: number;
spot_failures: number;
failure_rate?: number;
last_canary_at?: string | null;
last_spot_at?: string | null;
first_verified_at?: string | null;
failure_reason?: string | null;
};type ExchangeSellerOffer
export type ExchangeSellerOffer = {
offer_id: string;
machine_id: string;
models: string[];
hours?: { start: string; end: string; tz: string } | null;
concurrency?: number | null;
price?: { in_per_million: number; out_per_million: number };
audience?: string | null;
group?: string | null;
health?: string | null;
open_now?: boolean | null;
ready: boolean;
verification: ExchangeSellerVerification | null;
verified: boolean;
reputation: number;
free_only: boolean;
uptime_pct?: number | null;
tokens_per_s?: number | null;
};type ExchangeEarnings
export type ExchangeEarnings = {
owner: string;
generated_at: string;
offers: ExchangeSellerOffer[];
totals: {
requests: number;
tokens_in: number;
tokens_out: number;
pending_credits_micro: number;
spendable_credits_micro: number;
self_served_requests: number;
};
kudos?: number;
note?: string;
[field: string]: unknown;
};type ExchangeKey
export type ExchangeKey = { id: string; name: string; prefix: string; monthly_cap_usd: number; allowed_models: string[]; created_at: string; revoked_at: string | null };type ExchangeSearchOptions
export type ExchangeSearchOptions = { engine?: string; limit?: number; license?: string; commercial?: boolean; format?: string; orientation?: string; size?: 'small' | 'medium' | 'large'; color?: 'black_and_white' | 'black' | 'white' | 'yellow' | 'orange' | 'red' | 'purple' | 'magenta' | 'green' | 'teal' | 'blue'; type?: 'icon' | 'photo' | 'illustration' | 'vector'; after?: string; safe_search?: 'strict'; style?: 'line' | 'solid' | 'any'; set?: string; signal?: AbortSignal };interface CatalogSearchFilters
export interface CatalogSearchFilters { provider?: string; capability?: string; min_price?: number; max_price?: number; max_speed_ms?: number; sort?: 'relevance' | 'price' | 'speed' | 'quality'; rating_kind?: string; }interface CatalogModelResult
export interface CatalogModelResult { model: string; name: string; family: string | null; capabilities: Record<string, boolean>; provider: string; price: { in: number; out: number; cached?: number; per?: string; currency?: string } | null; speed: { p50_ms?: number; p95_ms?: number; tokens_per_second?: number } | null; quality: { elo: number; games: number; kind: string } | null; offers: number; task_match: string | null; score: number; }interface CatalogSearchResponse
export interface CatalogSearchResponse { q: string; count: number; results: CatalogModelResult[]; quality_unavailable: boolean; }function createCatalogSearchClient
export declare function createCatalogSearchClient(options?: { baseUrl?: string; fetchImpl?: typeof fetch }): { search(q: string, filters?: CatalogSearchFilters, options?: { signal?: AbortSignal }): Promise<CatalogSearchResponse> };type ExchangeSearchResult
export type ExchangeSearchResult = { results: Array<{ title: string; url: string; snippet: string; engine: string; published: string | null; indexed_on?: string | null; type?: string | null; thumbnail?: string | null; license?: string | null; license_url?: string | null; author?: string | null; author_url?: string | null; source_page?: string | null; attribution?: string | null; width?: number | null; height?: number | null }>; receipt: { engine: string; cost_usd: number; time_ms: number } };type ExchangeClient
export type ExchangeClient = {
keys: {
list(opts?: { signal?: AbortSignal }): Promise<{ keys: ExchangeKey[] }>;
create(input: { name: string; monthly_cap_usd: number; allowed_models: string[] }, opts?: { signal?: AbortSignal }): Promise<{ key: ExchangeKey; secret: string }>;
revoke(id: string, opts?: { signal?: AbortSignal }): Promise<{ id: string; revoked: boolean }>;
};
keyUsage(opts?: { signal?: AbortSignal }): Promise<{ rows: Array<{ day: string; key_id: string; model: string; requests: number; tokens_in: number; tokens_out: number; cost_usd: number; status: string }> }>;
deployments: {
list(opts?: { signal?: AbortSignal }): Promise<{ endpoints: unknown[]; status: unknown }>;
create(input: { model: string; idle_minutes?: number }, opts?: { signal?: AbortSignal }): Promise<unknown>;
stop(id: string, opts?: { signal?: AbortSignal }): Promise<unknown>;
};
search: ((q: string, opts?: ExchangeSearchOptions) => Promise<ExchangeSearchResult>) & { icons(q: string, opts?: ExchangeSearchOptions): Promise<ExchangeSearchResult> };
images(q: string, opts?: ExchangeSearchOptions): Promise<ExchangeSearchResult>;
fetch(url: string, opts?: { signal?: AbortSignal }): Promise<{ url: string; text: string; receipt: ExchangeSearchResult['receipt'] }>;
arena: {
start(input: { prompt: string; category?: string; entries: unknown[] }, options?: { signal?: AbortSignal }): Promise<unknown>;
vote(roundId: string, choice: 'left' | 'right' | 'tie' | 'both_bad', options?: { signal?: AbortSignal }): Promise<unknown>;
};
/** One chat completion; stream: true answers an async iterable of chunks. */
chat(body: ExchangeChatRequest, opts?: { signal?: AbortSignal }): Promise<ExchangeChatCompletion | AsyncIterable<ExchangeChatChunk>>;
/** The models the Exchange can serve. */
models(opts?: { signal?: AbortSignal }): Promise<ExchangeModelList>;
/** The offers that serve one model. */
offers(model: string, opts?: { signal?: AbortSignal }): Promise<ExchangeOffer[]>;
/** The whole public catalog. */
catalog(opts?: { signal?: AbortSignal }): Promise<ExchangeCatalog>;
/** The reviewed compute tariffs, keyless from the public site; `kind` filters the list. */
computePrices(query?: ComputePriceOptions, opts?: { signal?: AbortSignal }): Promise<ComputePriceBook>;
presets: {
list(opts?: { signal?: AbortSignal }): Promise<ExchangePreset[]>;
create(input: { name: string; policy: ExchangePresetPolicy }, opts?: { signal?: AbortSignal }): Promise<ExchangePreset>;
/** The platform has no PATCH: a preset is stored under its name, so a second POST replaces it. */
update(name: string, input: { policy: ExchangePresetPolicy }, opts?: { signal?: AbortSignal }): Promise<ExchangePreset>;
remove(name: string, opts?: { signal?: AbortSignal }): Promise<unknown>;
};
/** Private key usage by default; days or scope public requests aggregates. */
usage(query?: { scope?: 'mine' | 'public'; days?: number; from?: string; to?: string; requester?: string }, opts?: { signal?: AbortSignal }): Promise<ExchangeUsageAggregate | { usage: unknown } | { rows: unknown[] }>;
/** The receipt of one answered request. */
receipt(id: string, opts?: { signal?: AbortSignal }): Promise<ExchangeReceipt>;
seller: {
/** Register a Link machine's offer in the Network's user-owned AI offers, or an endpoint with the Exchange. */
offer(input: ExchangeOfferInput, opts?: { signal?: AbortSignal }): Promise<ExchangeOfferResult>;
offer(input: ExchangeEndpointOfferInput, opts?: { signal?: AbortSignal }): Promise<ExchangeEndpointOfferResult>;
/** The caller's own endpoint offers, with their verification. */
endpointOffers(opts?: { signal?: AbortSignal }): Promise<{ owner: string; offers: ExchangeEndpointOffer[] }>;
/** Remove one of the caller's endpoint offers. */
removeEndpointOffer(id: string, opts?: { signal?: AbortSignal }): Promise<{ id: string; removed: boolean }>;
/** The model list at an OpenAI-compatible endpoint. */
probe(input: { endpoint: string; key?: string | null }, opts?: { signal?: AbortSignal }): Promise<{ models: string[] }>;
/** The seller dashboard: the tokens served, the credits earned, the uptime and the verification. */
earnings(opts?: { owner?: string } & { signal?: AbortSignal }): Promise<ExchangeEarnings>;
/** The verification, the reputation and the uptime of every offer. */
verification(opts?: { owner?: string } & { signal?: AbortSignal }): Promise<{ owner: string | null; generated_at: string | null; offers: ExchangeSellerOffer[] }>;
/** The offers the Network holds, whole. */
offers(opts?: { owner?: string; source?: string } & { signal?: AbortSignal }): Promise<{ offers: ExchangeOfferDocument[]; count?: number; generated_at?: string }>;
};
webhooks: {
/** Constant-time check of the RAW body against X-OpenVibe-Signature-V2 (or a legacy sha256= header). */
verify(rawBody: string | Uint8Array | ArrayBufferView, signatureHeader: string, secret: string, opts?: { toleranceSec?: number; now?: number }): boolean;
};
baseUrl(): string;
networkUrl(): string;
};function createExchangeClient
export declare function createExchangeClient(options?: ExchangeOptions): ExchangeClient;function createComputePriceClient
export declare function createComputePriceClient(options?: { baseUrl?: string; fetchImpl?: typeof fetch; timeoutMs?: number; maxRetries?: number; retryBaseMs?: number; agent?: string }): ComputePriceClient;function verifyWebhook
The same check as exchange.webhooks.verify, for a receiver that only verifies webhooks.
export declare function verifyWebhook(rawBody: string | Uint8Array | ArrayBufferView, signatureHeader: string, secret: string, opts?: { toleranceSec?: number; now?: number }): boolean;const SIGNATURE_TOLERANCE_SEC
export declare const SIGNATURE_TOLERANCE_SEC: number;const EXCHANGE_BASE_URL
export declare const EXCHANGE_BASE_URL: string;const NETWORK_BASE_URL
export declare const NETWORK_BASE_URL: string;const DEFAULT_PATHS
export declare const DEFAULT_PATHS: Required<ExchangePaths>;const RETRY_STATUS
export declare const RETRY_STATUS: ReadonlySet<number>;