TypeScript SDK
The official TypeScript SDK for Cohera provides a fully typed, Promise-based interface to the Cohera API.
Installation
Section titled “Installation”npm install @cohera/sdkOr with other package managers:
# Yarnyarn add @cohera/sdk
# pnpmpnpm add @cohera/sdk
# Bunbun add @cohera/sdkQuick Start
Section titled “Quick Start”import { Cohera } from '@cohera/sdk';
const client = new Cohera({ apiKey: 'ck_live_...' });
// List certificatesconst certificates = await client.certificates.list();
for (const cert of certificates) { console.log(`${cert.name} - Expires: ${cert.expiryDate}`);}Configuration
Section titled “Configuration”Authentication
Section titled “Authentication”import { Cohera } from '@cohera/sdk';
// Via environment variable (recommended)const client = new Cohera();// Reads from COHERA_API_KEY
// Via constructorconst client = new Cohera({ apiKey: 'ck_live_...' });import { Cohera } from '@cohera/sdk';
const client = new Cohera({ accessToken: 'eyJ...' });Client Options
Section titled “Client Options”import { Cohera } from '@cohera/sdk';
const client = new Cohera({ apiKey: 'ck_live_...', baseUrl: 'https://api.cohera.io', // Custom base URL timeout: 30000, // Request timeout in ms maxRetries: 3, // Retry failed requests debug: true, // Enable debug logging});Resources
Section titled “Resources”Certificates
Section titled “Certificates”// List all certificatesconst certificates = await client.certificates.list();
// List with filtersconst certificates = await client.certificates.list({ supplierId: 'sup_abc123', status: 'active', expiresBefore: '2024-12-31',});
// Paginate resultsfor await (const cert of client.certificates.listAutoPaginate()) { console.log(cert.name);}
// Get a single certificateconst cert = await client.certificates.get('cert_abc123');
// Get with relationshipsconst cert = await client.certificates.get('cert_abc123', { include: ['supplier', 'components', 'products'],});
// Create a certificateconst cert = await client.certificates.create({ name: 'CoA - Batch 2024-001', supplierId: 'sup_abc123', certificateType: 'coa', expiryDate: '2025-06-30', documentUrl: 'https://...',});
// Update a certificateconst cert = await client.certificates.update('cert_abc123', { status: 'expired',});
// Delete a certificateawait client.certificates.delete('cert_abc123');Suppliers
Section titled “Suppliers”// List suppliersconst suppliers = await client.suppliers.list();
// Search suppliersconst suppliers = await client.suppliers.search('Acme');
// Get supplier with certificatesconst supplier = await client.suppliers.get('sup_abc123', { include: ['certificates', 'components'],});
// Create supplierconst supplier = await client.suppliers.create({ name: 'Acme Chemicals', email: 'contact@acme.com', status: 'approved',});Components
Section titled “Components”// List componentsconst components = await client.components.list();
// Get component with full graphconst component = await client.components.get('comp_abc123', { include: ['supplier', 'certificates', 'products', 'bom'],});
// Find components by certificateconst components = await client.components.list({ certificateId: 'cert_abc123',});Products
Section titled “Products”// List productsconst products = await client.products.list();
// Get product with BOMconst product = await client.products.get('prod_abc123', { include: ['bom', 'components', 'certificates'],});
// Impact analysis - find products affected by a certificateconst products = await client.products.list({ affectedByCertificate: 'cert_abc123',});TypeScript Features
Section titled “TypeScript Features”Full Type Safety
Section titled “Full Type Safety”import { Cohera, Certificate, Supplier } from '@cohera/sdk';
const client = new Cohera();
// Full IDE autocomplete and type checkingconst cert: Certificate = await client.certificates.get('cert_abc123');console.log(cert.name); // stringconsole.log(cert.expiryDate); // Dateconsole.log(cert.supplier); // Supplier
// Type-safe create/updateawait client.certificates.create({ name: 'Test', // Required supplierId: 'sup_...', // Required status: 'active', // "active" | "expired" | "pending"});Discriminated Unions
Section titled “Discriminated Unions”import { CertificateEvent } from '@cohera/sdk';
function handleEvent(event: CertificateEvent) { switch (event.type) { case 'certificate.created': // event.data is CreateEvent console.log('New certificate:', event.data.certificate.name); break; case 'certificate.expiring': // event.data is ExpiryEvent console.log('Days until expiry:', event.data.daysRemaining); break; case 'certificate.expired': // event.data is ExpiredEvent console.log('Certificate expired:', event.data.certificate.name); break; }}Generics
Section titled “Generics”import { Cohera, PaginatedResponse, Certificate } from '@cohera/sdk';
const client = new Cohera();
// Typed paginationconst page: PaginatedResponse<Certificate> = await client.certificates.list({ pageSize: 50, page: 1,});
console.log(page.data); // Certificate[]console.log(page.totalCount); // numberconsole.log(page.hasMore); // booleanFramework Integration
Section titled “Framework Integration”Next.js
Section titled “Next.js”import { Cohera } from '@cohera/sdk';import { NextResponse } from 'next/server';
const client = new Cohera();
export async function GET() { const certificates = await client.certificates.list(); return NextResponse.json(certificates);}Express
Section titled “Express”import express from 'express';import { Cohera } from '@cohera/sdk';
const app = express();const client = new Cohera();
app.get('/api/certificates', async (req, res) => { try { const certificates = await client.certificates.list(); res.json(certificates); } catch (error) { res.status(500).json({ error: error.message }); }});React Query
Section titled “React Query”import { useQuery, useMutation } from '@tanstack/react-query';import { Cohera } from '@cohera/sdk';
const client = new Cohera();
// Hook for listing certificatesexport function useCertificates() { return useQuery({ queryKey: ['certificates'], queryFn: () => client.certificates.list(), });}
// Hook for creating certificateexport function useCreateCertificate() { return useMutation({ mutationFn: (data: CreateCertificateParams) => client.certificates.create(data), });}Error Handling
Section titled “Error Handling”import { Cohera } from '@cohera/sdk';import { CoheraError, AuthenticationError, NotFoundError, RateLimitError, ValidationError,} from '@cohera/sdk/errors';
const client = new Cohera();
try { const cert = await client.certificates.get('cert_invalid');} catch (error) { if (error instanceof NotFoundError) { console.log(`Certificate not found: ${error.message}`); } else if (error instanceof RateLimitError) { console.log(`Rate limited. Retry after: ${error.retryAfter} seconds`); } else if (error instanceof AuthenticationError) { console.log(`Auth failed: ${error.message}`); } else if (error instanceof ValidationError) { console.log(`Validation error:`, error.errors); } else if (error instanceof CoheraError) { console.log(`API error: ${error.message}`); }}Webhooks
Section titled “Webhooks”Verify and parse webhook payloads:
import { Webhook } from '@cohera/sdk/webhooks';
const webhook = new Webhook({ secret: 'whsec_...' });
// Express middlewareapp.post('/webhooks/cohera', express.raw({ type: 'application/json' }), (req, res) => { try { const event = webhook.constructEvent( req.body, req.headers['x-cohera-signature'] as string );
switch (event.type) { case 'certificate.expiring': const { certificate, daysRemaining } = event.data; console.log(`${certificate.name} expires in ${daysRemaining} days`); break; }
res.json({ received: true }); } catch (error) { console.log('Webhook error:', error.message); res.status(400).send(`Webhook Error: ${error.message}`); }});Testing
Section titled “Testing”Use the mock client for testing:
import { MockCohera } from '@cohera/sdk/testing';
describe('Certificate Processing', () => { it('should process certificates', async () => { const client = new MockCohera();
// Configure mock responses client.certificates.mockList([ { id: 'cert_1', name: 'Test Cert', status: 'active' }, ]);
// Test your code const certs = await client.certificates.list(); expect(certs).toHaveLength(1); expect(certs[0].name).toBe('Test Cert'); });});Examples
Section titled “Examples”Certificate Expiry Monitor
Section titled “Certificate Expiry Monitor”import { Cohera } from '@cohera/sdk';
const client = new Cohera();
async function checkExpiringCertificates() { const threshold = new Date(); threshold.setDate(threshold.getDate() + 30);
const expiring = await client.certificates.list({ status: 'active', expiresBefore: threshold.toISOString(), });
for (const cert of expiring) { const daysLeft = Math.ceil( (cert.expiryDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24) ); console.log(`[${daysLeft} days] ${cert.name} - ${cert.supplier.name}`); }}
checkExpiringCertificates();Impact Analysis
Section titled “Impact Analysis”import { Cohera } from '@cohera/sdk';
const client = new Cohera();
async function analyzeImpact(certificateId: string) { const cert = await client.certificates.get(certificateId, { include: ['components', 'products'], });
console.log(`Certificate: ${cert.name}`); console.log(`Affects ${cert.components.length} components:`);
for (const component of cert.components) { console.log(` - ${component.name}`); for (const product of component.products) { console.log(` -> ${product.name} (${product.sku})`); } }}
analyzeImpact('cert_abc123');Browser Support
Section titled “Browser Support”The SDK works in all modern browsers. For older browsers, ensure you have polyfills for:
fetchPromiseAbortController
// Browser usage with bundlerimport { Cohera } from '@cohera/sdk';
const client = new Cohera({ apiKey: 'ck_live_...' });API Reference
Section titled “API Reference”For complete API documentation, see: