Creating Mandates
This guide covers patterns for creating mandates, including multi-action scopes, constraints, approval workflows, and template-based creation.
Prerequisites
- A Mandaitor tenant account with an API key
- The
@mandaitor/sdkpackage installed - Familiarity with Core Concepts
Basic Mandate Creation
import { MandaitorClient } from "@mandaitor/sdk";
const client = new MandaitorClient({
apiKey: process.env.MANDAITOR_API_KEY!,
tenantId: "tnt_your_tenant_id",
});
const mandate = await client.createMandate({
principal: {
type: "NATURAL_PERSON",
subject_id: "user:project-manager@example.com",
},
delegate: {
type: "AGENT",
subject_id: "monco:agent:validation-v3",
},
scope: {
actions: ["construction.validation.approve"],
resources: ["monco:project:proj_12345/zone:A/*"],
effect: "ALLOW",
},
constraints: {},
});
console.log(mandate.mandate_id); // "mdt_01HXYZ..."
console.log(mandate.status); // "ACTIVE"
Multi-Action Scopes
A single mandate can authorize multiple actions across multiple resources. This reduces the number of mandates needed for complex workflows:
const mandate = await client.createMandate({
principal: {
type: "NATURAL_PERSON",
subject_id: "user:project-manager@example.com",
},
delegate: {
type: "AGENT",
subject_id: "monco:agent:validation-v3",
},
scope: {
actions: [
"construction.validation.approve",
"construction.validation.flag",
"construction.validation.reject",
"construction.validation.request_recheck",
],
resources: ["monco:project:proj_12345/zone:A/*", "monco:project:proj_12345/zone:B/*"],
effect: "ALLOW",
},
constraints: {
time: { expires_at: "2026-12-31T23:59:59Z" },
},
});
Using Mandate Templates
Mandate templates from industry taxonomies provide pre-configured delegation blueprints. Reference templates by the taxonomy ID when creating mandates:
const mandate = await client.createMandate({
principal: {
type: "LEGAL_ENTITY",
subject_id: "org:acme-construction",
},
delegate: {
type: "AGENT",
subject_id: "monco:agent:cost-mgmt-v2",
},
scope: {
// Actions from the construction.cost-management template
actions: ["construction.cost.approve_invoice", "construction.cost.flag_deviation"],
resources: ["monco:project:proj_ABC/*"],
effect: "ALLOW",
},
constraints: {
time: { expires_at: "2027-06-30T23:59:59Z" },
require_mfa: true,
},
taxonomy_version: "construction@1.0.0",
});
Approval Workflow
For high-risk delegations, mandates can require explicit approval before activation. Set require_approval: true to create the mandate in PENDING_APPROVAL state:
const mandate = await client.createMandate({
principal: {
type: "NATURAL_PERSON",
subject_id: "user:engineer@example.com",
},
delegate: {
type: "AGENT",
subject_id: "agent:procurement-bot",
},
scope: {
actions: ["construction.procurement.create_order"],
resources: ["monco:project:proj_789/*"],
effect: "ALLOW",
},
constraints: {},
require_approval: true,
});
console.log(mandate.status); // "PENDING_APPROVAL"
Approving or Rejecting
A manager or admin can then approve or reject the mandate:
// Approve — transitions to ACTIVE
await client.approveMandate("mdt_01HXYZ...", "Approved by project lead");
// Or reject — transitions to REVOKED
await client.rejectMandate("mdt_01HXYZ...", "Scope too broad for this delegate");
Verification requests against a pending mandate return DENY with reason code APPROVAL_REQUIRED, including the mandate ID so the caller knows approval is needed.
Security Considerations
require_approvalshould be enforced for CRITICAL risk-level actions- Approval events are recorded in the immutable audit log
- The
MANDATE_APPROVEDandMANDATE_REJECTEDevent types track the approval decision and approver identity
Mandate Lifecycle
After creation, mandates can be managed through their lifecycle:
// Suspend — temporarily disable without revoking
await client.suspendMandate("mdt_01HXYZ...", "Quarterly review");
// Reactivate — re-enable a suspended mandate
await client.reactivateMandate("mdt_01HXYZ...");
// Revoke — permanently disable
await client.revokeMandate("mdt_01HXYZ...", "Contract terminated");
State Transitions
approve()
┌─────────────┐────────────▸┌──────────┐ ┌───────────┐
│ PENDING_ │ │ ACTIVE │◂───▸│ SUSPENDED │
│ APPROVAL │ └────┬─────┘ └─────┬─────┘
└──────┬──────┘ │ │
│ reject() ▾ ▾
▾ ┌─────────┐ ┌─────────┐
┌─────────┐ │ REVOKED │ │ REVOKED │
│ REVOKED │ └─────────┘ └─────────┘
│(rejected)│
└─────────┘ ┌─────────┐
│ EXPIRED │ (automatic, time-based)
└─────────┘
Audit Events
Every mandate operation emits an immutable audit event:
const events = await client.getMandateEvents("mdt_01HXYZ...", { limit: 10 });
for (const event of events.items) {
console.log(event.event_type, event.timestamp, event.actor);
}
// MANDATE_CREATED 2026-03-15T10:00:00Z { type: "NATURAL_PERSON", ... }
// MANDATE_APPROVED 2026-03-15T10:05:00Z { type: "NATURAL_PERSON", ... }
// VERIFICATION_ALLOWED 2026-03-15T11:30:00Z { type: "SERVICE", ... }