@aerocert/sdk
v0.2.0
Published
Official TypeScript SDK for the AeroCert blockchain certification API
Downloads
255
Maintainers
Readme
@aerocert/sdk
Official TypeScript SDK for the AeroCert blockchain certification API.
Anchor documents, verify certificates, manage batches, and validate webhooks — all with full type safety, automatic retries, and zero runtime dependencies.
Installation
npm install @aerocert/sdkRequires Node.js ≥ 18 (uses native
fetchandcrypto).
Quick Start
import { AeroCert } from '@aerocert/sdk';
const client = new AeroCert({ apiKey: 'ak_live_...' });
const cert = await client.certify({
dataToAnchor: {
type: 'maintenance_record',
aircraft: 'F-BPVJ',
component: 'Engine #1 overhaul',
performedBy: 'MbAviation',
date: '2025-06-15',
},
});
console.log(cert.certificateNumber); // "CERT-2025-00042"
console.log(cert.publicQrUrl); // "https://api.aerocert.co/api/v1/public/qr/..."
console.log(cert.transactionHash); // "0x3fa8e..."
console.log(cert.shareUrl); // "https://share.aerocert.co/CERT-2025-00042"Constructor
const client = new AeroCert({
apiKey: 'ak_live_...', // Required — your API key
baseUrl: 'https://...', // Optional — defaults to https://api.aerocert.co
maxRetries: 3, // Optional — automatic retries for 429/502 (default: 3)
});| Option | Type | Default | Description |
| ------------ | -------- | ---------------------------- | ---------------------------------------------- |
| apiKey | string | — | API key for X-API-Key header authentication |
| baseUrl | string | https://api.aerocert.co | AeroCert API base URL |
| maxRetries | number | 3 | Max retries on 429 (rate limit) and 502 errors |
Methods
certify(request): Promise<CertifyResponse>
Anchor data on the blockchain and receive a certificate.
const cert = await client.certify({
dataToAnchor: { invoice: 'INV-2025-001', amount: 15000, currency: 'EUR' },
});
// cert.publicQrUrl goes in the QR. verificationUrl is the final public destination.Parameters:
| Field | Type | Description |
| ---------------------- | ------------------------- | -------------------------------------------------------- |
| dataToAnchor | Record<string, unknown> | Free-form JSON to hash and anchor |
| modelId | string | Document model UUID (alternative to dataToAnchor) |
| values | Record<string, unknown> | Field values for the document model |
| clientReference | string | Your internal reference |
| schema | string | Schema identifier for the canonical hash |
| organizationWalletId | string | Specific wallet UUID |
| expiresAt | string | ISO-8601 expiry timestamp |
An Idempotency-Key header is auto-generated for safe retries.
Important:
publicQrUrlis the canonical URL to encode in a QR codeverificationUrlis the final public destination after routing
certifyBatch(request): Promise<BatchResponse>
Submit an asynchronous batch anchoring job.
const batch = await client.certifyBatch({
items: [
{ dataToAnchor: { part: 'Landing gear', serial: 'LG-001' } },
{ dataToAnchor: { part: 'Avionics unit', serial: 'AV-002' } },
],
webhookUrl: 'https://your-app.com/webhooks/aerocert',
});
// batch.batchId, batch.status === 'pending'An idempotencyKey is auto-generated if not provided.
waitForBatch(batchId, options?): Promise<BatchResponse>
Poll a batch until it reaches a terminal status (completed, failed, or aborted).
const result = await client.waitForBatch(batch.batchId, {
pollInterval: 2000, // ms between polls (default: 2000)
timeout: 60000, // max wait time in ms (default: 60000)
onProgress: (b) => console.log(`${b.status} — ${b.progress}%`),
});
for (const item of result.items!) {
console.log(item.certificateNumber, item.transactionHash);
}Throws AeroCertError with code: 'BATCH_TIMEOUT' if the deadline is exceeded.
verify(query): Promise<VerifyResponse>
Verify a certificate or transaction hash via public search.
const verification = await client.verify('CERT-2025-00042');
console.log(verification.data.verificationStatus); // "valid"This endpoint is public — no API key is sent. Anyone can verify a certificate.
downloadPdf(anchorId): Promise<ArrayBuffer>
Download the PDF certificate for an anchor.
import { writeFile } from 'node:fs/promises';
const pdf = await client.downloadPdf(42);
await writeFile('certificate.pdf', Buffer.from(pdf));AeroCert.verifyWebhookSignature(params): boolean (static)
Verify the HMAC-SHA256 signature of an incoming AeroCert webhook.
import { AeroCert } from '@aerocert/sdk';
// Express middleware example
app.post('/webhooks/aerocert', express.raw({ type: 'application/json' }), (req, res) => {
const isValid = AeroCert.verifyWebhookSignature({
payload: req.body,
secret: process.env.AEROCERT_WEBHOOK_SECRET!,
headers: {
'x-aerocert-webhook-id': req.headers['x-aerocert-webhook-id'] as string,
'x-aerocert-webhook-timestamp': req.headers['x-aerocert-webhook-timestamp'] as string,
'x-aerocert-webhook-signature': req.headers['x-aerocert-webhook-signature'] as string,
},
});
if (!isValid) {
return res.status(401).json({ error: 'Invalid webhook signature' });
}
const event = JSON.parse(req.body.toString());
console.log('Webhook event:', event.event, event.data);
res.sendStatus(200);
});Important: Use
express.raw()(notexpress.json()) to get the raw body for signature verification. If your framework parses the body first, use thestableStringifyutility to reconstruct the canonical form.
stableStringify(value): string
Deterministic JSON serialization that sorts object keys. Use this to reconstruct the canonical body when your framework parses the JSON before you can access the raw bytes.
import { stableStringify } from '@aerocert/sdk';
// Reconstruct canonical form from parsed JSON
const canonical = stableStringify(parsedBody);Error Handling
All API errors are thrown as typed AeroCertError instances with diagnostic metadata:
import { AeroCert, AeroCertError, RateLimitError } from '@aerocert/sdk';
try {
await client.certify({ dataToAnchor: { ... } });
} catch (err) {
if (err instanceof RateLimitError) {
console.log(`Rate limited — retry after ${err.retryAfter}s`);
// Note: retries are automatic up to maxRetries. This only fires
// when all retries are exhausted.
} else if (err instanceof AeroCertError) {
console.error(`API error [${err.code}]: ${err.message}`);
console.error(`Status: ${err.statusCode}, Request ID: ${err.requestId}`);
if (err.details) console.error('Details:', err.details);
}
}| Property | Type | Description |
| ------------ | ------------------- | ------------------------------------------------- |
| code | string | Machine-readable error code (e.g. INVALID_REQUEST) |
| message | string | Human-readable error message |
| statusCode | number | HTTP status code |
| requestId | string \| undefined | Server-assigned request identifier |
| details | unknown | Structured validation errors, etc. |
Automatic Retries
The client automatically retries on:
- 429 Too Many Requests — waits the
Retry-Afterduration (or 1s fallback) - 502 Bad Gateway — exponential backoff with jitter (1s, 2s, 4s…)
All other errors (400, 401, 403, 404, 422, 500, etc.) are thrown immediately. Configure maxRetries in the constructor (default: 3, set to 0 to disable).
Batch Processing Example
Full MbAviation-pattern flow:
import { AeroCert } from '@aerocert/sdk';
const client = new AeroCert({ apiKey: process.env.AEROCERT_API_KEY! });
// 1. Submit batch
const batch = await client.certifyBatch({
items: maintenanceRecords.map(record => ({
dataToAnchor: {
aircraft: record.aircraft,
component: record.component,
performedBy: record.technician,
date: record.date,
},
})),
});
console.log(`Batch ${batch.batchId} submitted (${batch.totalItems} items)`);
// 2. Wait for completion
const result = await client.waitForBatch(batch.batchId, {
timeout: 120_000,
onProgress: (b) => console.log(`Progress: ${b.progress ?? 0}%`),
});
// 3. Process results
for (const item of result.items ?? []) {
if (item.status === 'anchored') {
console.log(`✅ ${item.certificateNumber} — ${item.shareUrl}`);
} else {
console.error(`❌ Item ${item.index}: ${item.error}`);
}
}TypeScript Types
All request/response types are exported for full type safety:
import type {
AeroCertConfig,
CertifyRequest,
CertifyResponse,
CertifyBatchRequest,
CertifyBatchItem,
BatchResponse,
BatchStatus,
BatchItemResult,
WaitForBatchOptions,
VerifyResponse,
VerifyWebhookSignatureParams,
WebhookHeaders,
} from '@aerocert/sdk';API Documentation
For full API reference, see the AeroCert API Docs.
License
MIT
