@delegance/sdk 0.1.0 → 0.2.1
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/LICENSE +21 -0
- package/README.md +300 -216
- package/dist/index.d.mts +1048 -85
- package/dist/index.d.ts +1048 -85
- package/dist/index.js +681 -32
- package/dist/index.mjs +662 -31
- package/package.json +25 -19
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Delegance Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,308 +1,392 @@
|
|
|
1
1
|
# @delegance/sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK
|
|
3
|
+
Get commercial insurance quotes from your code. This TypeScript SDK covers the Delegance API: signup, instant quotes, bind, payments, policies, certificates, bonds, claims, and documents.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Full docs: https://portal.delegancebrokerage.com/docs/sdk
|
|
6
|
+
|
|
7
|
+
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
npm install @delegance/sdk
|
|
9
|
-
# or
|
|
10
|
-
yarn add @delegance/sdk
|
|
11
|
-
# or
|
|
12
|
-
pnpm add @delegance/sdk
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
Requires Node 18 or newer. The package ships CommonJS, ESM, and TypeScript types.
|
|
14
|
+
|
|
15
|
+
Prefer a terminal? [`@delegance/cli`](https://www.npmjs.com/package/@delegance/cli) runs the same flows: `npx -y @delegance/cli quote start --demo`.
|
|
16
|
+
|
|
17
|
+
## Availability
|
|
18
|
+
|
|
19
|
+
- Quoting is open to every account. A new account from `createSignup()` can quote as soon as the owner confirms the email.
|
|
20
|
+
- Bind, payments, bonds, and claims are live over the API.
|
|
21
|
+
- A licensed Delegance broker approves every bind before coverage starts. `instantQuotes.bind()` files the request; it never charges a card.
|
|
22
|
+
- A switched-off feature answers 503 with `reason: 'not_available'`. The SDK does not retry that answer.
|
|
23
|
+
|
|
24
|
+
## One key, one company
|
|
25
|
+
|
|
26
|
+
An API key belongs to exactly one company. Every call acts on that company, so you never pass a company id to quote.
|
|
27
|
+
|
|
28
|
+
- `documents.upload()` and `documents.list()` take an optional `companyId`. Leave it out. If you name a company the key does not belong to, the server answers 403 with `code: 'company_mismatch'`.
|
|
29
|
+
- A customer key cannot create companies. `companies.create()` and `companies.upsert()` answer 403 `tenant_key_cannot_create`. Open a new account with `createSignup()` instead.
|
|
30
|
+
- `companies.list()` returns the key's own company.
|
|
31
|
+
|
|
32
|
+
## Quick start: sign up and quote
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { createSignup, newDeviceSecret, DeleganceClient } from '@delegance/sdk';
|
|
36
|
+
|
|
37
|
+
// 1. Create the account. Keep `device.secret` on this machine only.
|
|
38
|
+
const signup = createSignup();
|
|
39
|
+
const account = await signup.createAccount({
|
|
40
|
+
name: 'Acme Bakery',
|
|
41
|
+
contactEmail: 'owner@acmebakery.com',
|
|
42
|
+
industry: 'commercial bakery',
|
|
43
|
+
companySize: '2-10',
|
|
44
|
+
address: { street: '100 Main St', city: 'Austin', state: 'TX', zip: '78701' },
|
|
45
|
+
});
|
|
46
|
+
const device = newDeviceSecret();
|
|
47
|
+
const { enrollmentId } = await signup.enroll(account.bootstrapKey, {
|
|
48
|
+
deviceSecretHash: device.hash,
|
|
49
|
+
firstName: 'Dana',
|
|
50
|
+
lastName: 'Owner',
|
|
51
|
+
});
|
|
52
|
+
await signup.requestVerification(account.bootstrapKey);
|
|
53
|
+
|
|
54
|
+
// 2. The owner clicks the emailed confirm link. Then collect the API key.
|
|
55
|
+
const result = await signup.waitForKey(enrollmentId, device.secret);
|
|
56
|
+
if (result.status !== 'ready') throw new Error('Confirm link not clicked yet');
|
|
57
|
+
|
|
58
|
+
// 3. Quote. See "Instant quotes" below for the answers.
|
|
59
|
+
const client = new DeleganceClient({ apiKey: result.apiKey });
|
|
60
|
+
const session = await client.instantQuotes.start(['general_liability']);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Store `result.apiKey` somewhere safe. The server shows it once.
|
|
64
|
+
|
|
65
|
+
## Quick start: existing API key
|
|
16
66
|
|
|
17
67
|
```typescript
|
|
18
68
|
import { DeleganceClient } from '@delegance/sdk';
|
|
19
69
|
import fs from 'fs';
|
|
20
70
|
|
|
21
|
-
|
|
22
|
-
const client = new DeleganceClient({
|
|
23
|
-
apiKey: 'dlg_xxxxxxxx_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// Create a company
|
|
27
|
-
const company = await client.companies.create({
|
|
28
|
-
name: 'ABC Construction',
|
|
29
|
-
industry: 'construction',
|
|
30
|
-
companySize: '11-25',
|
|
31
|
-
contactEmail: 'contact@abcconstruction.com',
|
|
32
|
-
fein: '12-3456789',
|
|
33
|
-
address: {
|
|
34
|
-
street: '123 Main St',
|
|
35
|
-
city: 'Austin',
|
|
36
|
-
state: 'TX',
|
|
37
|
-
zip: '78701'
|
|
38
|
-
}
|
|
39
|
-
});
|
|
71
|
+
const client = new DeleganceClient({ apiKey: process.env.DELEGANCE_API_KEY! });
|
|
40
72
|
|
|
41
|
-
|
|
73
|
+
// The key's own company
|
|
74
|
+
const [company] = await client.companies.list();
|
|
75
|
+
console.log(company.name);
|
|
42
76
|
|
|
43
|
-
// Upload a policy
|
|
77
|
+
// Upload a policy. No companyId: the key decides the company.
|
|
44
78
|
const doc = await client.documents.upload({
|
|
45
|
-
companyId: company.id,
|
|
46
79
|
file: fs.readFileSync('./GL-Policy-2025.pdf'),
|
|
47
80
|
fileName: 'GL-Policy-2025.pdf',
|
|
48
|
-
documentType: 'policy'
|
|
81
|
+
documentType: 'policy',
|
|
49
82
|
});
|
|
50
83
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Wait for extraction to complete
|
|
54
|
-
const result = await client.documents.waitForExtraction(doc.id, {
|
|
55
|
-
timeoutMs: 60000,
|
|
56
|
-
onStatusChange: (status) => console.log('Processing:', status)
|
|
57
|
-
});
|
|
84
|
+
const done = await client.documents.waitForExtraction(doc.id, { timeoutMs: 120_000 });
|
|
85
|
+
console.log(done.extraction?.policies);
|
|
58
86
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
87
|
+
// Read what is in force
|
|
88
|
+
const { policies } = await client.policies.list();
|
|
62
89
|
```
|
|
63
90
|
|
|
64
|
-
##
|
|
91
|
+
## Instant quotes
|
|
92
|
+
|
|
93
|
+
Real carrier premiums over the API. The flow has four calls.
|
|
65
94
|
|
|
66
|
-
|
|
95
|
+
1. `start(coverages)` returns the session and the carriers' questions.
|
|
96
|
+
2. `submit()` files your answers with the carriers.
|
|
97
|
+
3. `status()` or `waitForQuotes()` returns premiums as carriers answer.
|
|
98
|
+
4. `bind()` requests a bind on one offer.
|
|
99
|
+
|
|
100
|
+
Coverage ids: `general_liability`, `workers_comp`, `business_owners`, `cyber`, `professional_liability`, `tech_eo`, `commercial_auto`, `commercial_property`, `umbrella`.
|
|
67
101
|
|
|
68
102
|
```typescript
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// Optional: Custom headers
|
|
83
|
-
headers: {
|
|
84
|
-
'X-Custom-Header': 'value'
|
|
85
|
-
}
|
|
103
|
+
const session = await client.instantQuotes.start(['general_liability', 'workers_comp']);
|
|
104
|
+
|
|
105
|
+
// Each question: { id, label, type, options?, required, prefill?, suggested?, showIf?, requiredIfShown? }
|
|
106
|
+
const answers: Record<string, unknown> = {};
|
|
107
|
+
for (const q of session.questions) {
|
|
108
|
+
if (q.prefill !== undefined && q.prefill !== null) answers[q.id] = q.prefill;
|
|
109
|
+
}
|
|
110
|
+
answers.annual_revenue = 850000;
|
|
111
|
+
|
|
112
|
+
const submitted = await client.instantQuotes.submit({
|
|
113
|
+
submissionId: session.submissionId,
|
|
114
|
+
sessionVersion: session.sessionVersion,
|
|
115
|
+
answers,
|
|
86
116
|
});
|
|
117
|
+
|
|
118
|
+
if (submitted.status === 'submitted') {
|
|
119
|
+
const status = await client.instantQuotes.waitForQuotes(session.submissionId, { timeoutMs: 10 * 60_000 });
|
|
120
|
+
console.log('Coverage starts', status.effectiveDate);
|
|
121
|
+
for (const q of status.carrierQuotes) {
|
|
122
|
+
console.log(q.coverage, q.carrierName, q.premium, q.limits, q.deductible, q.bindable);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
87
125
|
```
|
|
88
126
|
|
|
89
|
-
###
|
|
127
|
+
### Answers
|
|
90
128
|
|
|
91
|
-
|
|
129
|
+
- Key every answer by question `id`.
|
|
130
|
+
- `yes_no`: `'yes'` or `'no'`. `number`, `currency`, `percentage`: a number. `select`: one option `value`. Anything else: text.
|
|
131
|
+
- `prefill` comes from the insured's own account data. Send it back unless the insured changes it.
|
|
132
|
+
- `suggested` is a guess from another source. It counts only after the insured confirms it.
|
|
133
|
+
- `showIf: { questionId, equals }` hides a follow-up until the parent answer matches. A hidden question is never required. `requiredIfShown` makes it required while visible.
|
|
92
134
|
|
|
93
|
-
|
|
94
|
-
import { createClientFromEnv } from '@delegance/sdk';
|
|
135
|
+
### Submit results
|
|
95
136
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
137
|
+
`submit()` returns `status`:
|
|
138
|
+
|
|
139
|
+
| Status | Meaning |
|
|
140
|
+
|--------|---------|
|
|
141
|
+
| `submitted` | Filed with the instant carriers. Poll `status()` for premiums. |
|
|
142
|
+
| `acord_pending` | Some coverages need a person. A broker task opened (`brokerTaskId`). |
|
|
143
|
+
| `no_carriers` | No carrier can quote this instantly. Hand it to a broker (below). |
|
|
144
|
+
|
|
145
|
+
A second submit for coverage that already has a live request answers 409 `active_request_exists`. To re-quote, call `start(coverages, { fresh: true })` and submit with `replace: true`.
|
|
146
|
+
|
|
147
|
+
### Reading quotes
|
|
148
|
+
|
|
149
|
+
`status()` returns `carrierQuotes`, one row per carrier offer:
|
|
150
|
+
|
|
151
|
+
- `premium`: annual premium in dollars, or null before the carrier prices it.
|
|
152
|
+
- `bindable`: true when you can bind the offer.
|
|
153
|
+
- `limits`: readable limits, for example `"$1M per occurrence / $2M aggregate"` or `"Statutory / $1M employers liability"`.
|
|
154
|
+
- `deductible`: dollars, 0 for none. Today only cyber quotes carry one; other lines return null.
|
|
155
|
+
- `effectiveDate` (on the status): when coverage would start, as `YYYY-MM-DD`.
|
|
99
156
|
|
|
100
|
-
|
|
157
|
+
The three fields are new in 0.2.1. An older server leaves them out, so treat a missing field like null.
|
|
101
158
|
|
|
102
|
-
|
|
159
|
+
Compare prices within one coverage only. The cheapest bindable offer per coverage is the one to show first.
|
|
103
160
|
|
|
104
|
-
|
|
161
|
+
### No instant carrier: broker handoff
|
|
105
162
|
|
|
106
163
|
```typescript
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
yearEstablished: '2015',
|
|
118
|
-
companyStructure: 'LLC',
|
|
119
|
-
description: 'Commercial construction company',
|
|
120
|
-
contactPhone: '+1-555-123-4567',
|
|
121
|
-
externalId: 'ams-12345', // For deduplication
|
|
122
|
-
address: {
|
|
123
|
-
street: '123 Main St',
|
|
124
|
-
suite: 'Suite 100',
|
|
125
|
-
city: 'Austin',
|
|
126
|
-
state: 'TX',
|
|
127
|
-
zip: '78701'
|
|
128
|
-
}
|
|
129
|
-
});
|
|
164
|
+
if (submitted.status === 'no_carriers') {
|
|
165
|
+
const plan = await client.instantQuotes.brokerHandoffQuestions(session.submissionId, answers);
|
|
166
|
+
const acordAnswers: Record<string, unknown> = {}; // answer plan.questions the same way
|
|
167
|
+
const handoff = await client.instantQuotes.brokerHandoff(session.submissionId, {
|
|
168
|
+
answers: acordAnswers,
|
|
169
|
+
instantAnswers: answers,
|
|
170
|
+
complete: true,
|
|
171
|
+
});
|
|
172
|
+
console.log(handoff.status, handoff.brokerTaskId); // 'broker_review'
|
|
173
|
+
}
|
|
130
174
|
```
|
|
131
175
|
|
|
132
|
-
|
|
176
|
+
A broker places the risk with a market that quotes by hand and emails the owner. `complete: false` says you stopped early; the broker asks the rest. A repeat call returns the same broker task. `status().brokerReview` shows the task.
|
|
133
177
|
|
|
134
|
-
|
|
135
|
-
// List your company
|
|
136
|
-
const companies = await client.companies.list();
|
|
178
|
+
### Bind and pay
|
|
137
179
|
|
|
138
|
-
|
|
139
|
-
const
|
|
180
|
+
```typescript
|
|
181
|
+
const status = await client.instantQuotes.status(session.submissionId);
|
|
182
|
+
const offer = status.carrierQuotes.find((q) => q.bindable && q.premium !== null);
|
|
183
|
+
if (!offer) throw new Error('No bindable offer yet');
|
|
184
|
+
|
|
185
|
+
const bind = await client.instantQuotes.bind(session.submissionId, offer.opportunityId);
|
|
186
|
+
console.log(bind.status, bind.next);
|
|
187
|
+
|
|
188
|
+
// After a broker approves the bind, a payment request appears
|
|
189
|
+
const due = (await client.payments.list()).filter((p) => p.payable);
|
|
190
|
+
if (due[0]) {
|
|
191
|
+
const { checkoutUrl } = await client.payments.checkout(due[0].id);
|
|
192
|
+
console.log('Pay here:', checkoutUrl); // Stripe checkout
|
|
193
|
+
}
|
|
140
194
|
```
|
|
141
195
|
|
|
142
|
-
|
|
196
|
+
A Delegance broker approves each bind request. You get an email when payment is ready. One live bind per coverage per submission: a repeat returns the existing request (`existing: true`).
|
|
143
197
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
industry: 'construction',
|
|
148
|
-
companySize: '11-25',
|
|
149
|
-
contactEmail: 'contact@abc.com',
|
|
150
|
-
externalId: 'ams-12345' // Deduplication key
|
|
151
|
-
});
|
|
198
|
+
`bindWithStepUp()` covers fast bind, where the owner attests the answers and enters a 6-digit code we email. Fast bind with the carrier's own checkout (tier A) is not open yet; until it is, every bind goes to a broker.
|
|
199
|
+
|
|
200
|
+
## Device login (existing customers)
|
|
152
201
|
|
|
153
|
-
|
|
154
|
-
|
|
202
|
+
A person who already has a portal account approves a new device in the browser. No API key is needed to start.
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { createDeviceLogin, newDeviceSecret, DeleganceClient } from '@delegance/sdk';
|
|
206
|
+
|
|
207
|
+
const login = createDeviceLogin();
|
|
208
|
+
const device = newDeviceSecret();
|
|
209
|
+
const start = await login.start({ deviceSecretHash: device.hash, deviceName: 'build-server' });
|
|
210
|
+
console.log(`Open ${start.verificationUriComplete} and confirm code ${start.userCode}`);
|
|
211
|
+
|
|
212
|
+
const result = await login.waitForKey(start.loginId, device.secret);
|
|
213
|
+
if (result.status === 'ready') {
|
|
214
|
+
const client = new DeleganceClient({ apiKey: result.apiKey });
|
|
215
|
+
const info = await client.auth.keyInfo(); // scopes, company, expiry
|
|
216
|
+
if (info.refreshable) await client.auth.refresh(); // extend a CLI key
|
|
155
217
|
}
|
|
156
218
|
```
|
|
157
219
|
|
|
158
|
-
|
|
220
|
+
## API keys
|
|
159
221
|
|
|
160
|
-
|
|
222
|
+
Create keys in the portal (Settings > API keys), with `delegance signup` / `delegance auth login`, or with `client.apiKeys.create()` from a key with the `admin` scope.
|
|
161
223
|
|
|
162
|
-
|
|
163
|
-
import fs from 'fs';
|
|
224
|
+
Key rules:
|
|
164
225
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
226
|
+
- A key belongs to one company.
|
|
227
|
+
- A new key expires in 90 days unless you pick another expiry.
|
|
228
|
+
- A key with `write`, `admin`, or `claims:write` must expire within 365 days. `expiresInDays: 'never'` is allowed only for a read-only key; otherwise the server answers 400 `write_key_requires_expiry`.
|
|
229
|
+
- `claims:write` can be created only while signed in to the portal (signup and device login keys for owners and admins carry it).
|
|
230
|
+
- Delegance staff accounts cannot create client keys (403).
|
|
231
|
+
- `appetite:read`, `mcp:read`, `mcp:orin`, and `claims:write` are opt-in. `read` and `write` never imply them.
|
|
232
|
+
- Keys from signup and device login refresh with `client.auth.refresh()`.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const created = await client.apiKeys.create({
|
|
236
|
+
name: 'CI uploader',
|
|
237
|
+
scopes: ['read', 'write'],
|
|
238
|
+
expiresInDays: 90,
|
|
174
239
|
});
|
|
240
|
+
console.log('Save this key now:', created.key);
|
|
175
241
|
```
|
|
176
242
|
|
|
177
|
-
|
|
243
|
+
Format: `dlg_xxxxxxxx_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`.
|
|
244
|
+
|
|
245
|
+
## Limits
|
|
246
|
+
|
|
247
|
+
| Limit | Error |
|
|
248
|
+
|-------|-------|
|
|
249
|
+
| Quote starts per key per day | 429 `quote_limit_reached` |
|
|
250
|
+
| Per-key daily AI budget (chat, quote sessions) | 429 `api_key_budget_exhausted` |
|
|
251
|
+
| Delegance-wide daily API AI budget | 429 `api_budget_exhausted`, `Retry-After: 3600` |
|
|
252
|
+
| Requests per minute | 429, see `client.usage.rateLimits()` |
|
|
253
|
+
|
|
254
|
+
The SDK does not retry a 429. Read `err.retryAfter` (seconds, from the body or the `Retry-After` header) and wait before you call again.
|
|
255
|
+
|
|
256
|
+
## Other modules
|
|
257
|
+
|
|
258
|
+
Every module hangs off the client. Each one has a docs page with examples.
|
|
259
|
+
|
|
260
|
+
| Module | What it does |
|
|
261
|
+
|--------|--------------|
|
|
262
|
+
| `instantQuotes` | Start, submit, status, broker handoff, bind |
|
|
263
|
+
| `payments` | Premium payment requests and checkout links |
|
|
264
|
+
| `bonds` | Surety bond quotes; you buy on the surety's page |
|
|
265
|
+
| `claims` | File and track claims (needs `claims:write`; accept the claims disclaimer once in the portal) |
|
|
266
|
+
| `policies` | Policies in force, expiring soon, cancellation requests |
|
|
267
|
+
| `coi` | Certificates of insurance |
|
|
268
|
+
| `documents` | Upload, extraction status, list |
|
|
269
|
+
| `sov` | Schedules of values |
|
|
270
|
+
| `chat` | Ask about your coverage |
|
|
271
|
+
| `knowledge` | Notecards and facts extracted from a document |
|
|
272
|
+
| `appetite` | Which carriers will write a risk (needs `appetite:read`) |
|
|
273
|
+
| `leads` | Send a prospect business to Delegance |
|
|
274
|
+
| `onboarding` | Account setup status and verification email |
|
|
275
|
+
| `feedback` | Report a bug, an idea, or a question |
|
|
276
|
+
| `usage` | Billing-period usage, daily usage, rate limits |
|
|
277
|
+
| `apiKeys` | Create, list, revoke keys |
|
|
278
|
+
| `auth` | Key info and refresh |
|
|
279
|
+
| `companies` | The key's own company |
|
|
280
|
+
| `quotes` | Legacy partner quote queue. Submission answers 501; use `instantQuotes` |
|
|
281
|
+
|
|
282
|
+
### Bonds
|
|
178
283
|
|
|
179
284
|
```typescript
|
|
180
|
-
const
|
|
181
|
-
{ companyId, file: buffer1, fileName: 'policy1.pdf' },
|
|
182
|
-
{ companyId, file: buffer2, fileName: 'policy2.pdf' },
|
|
183
|
-
{ companyId, file: buffer3, fileName: 'policy3.pdf' }
|
|
184
|
-
], { concurrency: 3 });
|
|
185
|
-
|
|
186
|
-
console.log(`Uploaded ${documents.length} documents`);
|
|
187
|
-
if (errors.length > 0) {
|
|
188
|
-
console.error('Failed uploads:', errors);
|
|
189
|
-
}
|
|
285
|
+
const start = await client.bonds.start({ state: 'TX', bondName: 'notary' });
|
|
190
286
|
```
|
|
191
287
|
|
|
192
|
-
|
|
288
|
+
### Claims
|
|
193
289
|
|
|
194
290
|
```typescript
|
|
195
|
-
const
|
|
291
|
+
const claim = await client.claims.file({ description: 'Water damage in the kitchen', incidentDate: '2026-10-01' });
|
|
292
|
+
console.log(claim.claimId, claim.status, claim.portalUrl);
|
|
293
|
+
```
|
|
196
294
|
|
|
197
|
-
|
|
198
|
-
// 'pending' | 'processing' | 'completed' | 'processed' | 'error' | 'failed'
|
|
295
|
+
A 403 with `reason: 'gate_not_acknowledged'` means the claims disclaimer is not accepted yet. The owner accepts it once in the portal (`err.body.portalUrl`).
|
|
199
296
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
297
|
+
### Feedback
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
const { id } = await client.feedback.submit({
|
|
301
|
+
type: 'bug',
|
|
302
|
+
message: 'quote submit hung on the delivery question',
|
|
303
|
+
context: { command: 'quote submit', exitCode: 1, traceId: 'trace-from-the-error' },
|
|
304
|
+
});
|
|
203
305
|
```
|
|
204
306
|
|
|
205
|
-
|
|
307
|
+
### Appetite
|
|
206
308
|
|
|
207
|
-
|
|
208
|
-
// List all documents
|
|
209
|
-
const { documents, pagination } = await client.documents.list();
|
|
309
|
+
Needs a key with the `appetite:read` scope. A warm cache hit returns the result at once; a cold match returns a job to poll.
|
|
210
310
|
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
offset: 0
|
|
311
|
+
```typescript
|
|
312
|
+
const start = await client.appetite.match({
|
|
313
|
+
state: 'CA',
|
|
314
|
+
industry: 'commercial bakery',
|
|
315
|
+
coverageTypes: ['general_liability', 'workers_comp'],
|
|
217
316
|
});
|
|
218
|
-
|
|
219
|
-
// Paginate
|
|
220
|
-
while (pagination.hasMore) {
|
|
221
|
-
const next = await client.documents.list({ offset: pagination.offset + 50 });
|
|
222
|
-
// ...
|
|
223
|
-
}
|
|
317
|
+
const result = start.status === 'succeeded' ? start : await client.appetite.waitForMatch(start.jobId);
|
|
224
318
|
```
|
|
225
319
|
|
|
226
|
-
|
|
320
|
+
### Leads
|
|
321
|
+
|
|
322
|
+
Idempotent on `externalId`. A contact email that already belongs to a company returns that company.
|
|
227
323
|
|
|
228
324
|
```typescript
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
325
|
+
const { companyId } = await client.leads.create({
|
|
326
|
+
name: 'Riverbend Bakery',
|
|
327
|
+
contactEmail: 'owner@riverbend.example',
|
|
328
|
+
state: 'TX',
|
|
329
|
+
externalId: 'crm-4411',
|
|
233
330
|
});
|
|
234
|
-
|
|
235
|
-
if (result.status === 'completed') {
|
|
236
|
-
console.log('Policies found:', result.extraction?.policies.length);
|
|
237
|
-
} else if (result.status === 'error') {
|
|
238
|
-
console.error('Processing failed:', result.error?.message);
|
|
239
|
-
}
|
|
240
331
|
```
|
|
241
332
|
|
|
242
|
-
##
|
|
333
|
+
## Use it from an AI agent
|
|
243
334
|
|
|
244
|
-
|
|
335
|
+
Claude Code, Codex, Gemini CLI, and other coding agents can drive the SDK or the CLI. The CLI is often simpler for an agent: `npx -y @delegance/cli quote start --json` prints the questions as JSON, and `--answers answers.json` files them. See the CLI README section "Use it from an AI agent" and https://portal.delegancebrokerage.com/docs/cli.
|
|
245
336
|
|
|
246
|
-
|
|
247
|
-
import {
|
|
248
|
-
AuthenticationError,
|
|
249
|
-
ValidationError,
|
|
250
|
-
NotFoundError,
|
|
251
|
-
RateLimitError,
|
|
252
|
-
DeleganceError
|
|
253
|
-
} from '@delegance/sdk';
|
|
337
|
+
Rules that keep an agent safe:
|
|
254
338
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
339
|
+
- Read the key from `DELEGANCE_API_KEY`. Never paste it into a prompt or a file the agent commits.
|
|
340
|
+
- Pass your own `idempotencyKey` to `submit()`, `bind()`, and `brokerHandoff()` when the agent may retry across restarts. The same key lands on the same request.
|
|
341
|
+
- Gate on `err.reason` and `err.code`, never on the message text.
|
|
342
|
+
|
|
343
|
+
## Configuration
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
const client = new DeleganceClient({
|
|
347
|
+
apiKey: 'dlg_xxxxxxxx_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // required
|
|
348
|
+
baseUrl: 'https://portal.delegancebrokerage.com', // default
|
|
349
|
+
timeout: 30000, // ms, default 30000
|
|
350
|
+
retries: 3, // default 3
|
|
351
|
+
headers: { 'X-Custom-Header': 'value' },
|
|
352
|
+
});
|
|
270
353
|
```
|
|
271
354
|
|
|
272
|
-
|
|
355
|
+
`createClientFromEnv()` reads `DELEGANCE_API_KEY` and, if set, `DELEGANCE_BASE_URL`.
|
|
273
356
|
|
|
274
|
-
|
|
357
|
+
## Errors
|
|
275
358
|
|
|
276
359
|
```typescript
|
|
277
|
-
import
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
360
|
+
import {
|
|
361
|
+
DeleganceError,
|
|
362
|
+
AuthenticationError, // 401
|
|
363
|
+
ValidationError, // 400
|
|
364
|
+
ForbiddenError, // 403
|
|
365
|
+
NotFoundError, // 404
|
|
366
|
+
RateLimitError, // 429
|
|
367
|
+
NotImplementedError, // 501
|
|
284
368
|
} from '@delegance/sdk';
|
|
285
369
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
370
|
+
try {
|
|
371
|
+
await client.documents.list({ companyId: 'another-company' });
|
|
372
|
+
} catch (err) {
|
|
373
|
+
if (err instanceof DeleganceError) {
|
|
374
|
+
console.error(err.statusCode, err.reason, err.code, err.message, err.traceId);
|
|
375
|
+
}
|
|
292
376
|
}
|
|
293
377
|
```
|
|
294
378
|
|
|
295
|
-
|
|
379
|
+
Every error carries:
|
|
296
380
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
381
|
+
- `statusCode`: the HTTP status.
|
|
382
|
+
- `reason`: the machine-readable reason from the body, when sent (`not_available`, `quote_limit_reached`, `active_request_exists`, `attestation_required`, ...).
|
|
383
|
+
- `code`: the body's `code`, when sent (`company_mismatch`). New in 0.2.1; on 0.2.0 read `err.body.code`.
|
|
384
|
+
- `body`: the parsed error body, for fields such as `portalUrl`.
|
|
385
|
+
- `traceId`: quote it to support.
|
|
301
386
|
|
|
302
|
-
|
|
387
|
+
Retries: the SDK retries network failures and 5xx answers other than 501, with backoff. It never retries a 4xx (including 429), a 501, or a 503 with `reason: 'not_available'`.
|
|
303
388
|
|
|
304
389
|
## Support
|
|
305
390
|
|
|
306
|
-
-
|
|
307
|
-
-
|
|
308
|
-
- Email: support@delegance.ai
|
|
391
|
+
- Docs: https://portal.delegancebrokerage.com/docs/sdk
|
|
392
|
+
- Email: support@delegancebrokerage.com
|