# SDK

## Installation

```bash
npm install @toani/vault-sdk
```

**System requirements**: Node.js >= 22.0.0

## Initialization

```typescript
import { toaniVaultSDK } from '@toani/vault-sdk';

// Basic initialization
const sdk = new toaniVaultSDK({
  baseUrl: 'https://vault.toani.ai',
  token: 'v4.local.your-api-token',
});

// Factory method (equivalent)
const sdk = toaniVaultSDK.create(
  'https://vault.toani.ai',
  'v4.local.your-api-token'
);
```

**Configuration parameters:**

| Parameter            | Type      | Default  | Description                                                        |
| -------------------- | --------- | -------- | ------------------------------------------------------------------ |
| `baseUrl`            | `string`  | Required | toani Vault server address                                         |
| `token`              | `string`  | Required | PASETO v4 API Token                                                |
| `timeout`            | `number`  | `30000`  | Request timeout (milliseconds)                                     |
| `maxRetries`         | `number`  | `3`      | Auto-retry count on failure                                        |
| `autoRefreshToken`   | `boolean` | `true`   | Auto-remind when token expires                                     |
| `tokenRefreshBuffer` | `number`  | `300000` | Milliseconds before expiry to trigger reminder (default 5 minutes) |

## Credential Management

### Create Credential

```typescript
import { toaniVaultSDK, CredentialType } from '@toani/vault-sdk';

// Username / Password
const cred = await sdk.credentials.createUsernamePassword(
  'schwab',            // Service ID
  'user@example.com',  // Username
  'my-password'        // Password
);

// API Key
const cred = await sdk.credentials.createApiKey(
  'stripe',
  'sk_live_...',
  'whsec_...'  // Secret, optional
);

// OAuth Refresh Token
const cred = await sdk.credentials.createOAuthRefresh('google', '1//0d...');

// Generic method (supports all credential types)
const cred = await sdk.credentials.create({
  serviceId: 'mydb',
  credentialType: CredentialType.DatabaseConnection,
  plaintextData: {
    host: 'db.example.com',
    port: 5432,
    database: 'production',
    username: 'dbuser',
    password: 'dbpass',
  },
  expiresAt: Math.floor(Date.now() / 1000) + 86400 * 30, // Expires in 30 days
});

// zkMe Credential (W3C Verifiable Credential — zkKYC shown as example)
// The same pattern applies to zkPoAI, AMLMe, zkKYA, and other zkMe credential types
const zkCred = await sdk.credentials.create({
  serviceId: 'zkme',
  credentialType: CredentialType.ZkmeCredential,
  plaintextData: {
    credential_json: {
      '@context': ['https://www.w3.org/2018/credentials/v1'],
      type: ['VerifiableCredential', 'ZkMeCredential'], // exact type set by zkMe at issuance
      issuer: 'did:zkme:issuer_xxx',
      issuanceDate: '2026-03-01T00:00:00Z',
      credentialSubject: {
        id: 'did:zkme:user_yyy',
        kycStatus: 'approved',
      },
      proof: {
        type: 'Ed25519Signature2020',
        created: '2026-03-01T00:00:00Z',
        proofPurpose: 'assertionMethod',
        proofValue: 'z58D...',
      },
    },
    did: 'did:zkme:user_yyy',
    zk_proof: 'base64_encoded_zkp...',
    credential_type: 'zkKYC', // optional: e.g. 'zkPoAI', 'AMLMe', 'zkKYA'
  },
});

console.log('Credential ID:', cred.credentialId);
```

### Query Credential

```typescript
// List all credentials (metadata only, no plaintext)
const { credentials, total } = await sdk.credentials.list();

// Filter by Service ID
const { credentials } = await sdk.credentials.list({ serviceId: 'schwab' });

// Filter by credential type
const { credentials } = await sdk.credentials.list({
  credentialType: CredentialType.ApiKey,
});

// Get single credential
const cred = await sdk.credentials.get('018f1b4e-...');
```

### Decrypt Credential

Decryption runs inside TEE and requires Token to have `credential:decrypt` Scope; operation is recorded in audit log.

```typescript
const decrypted = await sdk.credentials.decrypt(
  '018f1b4e-7e9e-7f3a-8b5c-2d4e6f8a0b2c',
  'User initiated bank statement query'  // Reason (audit log, required)
);

console.log('Username:', decrypted.plaintextData.username);
console.log('Password:', decrypted.plaintextData.password);
```

> **Note**: Do not persist plaintext in `plaintextData`; remove from memory promptly after use.

### Delete Credential

```typescript
const result = await sdk.credentials.delete('018f1b4e-...');
if (result.deleted) {
  console.log('Credential deleted');
}
```

## Token State Management

```typescript
// Local check (no network request)
if (!sdk.token.isValid()) {
  console.log('Token expired, please regenerate');
}

if (sdk.token.isExpiringSoon()) {
  console.log(`Expiring soon, remaining: ${sdk.token.getRemainingTimeFormatted()}`);
}

// Permission check
if (sdk.token.hasScope('credential:decrypt')) {
  // Can execute decryption
}

// Check for any one Scope
if (sdk.token.hasAnyScope(['credential:read', 'admin'])) {
  // Can list credentials
}

// Check for multiple Scopes simultaneously
if (sdk.token.hasAllScopes(['credential:write', 'audit:read'])) {
  // Can write credentials and view audit
}

// Verify with server (check if revoked)
const isValid = await sdk.token.verify();

// Revoke Token
await sdk.token.revoke();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.toani.ai/toani-vault/getting-started/sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
