humanos 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +310 -114
- package/dist/index.d.mts +3319 -1514
- package/dist/index.d.ts +3319 -1514
- package/dist/index.js +1621 -499
- package/dist/index.mjs +1578 -478
- package/generated/.openapi-generator/FILES +59 -33
- package/generated/api/actions-api.ts +273 -0
- package/generated/api/activity-api.ts +225 -0
- package/generated/api/{resource-api.ts → approval-api.ts} +65 -61
- package/generated/api/credentials-api.ts +365 -25
- package/generated/api/didapi.ts +138 -0
- package/generated/api/requests-api.ts +124 -134
- package/generated/api/user-api.ts +45 -36
- package/generated/api/webhooks-api.ts +84 -56
- package/generated/api.ts +5 -1
- package/generated/models/action-dto.ts +36 -0
- package/generated/models/action-entity.ts +57 -0
- package/generated/models/action-list-entity.ts +39 -0
- package/generated/models/action-query.ts +48 -0
- package/generated/models/action-ref-dto.ts +36 -0
- package/generated/models/action-version-detail-entity.ts +72 -0
- package/generated/models/action-version-list-entity.ts +39 -0
- package/generated/models/action-version-summary-entity.ts +48 -0
- package/generated/models/activities-entity.ts +39 -0
- package/generated/models/activity-entity.ts +90 -0
- package/generated/models/activity-query.ts +96 -0
- package/generated/models/consent.ts +36 -0
- package/generated/models/constraints-dto.ts +36 -0
- package/generated/models/{agent-detail-entity.ts → contact-entity.ts} +8 -8
- package/generated/models/create-presentation-dto.ts +30 -0
- package/generated/models/create-presentation400-response.ts +42 -0
- package/generated/models/create-presentation403-response.ts +42 -0
- package/generated/models/create-presentation404-response.ts +42 -0
- package/generated/models/create-subject-dto.ts +8 -2
- package/generated/models/create-subject-entity.ts +3 -3
- package/generated/models/{cancel-request404-response.ts → create400-response.ts} +5 -5
- package/generated/models/credential-dto-data-inner.ts +26 -0
- package/generated/models/credential-dto.ts +52 -6
- package/generated/models/credential-entity.ts +33 -7
- package/generated/models/{credential-subject.ts → credential-event-decision.ts} +13 -11
- package/generated/models/credential-event-user.ts +1 -1
- package/generated/models/credential-event.ts +15 -19
- package/generated/models/credential-placement-dto.ts +85 -0
- package/generated/models/credential-status.ts +5 -3
- package/generated/models/credentials-detail404-response.ts +42 -0
- package/generated/models/credentials-evidence404-response.ts +42 -0
- package/generated/models/credentials-issue-vp400-response.ts +42 -0
- package/generated/models/credentials-issue-vp403-response.ts +42 -0
- package/generated/models/credentials-issue-vp404-response.ts +42 -0
- package/generated/models/credentials-revoke400-response.ts +42 -0
- package/generated/models/credentials-revoke409-response.ts +42 -0
- package/generated/models/did-document-entity.ts +63 -0
- package/generated/models/evidence.ts +44 -0
- package/generated/models/generate-credential-entity.ts +2 -2
- package/generated/models/generate-request-dto.ts +18 -15
- package/generated/models/generate-request-entity.ts +6 -6
- package/generated/models/generate-subject-entity.ts +3 -3
- package/generated/models/get-evidence404-response.ts +42 -0
- package/generated/models/group-entity.ts +3 -3
- package/generated/models/groups-entity.ts +1 -1
- package/generated/models/identity-dto.ts +26 -26
- package/generated/models/identity-event-decision.ts +13 -1
- package/generated/models/identity-event-user.ts +42 -0
- package/generated/models/identity-event.ts +14 -18
- package/generated/models/{identity-event-identity.ts → identity-payload.ts} +12 -12
- package/generated/models/index.ts +55 -32
- package/generated/models/{action-type.ts → json-value.ts} +6 -12
- package/generated/models/{mandate-data-dto-value.ts → organization-data-entity.ts} +9 -3
- package/generated/models/{issuer-detail-entity.ts → otp-error.ts} +8 -8
- package/generated/models/otp-failed-event-otp.ts +3 -3
- package/generated/models/otp-failed-event.ts +11 -15
- package/generated/models/{subject.ts → partial-subject-entity.ts} +9 -9
- package/generated/models/presentation-receipt-entity.ts +42 -0
- package/generated/models/presentation-response-entity.ts +39 -0
- package/generated/models/receipt-entity.ts +36 -0
- package/generated/models/request-credential-entity.ts +72 -0
- package/generated/models/request-detail-entity.ts +26 -20
- package/generated/models/request-detail-subject-entity.ts +87 -0
- package/generated/models/request-entity.ts +14 -8
- package/generated/models/request-query.ts +3 -21
- package/generated/models/request-subject-entity.ts +21 -6
- package/generated/models/requests-create400-response.ts +42 -0
- package/generated/models/requests-detail404-response.ts +42 -0
- package/generated/models/requests-entity.ts +1 -1
- package/generated/models/requests-resend-otp403-response.ts +42 -0
- package/generated/models/resend-otp403-response.ts +42 -0
- package/generated/models/resource-entity.ts +11 -3
- package/generated/models/{group-resource-entity.ts → resource-minimal-entity.ts} +13 -11
- package/generated/models/resource-query.ts +3 -1
- package/generated/models/resources-entity.ts +1 -1
- package/generated/models/revoke-credential-dto.ts +30 -0
- package/generated/models/revoke-credential-entity.ts +63 -0
- package/generated/models/revoke-credential400-response.ts +42 -0
- package/generated/models/revoke-credential409-response.ts +42 -0
- package/generated/models/revoke-receipt-entity.ts +42 -0
- package/generated/models/schema-entity.ts +57 -0
- package/generated/models/schema-list-entity.ts +39 -0
- package/generated/models/schema-query.ts +48 -0
- package/generated/models/schema-response-entity.ts +45 -0
- package/generated/models/schema-version-detail-entity.ts +72 -0
- package/generated/models/schema-version-list-entity.ts +39 -0
- package/generated/models/schema-version-response-entity.ts +54 -0
- package/generated/models/schema-version-summary-entity.ts +48 -0
- package/generated/models/subject-contact-entity.ts +7 -7
- package/generated/models/subject-issuer-entity.ts +69 -0
- package/generated/models/subject-query.ts +4 -4
- package/generated/models/test-event.ts +11 -15
- package/generated/models/user-create400-response.ts +42 -0
- package/generated/models/user-detail400-response.ts +42 -0
- package/generated/models/user-detail404-response.ts +42 -0
- package/generated/models/verification-method-entity.ts +48 -0
- package/generated/models/verify-allow-response-entity.ts +61 -0
- package/generated/models/verify-deny-response-entity.ts +79 -0
- package/generated/models/verify-evaluation-entity.ts +51 -0
- package/generated/models/verify-presentation-dto.ts +36 -0
- package/generated/models/verify-receipt-entity.ts +42 -0
- package/generated/models/w3-cverifiable-credential-credential-subject-mandate-action.ts +44 -0
- package/generated/models/w3-cverifiable-credential-credential-subject-mandate-constraint-constraint-schema.ts +44 -0
- package/generated/models/w3-cverifiable-credential-credential-subject-mandate-constraint.ts +41 -0
- package/generated/models/w3-cverifiable-credential-credential-subject-mandate-context.ts +32 -0
- package/generated/models/{mandate-data-type.ts → w3-cverifiable-credential-credential-subject-mandate-grantor.ts} +3 -16
- package/generated/models/w3-cverifiable-credential-credential-subject-mandate.ts +65 -0
- package/generated/models/w3-cverifiable-credential-credential-subject.ts +41 -0
- package/generated/models/w3-cverifiable-credential-evidences-inner.ts +42 -0
- package/generated/models/w3-cverifiable-credential-proofs-inner.ts +62 -0
- package/generated/models/w3-cverifiable-credential-valid-from.ts +24 -0
- package/generated/models/w3-cverifiable-credential-valid-until.ts +24 -0
- package/generated/models/w3-cverifiable-credential.ts +24 -25
- package/generated/models/webhook-call-event.ts +6 -12
- package/package.json +1 -1
- package/generated/models/credential-full-entity.ts +0 -82
- package/generated/models/get-credential-entity.ts +0 -48
- package/generated/models/identity-field-placement.ts +0 -73
- package/generated/models/identity-field-type.ts +0 -38
- package/generated/models/mandate-data-dto-type.ts +0 -73
- package/generated/models/mandate-data-dto.ts +0 -71
- package/generated/models/signature-placement-item-dto.ts +0 -72
- package/generated/models/signature-placement.ts +0 -56
- package/generated/models/subject-entity.ts +0 -48
- package/generated/models/w3-cproof.ts +0 -82
package/README.md
CHANGED
|
@@ -1,45 +1,73 @@
|
|
|
1
1
|
# Humanos SDK for TypeScript/JavaScript
|
|
2
2
|
|
|
3
|
-
Official TypeScript/JavaScript SDK for the [Humanos](https://humanos.id) API.
|
|
3
|
+
Official TypeScript/JavaScript SDK for the [Humanos](https://humanos.id) API. Auto-signs every request, verifies and decrypts webhooks, and ships full type definitions.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/humanos)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Concepts
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
- **Webhook Verification** - Verify signatures and decrypt encrypted payloads
|
|
12
|
-
- **TypeScript Support** - Full type definitions included
|
|
13
|
-
- **Simple API** - Clean interface for all Humanos endpoints
|
|
10
|
+
Humanos gives your agent a cryptographic permission slip — issued by the user, scoped to a specific action, and verified at runtime.
|
|
14
11
|
|
|
15
|
-
|
|
12
|
+
- **Action** — a reusable policy template you publishable through the dashboard. Declares `userParams` (values the human approves), `executionParams` (what the agent must supply at execution time), and the rules that compare them.
|
|
13
|
+
- **Mandate** — a signed W3C credential (type `POLICY`) the user issues to your agent. References one action plus the `userParams` values that bind this specific approval.
|
|
14
|
+
- **Verifiable Presentation (VP)** — a short-lived, signed proof derived from a mandate. The agent presents one each time it wants to act.
|
|
15
|
+
- **Verify** — Humanos checks the VP's signatures, expiry, revocation status, and the action's rules against the agent's `executionParams`. Returns allow or deny.
|
|
16
|
+
- **Revoke** — kills a mandate. Any further VP issuance or `verify` is denied.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
## Lifecycle
|
|
19
|
+
|
|
20
|
+
A mandate's lifetime breaks into two flows: **request and approval** (one-time, gets you a mandate ID) and **issuance and verification** (repeats every time the agent acts).
|
|
21
|
+
|
|
22
|
+
**Flow 1 — Request and approval**
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐ ┌─ accepts ─▶ mandate issued
|
|
26
|
+
│ Action │ ─▶ │ Agent needs │ ─▶ │ Agent │ ─▶ │ User │ ─▶ ─────┤
|
|
27
|
+
│ defined │ │ permission │ │ requests │ │ decides │ └─ rejects ─▶ flow ends
|
|
28
|
+
└──────────┘ └──────────────┘ └──────────┘ └──────────┘
|
|
29
|
+
step 1 step 2 step 3
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Flow 2 — Issuance and verification**
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
┌──────────┐ ┌──────────────────────────────┐ ┌─ true ─▶ allow (agent acts)
|
|
36
|
+
│ Agent │ ─▶ │ Humanos verifies VP against │ ─▶ ─────┤
|
|
37
|
+
│issues VP │ │ executionParams │ └─ false ─▶ deny (blocked)
|
|
38
|
+
└──────────┘ └──────────────────────────────┘
|
|
39
|
+
step 4 step 5
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
18
43
|
|
|
19
44
|
```bash
|
|
20
45
|
npm install humanos
|
|
21
46
|
```
|
|
22
47
|
|
|
23
|
-
|
|
48
|
+
Requires Node 18 or newer.
|
|
24
49
|
|
|
25
|
-
|
|
50
|
+
## Configuration
|
|
26
51
|
|
|
27
|
-
|
|
52
|
+
Sign up at [humanos.id](https://humanos.id), then grab two sets of credentials from the dashboard:
|
|
28
53
|
|
|
29
|
-
|
|
54
|
+
1. **API credentials** — **Settings → API Keys**. Copy the **API Key** and **Signature Secret**.
|
|
55
|
+
2. **Webhook credentials** — **Settings → Webhooks**. Copy the **Webhook Signature Secret**, **Webhook Encryption Secret**, and **Webhook Encryption Salt**.
|
|
30
56
|
|
|
31
|
-
|
|
32
|
-
- **Signature Secret** - Used to sign requests with HMAC-SHA256
|
|
57
|
+
Add them to your `.env`:
|
|
33
58
|
|
|
34
|
-
|
|
59
|
+
```env
|
|
60
|
+
HUMANOS_API_KEY=<your-api-key>
|
|
61
|
+
HUMANOS_SIGNATURE_SECRET=<your-signature-secret>
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
HUMANOS_WEBHOOK_SIGNATURE_SECRET=<your-webhook-signature-secret>
|
|
64
|
+
HUMANOS_WEBHOOK_ENCRYPTION_SECRET=<your-webhook-encryption-secret>
|
|
65
|
+
HUMANOS_WEBHOOK_ENCRYPTION_SALT=<your-webhook-encryption-salt>
|
|
66
|
+
```
|
|
37
67
|
|
|
38
|
-
|
|
39
|
-
- **Webhook Encryption Secret** - Used to decrypt webhook payloads
|
|
40
|
-
- **Webhook Encryption Salt** - Used alongside the encryption secret
|
|
68
|
+
Everything else (action URNs, mandate URNs, etc.) is application data — keep it in code or your database, not in `.env`.
|
|
41
69
|
|
|
42
|
-
|
|
70
|
+
## Quick start
|
|
43
71
|
|
|
44
72
|
```typescript
|
|
45
73
|
import { HumanosClient } from "humanos";
|
|
@@ -49,69 +77,86 @@ const client = new HumanosClient({
|
|
|
49
77
|
apiKey: process.env.HUMANOS_API_KEY!,
|
|
50
78
|
signatureSecret: process.env.HUMANOS_SIGNATURE_SECRET!,
|
|
51
79
|
});
|
|
80
|
+
|
|
81
|
+
// Sanity check — confirms the API key, signature secret, and signing handshake.
|
|
82
|
+
const { data } = await client.requests.list();
|
|
83
|
+
console.log(data);
|
|
52
84
|
```
|
|
53
85
|
|
|
54
|
-
|
|
86
|
+
A `200 OK` with a (possibly empty) list means you're wired up. The walkthrough below exercises the rest of the flow.
|
|
55
87
|
|
|
56
|
-
|
|
88
|
+
## Integration walkthrough
|
|
57
89
|
|
|
58
|
-
|
|
59
|
-
const response = await client.requests.getRequests();
|
|
60
|
-
console.log(response.data);
|
|
61
|
-
```
|
|
90
|
+
Six steps, matching the lifecycle diagram above. Run through them once with a test action to get an end-to-end feel.
|
|
62
91
|
|
|
63
|
-
|
|
92
|
+
### 1. Define an action
|
|
64
93
|
|
|
65
|
-
|
|
94
|
+
In the dashboard, create an **action**. An action has three parts:
|
|
66
95
|
|
|
67
|
-
|
|
96
|
+
- **`executionParams`** — the values the agent supplies at `verify()` time.
|
|
97
|
+
- **`userParams`** — the constants the user pins at decision time.
|
|
98
|
+
- **Rules** — deterministic CEL expressions comparing the two above.
|
|
68
99
|
|
|
69
|
-
|
|
70
|
-
const request = await client.requests.generate({
|
|
71
|
-
contacts: ["user@example.com"],
|
|
72
|
-
securityLevel: "CONTACT",
|
|
73
|
-
resourcesIds: ["your-resource-id"],
|
|
74
|
-
});
|
|
100
|
+
Example:
|
|
75
101
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
102
|
+
| Part | Field | Type |
|
|
103
|
+
| ----------------- | ------------------- | --------------- |
|
|
104
|
+
| `executionParams` | `amount` | number |
|
|
105
|
+
| | `category` | string |
|
|
106
|
+
| `userParams` | `maxAmount` | number |
|
|
107
|
+
| | `allowedCategories` | array\<string\> |
|
|
79
108
|
|
|
80
|
-
|
|
109
|
+
Rules then express things like `executionParams.amount <= userParams.maxAmount` and `executionParams.category in userParams.allowedCategories`.
|
|
81
110
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
securityLevel: "CONTACT",
|
|
86
|
-
groupIds: ["your-group-id"],
|
|
87
|
-
});
|
|
88
|
-
```
|
|
111
|
+
Once defined, **publish the action** and **copy its ID**. Hold the ID as a constant in your code or store it alongside the rule it represents.
|
|
112
|
+
|
|
113
|
+
### 2. Issue a mandate request
|
|
89
114
|
|
|
90
|
-
|
|
115
|
+
Ask Humanos to issue a mandate to a user. The request bundles the contact, the action ID, and the `userParams` values the user is being asked to approve.
|
|
91
116
|
|
|
92
117
|
```typescript
|
|
93
|
-
const
|
|
118
|
+
const actionId = "urn:via:action:<uuid>"; // from step 1
|
|
119
|
+
|
|
120
|
+
const request = await client.requests.create({
|
|
94
121
|
contacts: ["user@example.com"],
|
|
95
122
|
securityLevel: "CONTACT",
|
|
96
123
|
credentials: [
|
|
97
124
|
{
|
|
98
|
-
scope: "
|
|
99
|
-
type: "
|
|
100
|
-
name: "
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
125
|
+
scope: "agent.execute",
|
|
126
|
+
type: "POLICY",
|
|
127
|
+
name: "Action mandate", // required, shown to the user
|
|
128
|
+
action: {
|
|
129
|
+
id: actionId,
|
|
130
|
+
userParams: {
|
|
131
|
+
maxAmount: 10000,
|
|
132
|
+
allowedCategories: ["BOOKS", "OFFICE"],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
105
135
|
},
|
|
106
136
|
],
|
|
107
137
|
});
|
|
138
|
+
|
|
139
|
+
console.log("Request ID:", request.data.id);
|
|
108
140
|
```
|
|
109
141
|
|
|
110
|
-
|
|
142
|
+
Persist `request.data.id` if you want to track pending approvals. The mandate ID itself becomes available once the user approves (next step).
|
|
143
|
+
|
|
144
|
+
### 3. User approval and mandate issuance
|
|
111
145
|
|
|
112
|
-
Humanos
|
|
146
|
+
Humanos handles the user-facing approval flow. The user reviews the `userParams` from step 2 and either approves or rejects.
|
|
113
147
|
|
|
114
|
-
The
|
|
148
|
+
**Identity verification.** The security code (OTP) is always delivered by **email or SMS**.
|
|
149
|
+
|
|
150
|
+
**Where the approval UI shows up.** Two options:
|
|
151
|
+
|
|
152
|
+
- **Hosted (default)** — the email or SMS message contains a link to the Humanos-hosted approval page. The user clicks through, reviews, decides.
|
|
153
|
+
- **Embedded iframe** — your application embeds the Humanos approval UI directly. The user never leaves your app. See the [iframe integration guide](https://humanos.mintlify.app/essentials/iframe-integration) for setup.
|
|
154
|
+
|
|
155
|
+
If KYC is required on the action, the user completes that first. If the user rejects (or KYC fails), no mandate is issued.
|
|
156
|
+
|
|
157
|
+
**On accept, Humanos issues the mandate and emits a `credential` webhook event.** The mandate ID — `urn:via:credential:…` — is the durable artifact: persist it on the rule record in your database (e.g., `ruleId → mandateUrn`).
|
|
158
|
+
|
|
159
|
+
The SDK's `createWebhookHandler` verifies signatures and decrypts payloads automatically:
|
|
115
160
|
|
|
116
161
|
```typescript
|
|
117
162
|
import express from "express";
|
|
@@ -119,7 +164,8 @@ import { createWebhookHandler, WebhookConfig } from "humanos";
|
|
|
119
164
|
|
|
120
165
|
const app = express();
|
|
121
166
|
|
|
122
|
-
//
|
|
167
|
+
// IMPORTANT: use express.text() so the raw body is preserved for signature verification.
|
|
168
|
+
// express.json() reformats the payload and breaks the HMAC check.
|
|
123
169
|
app.use(express.text({ type: "application/json" }));
|
|
124
170
|
|
|
125
171
|
const webhookConfig: WebhookConfig = {
|
|
@@ -130,112 +176,262 @@ const webhookConfig: WebhookConfig = {
|
|
|
130
176
|
|
|
131
177
|
app.post(
|
|
132
178
|
"/webhook",
|
|
133
|
-
createWebhookHandler(webhookConfig, (payload) => {
|
|
134
|
-
console.log("Event type:", payload.eventType);
|
|
135
|
-
|
|
179
|
+
createWebhookHandler(webhookConfig, async (payload) => {
|
|
136
180
|
switch (payload.eventType) {
|
|
137
|
-
case "credential":
|
|
138
|
-
|
|
181
|
+
case "credential": {
|
|
182
|
+
if (payload.decision.action !== "accept") {
|
|
183
|
+
// user rejected — mark rule unenforceable, notify operator
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const mandateUrn = payload.credential.id;
|
|
187
|
+
// persist: ruleId → mandateUrn
|
|
139
188
|
break;
|
|
189
|
+
}
|
|
140
190
|
case "identity":
|
|
141
|
-
|
|
191
|
+
// KYC / identity verification completed
|
|
142
192
|
break;
|
|
143
193
|
case "otp.failed":
|
|
144
|
-
|
|
194
|
+
// user failed OTP — possible fraud signal
|
|
145
195
|
break;
|
|
146
196
|
case "test":
|
|
147
|
-
|
|
197
|
+
// "Send test event" from the dashboard
|
|
148
198
|
break;
|
|
149
199
|
}
|
|
150
200
|
}),
|
|
151
201
|
);
|
|
152
202
|
|
|
153
|
-
app.listen(3000
|
|
154
|
-
|
|
155
|
-
|
|
203
|
+
app.listen(3000);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The `credential` payload shape:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
{
|
|
210
|
+
eventType: "credential",
|
|
211
|
+
requestId: string,
|
|
212
|
+
internalId?: string,
|
|
213
|
+
issuerDid: string,
|
|
214
|
+
user: { contact: string; id: string; internalId?: string },
|
|
215
|
+
credential: CredentialEntity, // full W3C VC; .id is the mandate URN
|
|
216
|
+
decision: { action: "accept" | "reject", date: string }, // ISO 8601
|
|
217
|
+
}
|
|
156
218
|
```
|
|
157
219
|
|
|
158
|
-
For local development,
|
|
220
|
+
For local development, expose your server with [ngrok](https://ngrok.com):
|
|
159
221
|
|
|
160
222
|
```bash
|
|
161
223
|
ngrok http 3000
|
|
162
224
|
```
|
|
163
225
|
|
|
164
|
-
|
|
226
|
+
Set the ngrok URL (e.g. `https://xxxx.ngrok-free.app/webhook`) under **Settings → Webhooks**.
|
|
227
|
+
|
|
228
|
+
If you're using the iframe channel, the same `credential` payload is also delivered via `window.postMessage` to the parent window — useful for live UI updates without a backend round-trip.
|
|
229
|
+
|
|
230
|
+
> **Dev shortcut:** during development you can copy the mandate ID directly from the dashboard's activity table (look for the `MANDATE_ISSUE` entry) instead of wiring a webhook.
|
|
231
|
+
|
|
232
|
+
### 4. Agent issues a VP
|
|
233
|
+
|
|
234
|
+
When the agent wants to act, your backend (or whichever component enforces the rule) asks Humanos for a fresh **Verifiable Presentation** bound to the mandate id captured in step 3. VPs are short-lived and single-purpose — issue a new one for every verify.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
const mandateId = "urn:via:credential:<id>"; // captured in step 3
|
|
238
|
+
|
|
239
|
+
const vp = await client.credentials.issueVP(mandateId, {
|
|
240
|
+
// targetVerifier: "did:web:your-verifier.example", // optional, see below
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Field-by-field:
|
|
245
|
+
|
|
246
|
+
- **`mandateId`** (first positional arg) — the mandate ID captured in step 3.
|
|
247
|
+
- **`targetVerifier`** (optional body field) — DID of the intended verifier. When provided, the VP is bound to that audience via `proof.domain` plus a challenge nonce.
|
|
248
|
+
|
|
249
|
+
The response is a `PresentationResponseEntity` — `{ presentation, receipt }`. Pass `vp.data.presentation` to step 5.
|
|
165
250
|
|
|
166
|
-
|
|
251
|
+
### 5. Humanos verifies the VP
|
|
167
252
|
|
|
168
|
-
|
|
253
|
+
Hand the VP plus the agent's `executionParams` to `verify()`. Humanos checks four things: signatures, expiry, revocation status, and rule compliance. `200 OK` means allow; `403` means at least one check failed (the response body names the failing rule under `evaluations`).
|
|
169
254
|
|
|
170
255
|
```typescript
|
|
171
|
-
|
|
172
|
-
|
|
256
|
+
await client.credentials.verify({
|
|
257
|
+
presentation: vp.data.presentation,
|
|
258
|
+
executionParams: { amount: 5000, category: "BOOKS" },
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Field-by-field:
|
|
263
|
+
|
|
264
|
+
- **`presentation`** — the signed VP from step 4. Read it from `vp.data.presentation`.
|
|
265
|
+
- **`executionParams`** — what the agent wants to do. Field names must match those declared on the action and are referenced inside rules as `executionParams.<field>`.
|
|
266
|
+
|
|
267
|
+
Expected outcomes for the example action:
|
|
268
|
+
|
|
269
|
+
| Case | `executionParams` | Result |
|
|
270
|
+
| ------------- | ---------------------------------------- | ------------------------------------------- |
|
|
271
|
+
| In-bounds | `{ amount: 5000, category: "BOOKS" }` | allow (200) + signed receipt |
|
|
272
|
+
| Out-of-bounds | `{ amount: 50000, category: "FLIGHTS" }` | deny (403) — body names the failing rule(s) |
|
|
173
273
|
|
|
174
|
-
|
|
175
|
-
const groups = await client.resources.getGroups();
|
|
274
|
+
### 6. Revoke a mandate
|
|
176
275
|
|
|
177
|
-
|
|
178
|
-
|
|
276
|
+
Mandates are immutable — to retire one (rule deletion, rule update, user pulling consent), call `credentials.revoke()`. Once revoked, the mandate is dead: `issueVP` errors with `credential_revoked`, and any VP still held by an agent fails `verify()` with the same reason. Stale rules cannot be enforced; that's the safety property.
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
await client.credentials.revoke(
|
|
280
|
+
mandateUrn,
|
|
281
|
+
undefined, // aPIVersion — leave undefined to use the SDK default
|
|
282
|
+
{ reason: "user_initiated" },
|
|
283
|
+
);
|
|
179
284
|
```
|
|
180
285
|
|
|
181
|
-
|
|
286
|
+
Field-by-field:
|
|
287
|
+
|
|
288
|
+
- **`credentialId`** (first arg) — the mandate ID.
|
|
289
|
+
- **`reason`** — free-text label recorded on the credential and in the `MANDATE_REVOKED` receipt. Recommended values from the VIA protocol: `user_initiated`, `organization_policy`, `system_expiry`.
|
|
290
|
+
|
|
291
|
+
The response is a `RevokeCredentialEntity` — `credentialId`, `status: "REVOKED"`, `revokedAt`, and a `MANDATE_REVOKED` receipt. Store it for audit if useful. Enforcement uses the revocation status itself, not the receipt.
|
|
292
|
+
|
|
293
|
+
## Humanos audit trail
|
|
294
|
+
|
|
295
|
+
For compliance, Humanos persists every consequential event in a mandate's lifecycle as an **immutable, cryptographically signed record**. You don't need to log these yourself — they're available for query at any time via `client.activity.list()`.
|
|
296
|
+
|
|
297
|
+
| Event | Trigger | Captured |
|
|
298
|
+
| ---------------------- | ---------------------------------- | ----------------------------------------------------------------------- |
|
|
299
|
+
| Mandate issued | User accepts a request | Action ID, `userParams`, signed credential, timestamp |
|
|
300
|
+
| Mandate revoked | `credentials.revoke()` succeeds | Mandate ID, reason, timestamp |
|
|
301
|
+
| Mandate canceled | Request canceled before approval | Request ID, canceler, timestamp |
|
|
302
|
+
| Human decision: accept | User approves a request | User, request, OTP channel (email or SMS), UI surface (hosted / iframe) |
|
|
303
|
+
| Human decision: reject | User rejects a request | User, request, OTP channel, UI surface |
|
|
304
|
+
| VP issue | `credentials.issueVP()` succeeds | Mandate ID, VP, target verifier, receipt |
|
|
305
|
+
| VP issue denied | `credentials.issueVP()` rejected | Mandate ID, reason code (e.g., `credential_revoked`) |
|
|
306
|
+
| Verify accept | `credentials.verify()` returns 200 | VP, `executionParams`, rule evaluations, signed receipt |
|
|
307
|
+
| Verify deny | `credentials.verify()` returns 403 | VP, `executionParams`, failing rule(s), signed receipt |
|
|
308
|
+
|
|
309
|
+
## Webhook details
|
|
310
|
+
|
|
311
|
+
`createWebhookHandler` decrypts and verifies the payload, then dispatches a discriminated union — switch on `eventType` to narrow:
|
|
312
|
+
|
|
313
|
+
| Event | Trigger |
|
|
314
|
+
| ------------ | --------------------------------------------------------------------------------- |
|
|
315
|
+
| `credential` | A credential request was approved or rejected. `credential.id` is the mandate ID. |
|
|
316
|
+
| `identity` | An identity / KYC check completed. |
|
|
317
|
+
| `otp.failed` | A user failed OTP entry. |
|
|
318
|
+
| `test` | "Send test event" from the dashboard. |
|
|
319
|
+
|
|
320
|
+
**Operational notes**
|
|
321
|
+
|
|
322
|
+
- **Send a test event** from **Settings → Webhooks** before going live — confirms your URL is reachable and your handler decodes the payload.
|
|
323
|
+
- **Retries:** failed deliveries are retried with backoff. Make your handler idempotent (key off `requestId` + `eventType`).
|
|
324
|
+
- **Order:** events for unrelated requests may arrive out of order. Within a single request, `credential` precedes any follow-up events.
|
|
325
|
+
|
|
326
|
+
## API reference
|
|
327
|
+
|
|
328
|
+
Every method below is fully typed; signatures live in the generated definitions.
|
|
182
329
|
|
|
183
330
|
```typescript
|
|
184
|
-
//
|
|
185
|
-
|
|
331
|
+
// Requests — credential request lifecycle
|
|
332
|
+
client.requests.list(); // paginate / filter your requests
|
|
333
|
+
client.requests.create({ ... }); // issue a credential request to a user
|
|
334
|
+
client.requests.detail(requestId); // full request including credentials and subjects
|
|
335
|
+
client.requests.cancel(requestId); // cancel a pending request
|
|
336
|
+
client.requests.resendOtp(requestId); // resend OTP via the original channel
|
|
337
|
+
|
|
338
|
+
// Credentials — mandates and verification
|
|
339
|
+
client.credentials.detail(credentialId); // fetch a credential by ID
|
|
340
|
+
client.credentials.evidence(evidenceId); // download attached evidence
|
|
341
|
+
client.credentials.issueVP(vcId, { targetVerifier }); // issue a fresh VP from a mandate
|
|
342
|
+
client.credentials.verify({ presentation, executionParams }); // evaluate a VP at runtime
|
|
343
|
+
client.credentials.revoke(credentialId, undefined, { reason }); // permanently revoke a mandate
|
|
344
|
+
|
|
345
|
+
// Actions — published policy templates
|
|
346
|
+
client.actions.list();
|
|
347
|
+
client.actions.versions(actionId);
|
|
348
|
+
|
|
349
|
+
// Activity — audit log
|
|
350
|
+
client.activity.list();
|
|
351
|
+
|
|
352
|
+
// Approval workflows (forms, consents, documents)
|
|
353
|
+
client.approval.list();
|
|
354
|
+
client.approval.workflows();
|
|
355
|
+
|
|
356
|
+
// Users
|
|
357
|
+
client.users.create([{ contact, internalId, identity }]);
|
|
358
|
+
client.users.detail({ contact });
|
|
359
|
+
|
|
360
|
+
// DID resolution
|
|
361
|
+
client.did.resolve(did);
|
|
362
|
+
```
|
|
186
363
|
|
|
187
|
-
|
|
188
|
-
const detail = await client.requests.getRequestDetail(requestId);
|
|
364
|
+
## API versioning
|
|
189
365
|
|
|
190
|
-
|
|
191
|
-
const request = await client.requests.generate({ ... });
|
|
366
|
+
Humanos uses **date-based API versions** (e.g., `2026-03-24`). The SDK pins each release to a default version and sends it as an `api-version` header on every request — your integration stays isolated from API changes, and you upgrade by bumping the SDK on your own schedule.
|
|
192
367
|
|
|
193
|
-
|
|
194
|
-
await client.requests.cancelRequest(requestId);
|
|
368
|
+
The current default is exported as `API_VERSION`:
|
|
195
369
|
|
|
196
|
-
|
|
197
|
-
|
|
370
|
+
```typescript
|
|
371
|
+
import { API_VERSION } from "humanos";
|
|
372
|
+
console.log(API_VERSION); // "2026-03-24"
|
|
198
373
|
```
|
|
199
374
|
|
|
200
|
-
|
|
375
|
+
To pin a different version globally, override the header via `axiosConfig`:
|
|
201
376
|
|
|
202
377
|
```typescript
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
fullName: "John Doe",
|
|
210
|
-
birth: "1990-01-01",
|
|
211
|
-
docId: "123456789",
|
|
212
|
-
countryAlpha3: "USA",
|
|
213
|
-
},
|
|
378
|
+
const client = new HumanosClient({
|
|
379
|
+
basePath: "https://api.humanos.id",
|
|
380
|
+
apiKey: process.env.HUMANOS_API_KEY!,
|
|
381
|
+
signatureSecret: process.env.HUMANOS_SIGNATURE_SECRET!,
|
|
382
|
+
axiosConfig: {
|
|
383
|
+
headers: { "api-version": "2025-12-01" },
|
|
214
384
|
},
|
|
215
|
-
|
|
385
|
+
});
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Every method also accepts an optional `aPIVersion` parameter for per-call overrides — useful when testing a new version against a single endpoint before bumping globally:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
await client.credentials.verify(
|
|
392
|
+
{ presentation: vp.data.presentation, executionParams: { ... } },
|
|
393
|
+
"2025-12-01", // api version for this call only
|
|
394
|
+
);
|
|
216
395
|
```
|
|
217
396
|
|
|
218
|
-
|
|
397
|
+
**Action versions are independent of API versions.** When you republish an action in the dashboard, mandates already issued against the older version keep referencing that version — they don't break. List published versions with `client.actions.versions(actionId)`.
|
|
398
|
+
|
|
399
|
+
## Error handling
|
|
219
400
|
|
|
220
|
-
The SDK throws
|
|
401
|
+
The SDK throws on non-2xx responses. The error includes the underlying HTTP response when available:
|
|
221
402
|
|
|
222
403
|
```typescript
|
|
223
404
|
try {
|
|
224
|
-
|
|
405
|
+
await client.requests.create({ ... });
|
|
225
406
|
} catch (error) {
|
|
226
407
|
if (error.response) {
|
|
227
|
-
console.error(
|
|
228
|
-
console.error(
|
|
408
|
+
console.error("Status:", error.response.status);
|
|
409
|
+
console.error("Body:", error.response.data);
|
|
229
410
|
} else {
|
|
230
|
-
console.error(
|
|
411
|
+
console.error("Error:", error.message);
|
|
231
412
|
}
|
|
232
413
|
}
|
|
233
414
|
```
|
|
234
415
|
|
|
235
|
-
##
|
|
416
|
+
## Troubleshooting
|
|
417
|
+
|
|
418
|
+
**`401` on every request.** Signature mismatch. Double-check the signature secret matches the dashboard exactly — no trailing whitespace or stray newline.
|
|
419
|
+
|
|
420
|
+
**`400` on `requests.create()` with "name is required".** Each `credentials[]` entry needs a `name` field. The example in step 2 uses `"Action mandate"`.
|
|
421
|
+
|
|
422
|
+
**Webhook never fires.** Confirm the URL in **Settings → Webhooks** matches your live endpoint. Send a test event from the dashboard. For local dev, the ngrok tunnel must be open when the user approves.
|
|
423
|
+
|
|
424
|
+
**Webhook fires but the handler errors with a signature mismatch.** Make sure your server uses `express.text({ type: "application/json" })`. `express.json()` parses + reformats the body, which breaks HMAC verification.
|
|
425
|
+
|
|
426
|
+
**`verify()` returns 403 with no obvious failing rule.** Check that the `executionParams` field names exactly match the action's declared fields. A typo silently fails rule evaluation.
|
|
427
|
+
|
|
428
|
+
**`issueVP()` returns 400 after revoke.** Expected — once a mandate is revoked, VP issuance is blocked at source with `credential_revoked`. Existing VPs also fail `verify()` for the same reason.
|
|
429
|
+
|
|
430
|
+
## Documentation & related
|
|
236
431
|
|
|
237
|
-
- [API
|
|
238
|
-
- [Humanos
|
|
432
|
+
- [Full API documentation](https://humanos.mintlify.app/)
|
|
433
|
+
- [Humanos website](https://humanos.id)
|
|
434
|
+
- Sister SDKs: [Python](../python/README.md), [C#](../csharp/README.md)
|
|
239
435
|
|
|
240
436
|
## Support
|
|
241
437
|
|
|
@@ -243,4 +439,4 @@ try {
|
|
|
243
439
|
|
|
244
440
|
## License
|
|
245
441
|
|
|
246
|
-
MIT License
|
|
442
|
+
MIT License — see [LICENSE](./LICENSE) file for details.
|