TypeScript SDK
Node and browser: services, chat, streaming, audio and usage.
Configure the client
PuraInferenceClient takes apiBase ending in /v1, clientId and the grant’s TokenStore. clientSecret is only used on a confidential backend. Optional fetch adapts transport; preserve HTTPS, headers and contract bodies in production.
import {PuraInferenceClient} from '@pura-ai/sdk';
const pura = new PuraInferenceClient({
apiBase: 'https://ai.puradigital.it/v1',
clientId: process.env.PURA_CLIENT_ID!,
clientSecret: process.env.PURA_CLIENT_SECRET!,
store: userTokenStore,
});
const capabilities = await pura.capabilities();
const usage = await pura.usage();Inference methods
capabilities() returns services.chat and services.audio_transcription. chat(body) returns the response JSON. streamChat(body) returns a Response with an SSE ReadableStream; handle parsing and cancellation. transcribe(options) returns text. usage() exposes account percentages. None of these methods selects a model.
Consume the stream
The reader receives chunks, not complete events: a chunk boundary does not necessarily match an SSE line. Decode with streaming TextDecoder and maintain a buffer until an event separator. Close the reader when the user stops.
const response = await pura.streamChat({
messages: [{role: 'user', content: 'Hello'}],
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const {done, value} = await reader.read();
if (done) break;
consumeSseChunk(decoder.decode(value, {stream: true}));
}
consumeSseChunk(decoder.decode());
} finally {
await reader.cancel();
reader.releaseLock();
}Typed errors
PuraError.status and PuraError.code distinguish authentication, revocation, limits and unavailability. The SDK refreshes tokens when needed; it does not switch provider, debit the wallet or automatically repeat inference with an ambiguous outcome.
import {PuraError} from '@pura-ai/sdk';
try {
await pura.chat({messages});
} catch (error) {
if (error instanceof PuraError && error.status === 402) {
showSubscriptionLimit(error.code);
} else {
throw error;
}
}