npm package: @mandaitor/sdk
Description: Mandaitor Delegation Mandate Registry — TypeScript SDK
Author: Mandaitor
Latest version: 3.0.0

# @mandaitor/sdk

TypeScript SDK for the Mandaitor Delegation Mandate Registry API.

---

## Installation

```bash
npm install @mandaitor/sdk
# or
pnpm add @mandaitor/sdk
```

## Quick Start

```typescript
import { MandaitorClient } from "@mandaitor/sdk";

const client = new MandaitorClient({
  apiKey: "mk_live_...",
  tenantId: "tnt_acme_prod",
});

// Create a mandate
const mandate = await client.createMandate({
  principal: { id: "user-123", type: "NATURAL_PERSON" },
  delegate: { id: "agent-456", type: "AGENT" },
  scope: {
    actions: ["construction.validation.approve"],
    resources: ["project:proj-1/zone:EG/installation:stk_01"],
    effect: "ALLOW",
  },
  constraints: {
    validFrom: new Date().toISOString(),
    validUntil: new Date(Date.now() + 86400000).toISOString(),
  },
});

// Verify a delegation claim
const result = await client.verify({
  delegate_subject_id: "agent-456",
  action: "construction.validation.approve",
  resource: "project:proj-1/zone:EG/installation:stk_01",
});

console.log(result.decision); // "ALLOW" or "DENY"
```

## API Reference

### `MandaitorClient`

| Method                                 | Description                                 |
| -------------------------------------- | ------------------------------------------- |
| `createMandate(request)`               | Create a new delegation mandate             |
| `getMandate(mandateId)`                | Retrieve a mandate by ID                    |
| `listMandates(params?)`                | List mandates with optional pagination      |
| `revokeMandate(mandateId, reason?)`    | Permanently revoke a mandate                |
| `suspendMandate(mandateId, reason?)`   | Temporarily suspend a mandate               |
| `reactivateMandate(mandateId)`         | Reactivate a suspended mandate              |
| `verify(request)`                      | Verify a delegation claim                   |
| `verifyWithPoM(request, options)`      | Verify with Proof-of-Mandate VC             |
| `getMandateEvents(mandateId, params?)` | Get audit events for a specific mandate     |
| `getAuditEvents(mandateId, options?)`  | _(deprecated)_ Alias for `getMandateEvents` |
| `listEvents(params?)`                  | Query all events for the tenant             |
| `getEvent(eventId, mandateId)`         | Get a specific event by ID                  |

### Configuration

```typescript
interface MandaitorClientConfig {
  apiKey: string; // API key issued during tenant onboarding
  tenantId: string; // Tenant identifier, e.g. "tnt_acme_prod"
  baseUrl?: string; // API base URL (defaults to production)
  timeout?: number; // Request timeout in ms (default: 5000)
  retries?: number; // Number of retries for 5xx/429 errors (default: 2)
}
```

### Error Handling

The SDK provides typed error classes for all API error scenarios:

| Error Class                | HTTP Status | Description                                                |
| -------------------------- | ----------- | ---------------------------------------------------------- |
| `MandaitorAuthError`       | 401         | Invalid or missing API key                                 |
| `MandaitorForbiddenError`  | 403         | Insufficient permissions                                   |
| `MandaitorNotFoundError`   | 404         | Resource not found                                         |
| `MandaitorConflictError`   | 409         | State conflict (e.g., revoking an already revoked mandate) |
| `MandaitorRateLimitError`  | 429         | Rate limit exceeded                                        |
| `MandaitorValidationError` | 400         | Invalid request payload                                    |
| `MandaitorTimeoutError`    | -           | Request timed out                                          |

## Development

```bash
# Build
pnpm build

# Run unit tests
pnpm test:unit

# Run integration tests (requires testing stage credentials)
pnpm test:integration
```