@metrasign/sdk
v0.3.0
Published
Minimal TypeScript SDK for the MetraSign public API — upload + certify documents and discover document types.
Downloads
203
Readme
@metrasign/sdk
Minimal TypeScript SDK for the MetraSign public API.
Exposes an uploadAndCertify helper that drives the three-step
presigned-URL upload flow, and documentTypes() to discover the available
document types and the fields each one expects.
Every other endpoint (list, get, certify, revoke, transfer) is exposed via
the public REST API at /public/* and fully documented in the
OpenAPI spec — call them
directly with fetch or generate a typed client from the spec.
Install
pnpm add @metrasign/sdkQuick start
import { MetrasignClient } from "@metrasign/sdk";
import fs from "node:fs";
const client = new MetrasignClient({
baseUrl: "https://api.metrasign.com/public",
apiKey: process.env.METRASIGN_API_KEY!,
});
const result = await client.uploadAndCertify({
file: new File([fs.readFileSync("invoice.pdf")], "invoice.pdf"),
organisationId: "org-uuid", // omit if your key is scoped to a single org
documentType: "0xabc…", // on-chain schema UID (see documentTypes())
title: "Invoice #1234",
// Doc-type field values — validated server-side against the type's
// field definitions. Unknown keys are rejected.
fieldValues: { invoiceNumber: "1234", amount: "10000" },
// Arbitrary extra pairs (optional, size-capped, not part of the
// certified shape).
metadata: { source: "erp-export" },
certify: true, // auto-cert in the verify worker
});
// Poll the upload attempt to track verification + (auto-)certification.
// `resolvedDocumentId` appears once the verify worker resolves the doc.
console.log(result.uploadAttemptId);The file's name and MIME type are taken from the File itself (with an
extension-based fallback for the type). When passing a Blob or raw
Uint8Array, set filename — the content type is then inferred from its
extension. Certification visibility defaults to "organization"; pass
visibility: "public" | "private" to override.
Discover document types
documentTypes() lists the types available to the organisation — its own
registered types plus the public catalogue — with the field definitions
needed to build a valid fieldValues bag:
const types = await client.documentTypes(); // { organisationId } optional
for (const t of types) {
console.log(t.schemaUid, t.name);
for (const f of [...t.fields, ...t.privateFields]) {
console.log(` ${f.key} (${f.type})${f.required ? " — required" : ""}`);
}
}Values for both public and private fields go in the one fieldValues
bag, always as strings (uint256 → "42", bool → "true"); the server
splits private fields out using the schema's markers. Private values are
stored off-chain and never returned by public document reads.
What it does under the hood
- POST
/public/documents/upload-attemptswith JSON metadata → server returns a presigned PUT URL - PUT the file bytes directly to that URL — the API server never sees the bytes
- POST
/public/documents/upload-attempts/{id}/complete→ server verifies the blob landed and enqueues the verify worker
When certify: true is set, the verify worker also auto-certifies the
resulting document on-chain using the wallet of the API key's creator —
no separate POST /:id/certify call.
Required scopes
| Use case | API key scopes |
| --- | --- |
| List document types | ["read"] |
| Upload only | ["read", "write"] |
| Upload + auto-cert | ["read", "write", "certify"] |
Errors
MetrasignError carries the HTTP status, the server's structured error
code, and the raw response body.
import { MetrasignError } from "@metrasign/sdk";
try {
await client.uploadAndCertify({ ... });
} catch (err) {
if (err instanceof MetrasignError) {
console.error(err.status, err.code, err.message);
}
throw err;
}Signer identity
certify: true certifications are signed on-chain by the wallet of the
user who created the API key. That address is recorded as the cert's
certifier. Treat your API key like that user's wallet — anyone
holding it can sign certifications as that user.
