Documentation
JavaScript SDK
The SDK is published as @behalfid/sdk and uses fetch, so it works in Node 18+ without extra dependencies.
Install
npm install @behalfid/sdk
Initialize
import { BehalfID } from "@behalfid/sdk";
const behalf = new BehalfID({
apiKey: process.env.BEHALFID_API_KEY!,
baseUrl: "https://behalfid.vercel.app"
});Add a connected agent
const agent = await behalf.createAgent({
name: "Ollie",
agentType: "connected",
provider: "ollie",
externalAgentLabel: "Jasper's Ollie assistant",
description: "Personal assistant used for planning"
});Create a permission with structured scopes
await behalf.createPermission({
agentId,
action: "access_data",
resource: "gmail.com",
allowedActions: ["read labels", "summarize messages", "provide pricing metrics"],
blockedActions: ["send email", "delete messages", "schedule events", "make purchases"],
requiresApproval: true,
template: "access_data"
});Agent descriptions are informational. Permissions are the source of truth. Use allowedActions and blockedActions to make the permission explicit so external agents can read them from the passport page.
Fail-closed enforcement
Use enforceAction to gate every external action. On denial, this throws — the agent never reaches the code that would have executed the action. This is fail closed: on denial, the safe default is to stop.
async function enforceAction(input) {
const result = await behalf.verify({ agentId, ...input });
if (!result.allowed) {
throw new Error(`Action blocked by BehalfID: ${result.reason}`);
}
return result;
}
// Allowed — proceeds.
await enforceAction({ action: "browse_web", vendor: "web" });
// Denied — throws. The next line never runs.
await enforceAction({ action: "purchase", vendor: "coachella.com", amount: 742 });
console.log("Booking ticket..."); // ← never reachedVerify an action
const result = await behalf.verify({
agentId,
action: "access_data",
vendor: "gmail.com",
metadata: {
scope: "read labels"
}
});In the current API, vendor can represent the resource or service being accessed. Pass amount only for transaction-like actions. Pass metadata.scope to hint which allowed action is being requested.
Logs and key rotation
const logs = await behalf.getLogs(agentId); const rotated = await behalf.rotateKey(agentId);
Webhook signature helper
import { verifyWebhookSignature } from "@behalfid/sdk";
const valid = await verifyWebhookSignature({
secret: process.env.BEHALFID_WEBHOOK_SECRET!,
payload: rawBody,
timestamp: req.headers["behalfid-timestamp"],
signature: req.headers["behalfid-signature"]
});