Skip to content

SDK Reference

Terminal window
npm install @humanauth/sdk

@humanauth/harp is no longer needed. Protocol types and crypto primitives are included in the SDK.

The primary class for sending requests to humans and receiving responses.

import { HumanAuthClient } from "@humanauth/sdk";
const client = HumanAuthClient.fromPairing(pairing);

Creates a client from a saved Pairing. The client handles encryption, relay communication, signature verification, and polling.

Request binary approval. Blocks by default until the human responds or TTL expires.

const result = await client.authorize({
action: "deploy_production",
description: "Deploy API v2.1.0 to production",
severity: "high",
parameters: { service: "api", version: "2.1.0" },
reasoning: "New features ready, all tests passing",
ttl: 300,
});
if (result.decision === "approved") {
await deploy();
} else {
console.log(`Denied: ${result.reason}`);
}

AuthorizeOptions:

FieldTypeRequiredDefaultDescription
actionstringYesAction identifier
descriptionstringYesHuman-readable description
severitySeverityNo”medium”low, medium, high, critical
assuranceAssuranceNo”biometric”tap, biometric, elevated
parametersRecord<string, unknown>NoAction parameters for context
reasoningstringNoWhy the agent wants this
contextRecord<string, unknown>NoCross-protocol references
ttlnumberNo300Timeout in seconds (max 86400)
blockingbooleanNotrueIf false, returns request_id immediately
callbackUrlstringNoWebhook URL for non-blocking
callbackSecretstringNoHMAC secret for webhook

AuthorizeResult:

interface AuthorizeResult {
decision: "approved" | "denied";
reason?: string;
}

Request structured data input. Blocks by default.

const result = await client.collect({
action: "deployment_config",
description: "Please configure the deployment",
schema: {
fields: [
{
name: "target",
type: "select",
label: "Deploy Target",
required: true,
options: [
{ value: "staging", label: "Staging" },
{ value: "production", label: "Production" },
],
},
{
name: "notify_team",
type: "checkbox",
label: "Notify team on Slack",
default: true,
},
],
},
severity: "medium",
ttl: 600,
});
console.log(result.form_data);
// { target: "staging", notify_team: true }

CollectOptions:

FieldTypeRequiredDefaultDescription
actionstringYesAction identifier
descriptionstringYesWhat data you need and why
schemaCollectSchemaYesForm definition (max 20 fields)
severitySeverityNo”medium”How sensitive is this data
assuranceAssuranceNo”biometric”Authentication level
parametersRecord<string, unknown>NoAdditional context
reasoningstringNoWhy you need this data
contextRecord<string, unknown>NoCross-protocol references
ttlnumberNo600Timeout in seconds
blockingbooleanNotrueIf false, returns request_id immediately
callbackUrlstringNoWebhook URL
callbackSecretstringNoHMAC secret

CollectResult:

interface CollectResult {
form_data: Record<string, unknown>;
reason?: string;
}

CollectSchema:

interface CollectSchema {
fields: CollectField[]; // max 20 fields
submitLabel?: string; // custom submit button text
}
interface CollectField {
name: string;
type: "select" | "multiselect" | "checkbox" | "number" | "datetime";
label: string;
description?: string;
required?: boolean;
default?: unknown;
options?: { value: string; label: string }[]; // for select/multiselect
min?: number; // for number
max?: number; // for number
step?: number; // for number
minDate?: string; // for datetime (ISO 8601)
maxDate?: string; // for datetime (ISO 8601)
}

Send a notification. Always fire-and-forget — returns after relay acknowledges receipt.

await client.inform({
action: "deploy_complete",
description: "Deployment to staging completed successfully",
severity: "low",
category: "result",
});

InformOptions:

FieldTypeRequiredDefaultDescription
actionstringYesAction name or context
descriptionstringYesNotification message
severitySeverityNo”low”Urgency level
categorystringNo”general”escalation, result, status, error, general
parametersRecord<string, unknown>NoAdditional context
reasoningstringNoWhy you’re sending this
callbackUrlstringNoWebhook fires on “viewed” state
callbackSecretstringNoHMAC secret

Returns Promise<void>.

Cancel a pending request.

await client.cancel("req_abc123");

Only works when the request is in pending state. Throws if already delivered/decided.

Check the current status of a request.

const status = await client.status("req_abc123");
console.log(status);
// { request_id: "req_abc123", status: "viewed", created_at: 1712345678, delivered_at: 1712345680, viewed_at: 1712345690 }

RequestStatus:

interface RequestStatus {
request_id: string;
status: "pending" | "delivered" | "viewed" | "decided" | "expired" | "cancelled";
created_at: number;
delivered_at?: number;
viewed_at?: number;
decided_at?: number;
}
interface Pairing {
pair_id: string;
platform_id: string;
platform_name: string;
device_id: string;
shared_secret: Uint8Array;
encryption_key: Uint8Array;
platform_auth_key: Uint8Array;
app_auth_key: Uint8Array;
signing_pub: Uint8Array;
relay_url: string;
paired_at: string;
}
type Severity = "low" | "medium" | "high" | "critical";
type Assurance = "tap" | "biometric" | "elevated";
import { loadPairing } from "@humanauth/sdk";
const pairing = await loadPairing("pair_abc123");
import { listPairings } from "@humanauth/sdk";
const pairings = await listPairings();
import { encrypt } from "@humanauth/sdk";
const { nonce, ciphertext } = encrypt(encryptionKey, plaintextBytes);
import { decrypt } from "@humanauth/sdk";
const plaintext = decrypt(encryptionKey, nonce, ciphertext);
import { deriveSharedSecret } from "@humanauth/sdk";
const sharedSecret = deriveSharedSecret(myPrivateKey, theirPublicKey);
import { deriveKeys } from "@humanauth/sdk";
const { encryption_key, platform_auth_key, app_auth_key } = deriveKeys(sharedSecret);
VariableDefaultDescription
HARP_PAIRINGS_DIR~/.harp/pairingsDirectory for saved pairing files
HARP_AUDIT_DIR~/.harp/auditDirectory for audit log files