SDK Reference
v1.0.0Client libraries for JavaScript and Python that wrap the DID.comms v1 REST API. All sovereign proxy rules are enforced — no DID exposure, no client-side keys, no metadata leakage.
Zero DID Exposure
DIDs never leave the proxy. API keys are the only external identifier.
Strip & Seal Always On
Metadata stripping is not toggleable. Every envelope is sealed by default.
No Client-Side Keys
Signing keys are generated and stored by Arcform. SDK never touches raw keys.
Installation
JavaScript / Node.js
npm install @didcomms/sdkbash
Python
pip install didcomms-sdkbash
Note: Until the npm/pip packages are published, download the SDK source files above and include them directly in your project.
Quick Setup
JavaScript
import { DIDComms } from "@didcomms/sdk";
const client = new DIDComms({
apiKey: "ak_your_api_key", // from /v1/did/activate
token: "your_session_token", // from login
baseUrl: "https://arcform-api.com",
});
// Activate → Send → Check Status
const identity = await client.activate({ label: "My App" });
const receipt = await client.send("ak_recipient", "Hello sovereign world");
const info = await client.status();javascriptPython
from didcomms import DIDComms
client = DIDComms(
api_key="ak_your_api_key",
token="your_session_token",
base_url="https://arcform-api.com",
)
# Activate → Send → Check Status
identity = client.activate(label="My App")
receipt = client.send("ak_recipient", "Hello sovereign world")
info = client.status()pythonAuthentication Model
The SDK uses a dual-layer auth model. Every request includes:
Authorization— Bearer token from your session (identifies the developer account)X-DID-API-Key— API key (identifies the sovereign identity performing the action)Both are set automatically by the SDK constructor. You never need to manage headers manually.
Methods
client.activate(options?)Create a new sovereign identity and API key. Returns a DID, fingerprint, and API key scoped to the free tier.
Parameters
labelstring— Optional friendly label for the identityReturns
{ did, fingerprint, api_key_id, plan, usage, metadata_policy, status }Example
const identity = await client.activate({ label: "Production Key" });
console.log(identity.api_key_id); // "ak_b1df21..."
console.log(identity.did); // "did:comms:ff7e..."
console.log(identity.metadata_policy); // "strip_and_seal"javascriptclient.send(to, message)Send a sealed envelope to another DID.comms identity. The message is encrypted (X25519-XSalsa20-Poly1305), metadata is stripped and sealed, and the envelope is routed through mediator hops. Raw DIDs are rejected — use API keys only.
Parameters
tostring— Recipient API key (ak_...) — raw DIDs rejectedmessagestring— Message content to encrypt and sendReturns
{ envelope_id, envelope_hash, sender, recipient, encryption, routing, metadata_policy, metrics }Example
const receipt = await client.send("ak_recipient_key", "Hello sovereign world");
console.log(receipt.envelope_id);
console.log(receipt.encryption.status); // "sealed"
console.log(receipt.routing.hops); // 2
console.log(receipt.metadata_policy); // "stripped_and_sealed"javascriptclient.status()Get the current identity's status, usage counters, plan tier, and registered webhook count.
Returns
{ did, fingerprint, api_key_id, label, status, plan, usage, webhooks, metadata_policy }Example
const info = await client.status(); console.log(info.usage.messages_remaining); // 947 console.log(info.usage.utilisation_pct); // 5 console.log(info.plan); // "builder"javascript
client.verify(envelopeHash)Verify the delivery status, sender identity, routing integrity, and bubble lifecycle of an envelope. Returns a proof-of-transit object with integrity flags, identity verdict, and signer set resolution. Zero content exposure.
Parameters
envelopeHashstring— The envelope hash to verifyReturns
{ status, envelope_hash, verified_at, proof_checksum, audit_spine, identity, bubble_state, integrity }Example
const proof = await client.verify("aa4a2d3dadd8ba65");
console.log(proof.status); // "verified"
console.log(proof.identity.identity_verdict); // "ok"
console.log(proof.identity.key_status_at_send); // "active"
console.log(proof.integrity.proof_checksum_valid); // true
console.log(proof.bubble_state.signal_type); // "message"javascriptclient.verifyBatch(envelopeHashes)Batch-verify multiple envelopes in a single request. Processes in parallel chunks for industrial throughput. Returns individual proofs and an aggregated summary. Maximum 50 hashes per batch.
Parameters
envelopeHashesstring[]— Array of envelope hashes (max 50)Returns
{ mode, results: Proof[], summary: { total, verified, partial, degraded, orphaned, unverified } }Example
const batch = await client.verifyBatch([ "aa4a2d3dadd8ba65", "b48f21c316cb75f6" ]); console.log(batch.summary.verified); // 2 console.log(batch.summary.degraded); // 0 batch.results.forEach(p => console.log(p.status));javascript
client.webhooks.register(url, events?)Register a webhook endpoint. Sealed envelope deliveries will be pushed to your URL with an HMAC signature in the X-DIDComms-Signature header.
Parameters
urlstring— Your HTTPS endpoint URLeventsstring[]— Event types (default: ['envelope.received'])Returns
{ success, webhook_id, url, events, secret, status }Example
const wh = await client.webhooks.register("https://myapp.com/hooks/didcomms");
// Save the secret for signature verification
console.log(wh.secret); // "whsec_c904ab..."
console.log(wh.status); // "active"javascriptclient.webhooks.list()List all registered webhooks for the current identity, including failure counts and last trigger timestamps.
Returns
{ api_key_id, webhooks: [{ id, url, events, status, failure_count, last_triggered_at }] }Example
const { webhooks } = await client.webhooks.list();
webhooks.forEach(wh => console.log(wh.url, wh.status));javascriptclient.webhooks.delete(webhookId)Delete a registered webhook endpoint by ID.
Parameters
webhookIdstring— The webhook record ID to deleteReturns
{ success: true, message }Example
await client.webhooks.delete("6a3d7ccaaf66...");javascriptWebhooks.verifySignature(payload, signature, secret)Static method. Verify an incoming webhook's HMAC-SHA256 signature to confirm it was sent by DID.comms. Use this in your webhook handler before processing the payload.
Parameters
payloadstring— Raw request body stringsignaturestring— Value of the X-DIDComms-Signature headersecretstring— Your webhook secret (whsec_...)Returns
Promise<boolean>Example
import { Webhooks } from "@didcomms/sdk";
const isValid = await Webhooks.verifySignature(
rawBody,
req.headers["x-didcomms-signature"],
process.env.DIDCOMMS_WEBHOOK_SECRET
);
if (!isValid) return res.status(401).json({ error: "Invalid signature" });javascriptError Handling
try {
const receipt = await client.send("ak_recipient", "Hello");
} catch (err) {
if (err instanceof DIDCommsError) {
console.error(err.code); // "MONTHLY_LIMIT_EXCEEDED"
console.error(err.status); // 429
console.error(err.message); // "Monthly message limit exceeded."
}
}javascriptError Codes
MISSING_CONFIGapiKey or token not provided to constructorMISSING_SENDERNo X-DID-API-Key header or api_key_id in bodyMISSING_RECIPIENTNo recipient specified in send()MISSING_PAYLOADNo message content in send()KEY_NOT_FOUNDAPI key does not existKEY_INACTIVEAPI key is revoked or deactivatedRAW_DID_REJECTEDRaw DIDs passed as recipient — use API keysMONTHLY_LIMIT_EXCEEDEDPlan message quota exhaustedWebhook Verification
Every webhook delivery includes an X-DIDComms-Signature header. Verify it with the static Webhooks.verifySignature() method before processing.
// Express.js webhook handler
app.post("/hooks/didcomms", async (req, res) => {
const { Webhooks } = require("@didcomms/sdk");
const isValid = await Webhooks.verifySignature(
JSON.stringify(req.body),
req.headers["x-didcomms-signature"],
process.env.DIDCOMMS_WEBHOOK_SECRET
);
if (!isValid) return res.status(401).json({ error: "Bad signature" });
// Process the sealed envelope event
const { event, envelope_id, sender } = req.body;
console.log("Received:", event, "from:", sender);
res.status(200).json({ received: true });
});javascript