attio-ts-sdk 1.0.0 → 1.1.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/README.md +393 -53
- package/dist/index.d.mts +522 -163
- package/dist/index.mjs +744 -146
- package/dist/index.mjs.map +1 -1
- package/package.json +27 -12
package/README.md
CHANGED
|
@@ -7,25 +7,50 @@
|
|
|
7
7
|
[](https://context7.com/hbmartin/attio-ts-sdk)
|
|
8
8
|
[](https://deepwiki.com/hbmartin/attio-ts-sdk)
|
|
9
9
|
|
|
10
|
-
A modern, type-safe TypeScript SDK for the [Attio](https://attio.com) CRM API. Built with Zod v4 and a
|
|
11
|
-
|
|
12
|
-
- **Create an Attio client in one line** (`createAttioClient({ apiKey })`)
|
|
13
|
-
- **Retry & rate‑limit aware** (exponential backoff + `Retry-After`)
|
|
14
|
-
- **Normalized errors** (consistent shape + optional suggestions for select/status mismatches)
|
|
15
|
-
- **Record normalization** (handles inconsistent response shapes)
|
|
16
|
-
- **Metadata caching** (attributes, select options, statuses)
|
|
17
|
-
- **Pagination helpers** (`paginate` + cursor handling)
|
|
18
|
-
|
|
19
|
-
You still have full access to the generated, spec‑accurate endpoints.
|
|
20
|
-
|
|
21
|
-
## Features
|
|
10
|
+
A modern, type-safe TypeScript SDK for the [Attio](https://attio.com) CRM API. Built with Zod v4 and a client layer that adds retries, error normalization, caching, and higher‑level helpers on top of the generated OpenAPI client.
|
|
22
11
|
|
|
23
12
|
- **Full Attio API Coverage** - People, companies, lists, notes, tasks, meetings, webhooks, and more
|
|
13
|
+
- **Create a client in one line** - `createAttioClient({ apiKey })`
|
|
14
|
+
- **Retry & rate‑limit aware** - exponential backoff + `Retry-After`
|
|
15
|
+
- **Normalized errors** - consistent shape + optional suggestions for select/status mismatches
|
|
16
|
+
- **Record normalization** - handles inconsistent response shapes
|
|
17
|
+
- **Metadata caching** - attributes, select options, statuses
|
|
18
|
+
- **Pagination helpers** - `paginate` + `paginateOffset` + cursor handling
|
|
24
19
|
- **Runtime Validation** - Every request and response validated with Zod v4 schemas
|
|
25
20
|
- **Tree-Shakeable** - Import only what you need
|
|
26
21
|
- **TypeScript First** - Complete type definitions generated from OpenAPI spec
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
|
|
23
|
+
You still have full access to the generated, spec‑accurate endpoints.
|
|
24
|
+
|
|
25
|
+
### See Also
|
|
26
|
+
|
|
27
|
+
- [attio-js](https://github.com/d-stoll/attio-js) - an alternative SDK generated with Speakeasy
|
|
28
|
+
- [attio-tui](https://github.com/hbmartin/attio-tui) - a TUI for using Attio built with the library
|
|
29
|
+
|
|
30
|
+
## Table of Contents
|
|
31
|
+
|
|
32
|
+
- [Installing](#installing)
|
|
33
|
+
- [Getting Your API Key](#getting-your-api-key)
|
|
34
|
+
- [Usage](#usage)
|
|
35
|
+
- [Quick Start](#quick-start)
|
|
36
|
+
- [Recommended Pattern](#recommended-pattern)
|
|
37
|
+
- [Attio SDK](#attio-sdk)
|
|
38
|
+
- [Attio Convenience Layer](#attio-convenience-layer)
|
|
39
|
+
- [Value Helpers](#value-helpers)
|
|
40
|
+
- [Record Value Accessors](#record-value-accessors)
|
|
41
|
+
- [Schema Helpers](#schema-helpers)
|
|
42
|
+
- [Client Configuration](#client-configuration)
|
|
43
|
+
- [Error Handling](#error-handling)
|
|
44
|
+
- [Pagination Helpers](#pagination-helpers)
|
|
45
|
+
- [Caching](#caching)
|
|
46
|
+
- [Debug Hooks](#debug-hooks)
|
|
47
|
+
- [Metadata Helpers](#metadata-helpers)
|
|
48
|
+
- [Working with Records](#working-with-records)
|
|
49
|
+
- [Using Generated Endpoints Directly](#using-generated-endpoints-directly)
|
|
50
|
+
- [Managing Lists](#managing-lists)
|
|
51
|
+
- [Notes and Tasks](#notes-and-tasks)
|
|
52
|
+
- [Webhooks](#webhooks)
|
|
53
|
+
- [Development](#development)
|
|
29
54
|
|
|
30
55
|
## Installing
|
|
31
56
|
|
|
@@ -45,6 +70,19 @@ bun add attio-ts-sdk zod
|
|
|
45
70
|
|
|
46
71
|
> **Note:** Zod v4 is a peer dependency - install it alongside the SDK.
|
|
47
72
|
|
|
73
|
+
## Getting Your API Key
|
|
74
|
+
|
|
75
|
+
1. Log in to your [Attio](https://attio.com) workspace.
|
|
76
|
+
2. Navigate to **Workspace Settings → Developers** (or visit `https://app.attio.com/settings/developers` directly).
|
|
77
|
+
3. Click **Create a new integration**, give it a name, and select the scopes your application needs.
|
|
78
|
+
4. Copy the generated API token and store it securely (e.g. in an environment variable).
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
export ATTIO_API_KEY="your-api-key-here"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The SDK reads the key from whatever you pass to `createAttioClient({ apiKey })` — it does **not** read environment variables automatically, so you control exactly how the secret is loaded.
|
|
85
|
+
|
|
48
86
|
## Usage
|
|
49
87
|
|
|
50
88
|
This SDK provides two layers:
|
|
@@ -77,10 +115,82 @@ const { data: people } = await postV2ObjectsByObjectRecordsQuery({
|
|
|
77
115
|
});
|
|
78
116
|
```
|
|
79
117
|
|
|
118
|
+
### Recommended Pattern
|
|
119
|
+
|
|
120
|
+
Prefer the Attio convenience layer, throw on errors by default, and unwrap responses with helpers.
|
|
121
|
+
This keeps request code compact and consistent.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import {
|
|
125
|
+
assertOk,
|
|
126
|
+
createAttioClient,
|
|
127
|
+
createAttioSdk,
|
|
128
|
+
getV2Objects,
|
|
129
|
+
value,
|
|
130
|
+
} from 'attio-ts-sdk';
|
|
131
|
+
|
|
132
|
+
const client = createAttioClient({
|
|
133
|
+
apiKey: process.env.ATTIO_API_KEY,
|
|
134
|
+
responseStyle: 'data',
|
|
135
|
+
throwOnError: true,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const sdk = createAttioSdk({ client });
|
|
139
|
+
|
|
140
|
+
const company = await sdk.records.create({
|
|
141
|
+
object: 'companies',
|
|
142
|
+
values: {
|
|
143
|
+
name: value.string('Acme Corp'),
|
|
144
|
+
domains: value.domain('acme.com'),
|
|
145
|
+
annual_revenue: value.currency(50000, 'USD'),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Use assertOk with generated endpoints when you need raw access
|
|
150
|
+
const objects = assertOk(await getV2Objects({ client }));
|
|
151
|
+
console.log(objects);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Attio SDK
|
|
155
|
+
|
|
156
|
+
`createAttioSdk` builds on top of the convenience layer and the generated endpoints to provide a single, namespaced object you can pass around your application. It binds the client once so you don't repeat `{ client }` on every call, and groups operations by resource.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { createAttioSdk } from 'attio-ts-sdk';
|
|
160
|
+
|
|
161
|
+
const sdk = createAttioSdk({ apiKey: process.env.ATTIO_API_KEY });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The returned `sdk` object exposes these namespaces:
|
|
165
|
+
|
|
166
|
+
| Namespace | Methods |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `sdk.objects` | `list`, `get`, `create`, `update` |
|
|
169
|
+
| `sdk.records` | `create`, `update`, `upsert`, `get`, `delete`, `query` |
|
|
170
|
+
| `sdk.lists` | `list`, `get`, `queryEntries`, `addEntry`, `updateEntry`, `removeEntry` |
|
|
171
|
+
| `sdk.metadata` | `listAttributes`, `getAttribute`, `getAttributeOptions`, `getAttributeStatuses`, `schema` |
|
|
172
|
+
|
|
173
|
+
The underlying `AttioClient` is also available as `sdk.client` when you need to drop down to the generated endpoints.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const companies = await sdk.records.query({
|
|
177
|
+
object: 'companies',
|
|
178
|
+
filter: { attribute: 'name', value: 'Acme' },
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const attributes = await sdk.metadata.listAttributes({
|
|
182
|
+
target: 'objects',
|
|
183
|
+
identifier: 'companies',
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Use the generated endpoints when you need full spec access
|
|
187
|
+
const { data } = await getV2Objects({ client: sdk.client });
|
|
188
|
+
```
|
|
189
|
+
|
|
80
190
|
### Attio Convenience Layer
|
|
81
191
|
|
|
82
|
-
The
|
|
83
|
-
record normalization, and opinionated defaults.
|
|
192
|
+
The standalone helper functions wrap the generated endpoints with retries, error normalization,
|
|
193
|
+
record normalization, and opinionated defaults. They are the same functions that `createAttioSdk` uses under the hood — use them directly when you prefer explicit `{ client }` threading.
|
|
84
194
|
|
|
85
195
|
```typescript
|
|
86
196
|
import { createAttioClient, createRecord, listLists, searchRecords } from 'attio-ts-sdk';
|
|
@@ -105,6 +215,71 @@ const matches = await searchRecords({
|
|
|
105
215
|
});
|
|
106
216
|
```
|
|
107
217
|
|
|
218
|
+
### Value Helpers
|
|
219
|
+
|
|
220
|
+
The `value` namespace provides factory functions that build correctly shaped field-value arrays for record creation and updates. Each helper validates its input with Zod before returning, so typos and bad data fail fast at the call site rather than in the API response.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { value } from 'attio-ts-sdk';
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
| Helper | Signature | Description |
|
|
227
|
+
| --- | --- | --- |
|
|
228
|
+
| `value.string` | `(value: string) => ValueInput[]` | Non-empty string field. |
|
|
229
|
+
| `value.number` | `(value: number) => ValueInput[]` | Finite numeric field. |
|
|
230
|
+
| `value.boolean` | `(value: boolean) => ValueInput[]` | Boolean field. |
|
|
231
|
+
| `value.domain` | `(value: string) => ValueInput[]` | Domain field (non-empty string). |
|
|
232
|
+
| `value.email` | `(value: string) => ValueInput[]` | Email field (validated format). |
|
|
233
|
+
| `value.currency` | `(value: number, currencyCode?: string) => ValueInput[]` | Currency field. `currencyCode` is an optional ISO 4217 code (e.g. `"USD"`). |
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const values = {
|
|
237
|
+
name: value.string('Acme Corp'),
|
|
238
|
+
domains: value.domain('acme.com'),
|
|
239
|
+
contact_email: value.email('hello@acme.com'),
|
|
240
|
+
employee_count: value.number(150),
|
|
241
|
+
is_customer: value.boolean(true),
|
|
242
|
+
annual_revenue: value.currency(50000, 'USD'),
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
await sdk.records.create({ object: 'companies', values });
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Record Value Accessors
|
|
249
|
+
|
|
250
|
+
`getValue` and `getFirstValue` extract attribute values from a record object. Pass an optional Zod schema to get typed, validated results.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { getFirstValue, getValue } from 'attio-ts-sdk';
|
|
254
|
+
|
|
255
|
+
// Untyped — returns unknown
|
|
256
|
+
const name = getFirstValue(company, 'name');
|
|
257
|
+
const domains = getValue(company, 'domains');
|
|
258
|
+
|
|
259
|
+
// Typed — returns parsed values or throws on mismatch
|
|
260
|
+
import { z } from 'zod';
|
|
261
|
+
|
|
262
|
+
const nameSchema = z.object({ value: z.string() });
|
|
263
|
+
const typedName = getFirstValue(company, 'name', { schema: nameSchema });
|
|
264
|
+
// ^? { value: string } | undefined
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Schema Helpers
|
|
268
|
+
|
|
269
|
+
Create a schema from cached metadata and use accessors to reduce raw string keys:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { createSchema } from 'attio-ts-sdk';
|
|
273
|
+
|
|
274
|
+
const schema = await createSchema({
|
|
275
|
+
client,
|
|
276
|
+
target: 'objects',
|
|
277
|
+
identifier: 'companies',
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const name = schema.getAccessorOrThrow('name').getFirstValue(company);
|
|
281
|
+
```
|
|
282
|
+
|
|
108
283
|
### Client Configuration
|
|
109
284
|
|
|
110
285
|
```typescript
|
|
@@ -121,7 +296,28 @@ const client = createAttioClient({
|
|
|
121
296
|
|
|
122
297
|
### Error Handling
|
|
123
298
|
|
|
124
|
-
|
|
299
|
+
All errors thrown by the convenience layer and `createAttioSdk` are normalized into a hierarchy rooted at `AttioError`:
|
|
300
|
+
|
|
301
|
+
| Class | Default Code | When |
|
|
302
|
+
| --- | --- | --- |
|
|
303
|
+
| `AttioApiError` | *(from response)* | HTTP error responses (4xx / 5xx). Includes `response`, `requestId`, and optional `retryAfterMs`. |
|
|
304
|
+
| `AttioNetworkError` | *(from cause)* | Connection failures, DNS errors, timeouts. |
|
|
305
|
+
| `AttioRetryError` | `RETRY_ERROR` | All retry attempts exhausted. |
|
|
306
|
+
| `AttioResponseError` | `RESPONSE_ERROR` | Response body failed Zod validation. |
|
|
307
|
+
| `AttioConfigError` | `CONFIG_ERROR` | Invalid client configuration. |
|
|
308
|
+
| `AttioBatchError` | `BATCH_ERROR` | A batch operation partially or fully failed. |
|
|
309
|
+
|
|
310
|
+
Every `AttioError` carries these optional fields:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
error.status // HTTP status code
|
|
314
|
+
error.code // machine-readable error code
|
|
315
|
+
error.requestId // Attio x-request-id header
|
|
316
|
+
error.retryAfterMs // parsed Retry-After (milliseconds)
|
|
317
|
+
error.suggestions // fuzzy-match suggestions for value mismatches (see below)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Catching errors from the convenience layer
|
|
125
321
|
|
|
126
322
|
```typescript
|
|
127
323
|
import { createAttioClient, createRecord, AttioError } from 'attio-ts-sdk';
|
|
@@ -135,25 +331,151 @@ try {
|
|
|
135
331
|
values: { stage: [{ value: 'Prospectt' }] },
|
|
136
332
|
});
|
|
137
333
|
} catch (err) {
|
|
138
|
-
|
|
139
|
-
|
|
334
|
+
if (err instanceof AttioError) {
|
|
335
|
+
console.log(err.status, err.code, err.requestId, err.suggestions);
|
|
336
|
+
} else {
|
|
337
|
+
// Re-throw if it's not an error we specifically handle
|
|
338
|
+
throw err;
|
|
339
|
+
}
|
|
140
340
|
}
|
|
141
341
|
```
|
|
142
342
|
|
|
343
|
+
#### Smart suggestions for value mismatches
|
|
344
|
+
|
|
345
|
+
When an API error indicates a select option or status mismatch, the SDK automatically attaches a `suggestions` object with up to three fuzzy-matched alternatives:
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
error.suggestions
|
|
349
|
+
// {
|
|
350
|
+
// field: 'stage',
|
|
351
|
+
// attempted: 'Prospectt',
|
|
352
|
+
// bestMatch: 'Prospect',
|
|
353
|
+
// matches: ['Prospect', 'Prospecting', 'Closed']
|
|
354
|
+
// }
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Response helpers for generated endpoints
|
|
358
|
+
|
|
359
|
+
When using the generated endpoints directly, use `assertOk` or `toResult` to unwrap responses:
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
import { assertOk, toResult, getV2Objects } from 'attio-ts-sdk';
|
|
363
|
+
|
|
364
|
+
// Throws on error, returns the data payload
|
|
365
|
+
const objects = assertOk(await getV2Objects({ client }));
|
|
366
|
+
|
|
367
|
+
// Returns a discriminated union { ok: true, value } | { ok: false, error }
|
|
368
|
+
const result = toResult(await getV2Objects({ client }));
|
|
369
|
+
if (result.ok) {
|
|
370
|
+
console.log(result.value);
|
|
371
|
+
} else {
|
|
372
|
+
console.error(result.error);
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### throwOnError mode
|
|
377
|
+
|
|
378
|
+
You can also opt into exceptions at the client level:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
const client = createAttioClient({
|
|
382
|
+
apiKey: process.env.ATTIO_API_KEY,
|
|
383
|
+
throwOnError: true,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Generated endpoints now throw instead of returning { error }
|
|
387
|
+
const { data } = await postV2ObjectsByObjectRecords({
|
|
388
|
+
client,
|
|
389
|
+
path: { object: 'companies' },
|
|
390
|
+
body: { data: { values: { name: [{ value: 'Test' }] } } },
|
|
391
|
+
});
|
|
392
|
+
```
|
|
393
|
+
|
|
143
394
|
### Pagination Helpers
|
|
144
395
|
|
|
396
|
+
The SDK provides two pagination strategies. Use the one that matches the endpoint:
|
|
397
|
+
|
|
398
|
+
| Strategy | Helper | Endpoints |
|
|
399
|
+
| --- | --- | --- |
|
|
400
|
+
| **Offset-based** | `paginateOffset` | Record queries (`postV2ObjectsByObjectRecordsQuery`), list entry queries (`postV2ListsByListEntriesQuery`) |
|
|
401
|
+
| **Cursor-based** | `paginate` | Meetings (`getV2Meetings`), notes (`getV2Notes`), tasks (`getV2Tasks`), webhooks, and most `GET` list endpoints |
|
|
402
|
+
|
|
403
|
+
Both helpers automatically extract items and pagination metadata from raw API responses — pass the generated endpoint call directly and the helper does the rest.
|
|
404
|
+
|
|
405
|
+
> **Note:** The convenience functions `queryRecords` / `sdk.records.query` and `queryListEntries` / `sdk.lists.queryEntries` return a single page of unwrapped results. To collect **all** pages, use the pagination helpers with the generated endpoints as shown below.
|
|
406
|
+
|
|
407
|
+
#### Paginating record queries (offset-based)
|
|
408
|
+
|
|
145
409
|
```typescript
|
|
146
|
-
import {
|
|
410
|
+
import {
|
|
411
|
+
createAttioClient,
|
|
412
|
+
paginateOffset,
|
|
413
|
+
postV2ObjectsByObjectRecordsQuery,
|
|
414
|
+
} from 'attio-ts-sdk';
|
|
147
415
|
|
|
148
416
|
const client = createAttioClient({ apiKey: process.env.ATTIO_API_KEY });
|
|
149
417
|
|
|
418
|
+
// Collect all companies matching a filter across every page
|
|
419
|
+
const allCompanies = await paginateOffset(async (offset, limit) => {
|
|
420
|
+
return postV2ObjectsByObjectRecordsQuery({
|
|
421
|
+
client,
|
|
422
|
+
path: { object: 'companies' },
|
|
423
|
+
body: {
|
|
424
|
+
offset,
|
|
425
|
+
limit,
|
|
426
|
+
filter: { attribute: 'name', value: 'Acme' },
|
|
427
|
+
sorts: [{ attribute: 'created_at', direction: 'desc' }],
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### Paginating list entry queries (offset-based)
|
|
150
434
|
|
|
151
|
-
|
|
152
|
-
|
|
435
|
+
```typescript
|
|
436
|
+
import { paginateOffset, postV2ListsByListEntriesQuery } from 'attio-ts-sdk';
|
|
437
|
+
|
|
438
|
+
const allEntries = await paginateOffset(async (offset, limit) => {
|
|
439
|
+
return postV2ListsByListEntriesQuery({
|
|
153
440
|
client,
|
|
154
|
-
|
|
441
|
+
path: { list: 'sales-pipeline' },
|
|
442
|
+
body: {
|
|
443
|
+
offset,
|
|
444
|
+
limit,
|
|
445
|
+
filter: { attribute: 'stage', value: 'negotiation' },
|
|
446
|
+
},
|
|
155
447
|
});
|
|
156
|
-
|
|
448
|
+
});
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
#### Paginating cursor-based endpoints
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
import { paginate, getV2Meetings } from 'attio-ts-sdk';
|
|
455
|
+
|
|
456
|
+
const allMeetings = await paginate(async (cursor) => {
|
|
457
|
+
return getV2Meetings({ client, query: { cursor } });
|
|
458
|
+
});
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### Pagination options
|
|
462
|
+
|
|
463
|
+
Both helpers accept an options object to control limits:
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
// Offset-based options
|
|
467
|
+
const records = await paginateOffset(fetchPage, {
|
|
468
|
+
offset: 0, // starting offset (default: 0)
|
|
469
|
+
limit: 100, // items per page (default: 50)
|
|
470
|
+
maxPages: 5, // stop after N pages
|
|
471
|
+
maxItems: 200, // stop after N total items
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Cursor-based options
|
|
475
|
+
const meetings = await paginate(fetchPage, {
|
|
476
|
+
cursor: null, // starting cursor (default: null)
|
|
477
|
+
maxPages: 10, // stop after N pages
|
|
478
|
+
maxItems: 500, // stop after N total items
|
|
157
479
|
});
|
|
158
480
|
```
|
|
159
481
|
|
|
@@ -185,13 +507,35 @@ const optionsAgain = await getAttributeOptions({
|
|
|
185
507
|
}); // Returns cached result, no API call
|
|
186
508
|
```
|
|
187
509
|
|
|
188
|
-
The metadata caches have the following
|
|
510
|
+
The metadata caches have the following defaults:
|
|
189
511
|
- **Attributes cache**: 200 entries max
|
|
190
512
|
- **Options cache**: 500 entries max
|
|
191
513
|
- **Statuses cache**: 500 entries max
|
|
192
514
|
|
|
193
515
|
When a cache reaches its limit, the oldest entry is evicted.
|
|
194
516
|
|
|
517
|
+
You can customize TTL, max entries, and adapters per client:
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
const client = createAttioClient({
|
|
521
|
+
apiKey: process.env.ATTIO_API_KEY,
|
|
522
|
+
cache: {
|
|
523
|
+
enabled: true,
|
|
524
|
+
metadata: {
|
|
525
|
+
ttlMs: 2 * 60 * 1000,
|
|
526
|
+
maxEntries: { attributes: 300, options: 800, statuses: 800 },
|
|
527
|
+
adapter: {
|
|
528
|
+
create: ({ scope, ttlMs, maxEntries }) =>
|
|
529
|
+
new YourCacheAdapter({ scope, ttlMs, maxEntries }),
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// Clear metadata caches for this client
|
|
536
|
+
client.cache.clear();
|
|
537
|
+
```
|
|
538
|
+
|
|
195
539
|
#### Client Instance Caching
|
|
196
540
|
|
|
197
541
|
You can cache `AttioClient` instances to reuse them across your application. This is useful when you want to avoid creating new client instances for repeated operations.
|
|
@@ -218,6 +562,27 @@ const freshClient = getAttioClient({
|
|
|
218
562
|
});
|
|
219
563
|
```
|
|
220
564
|
|
|
565
|
+
### Debug Hooks
|
|
566
|
+
|
|
567
|
+
You can tap into request/response/error lifecycles for logging and tracing.
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
const client = createAttioClient({
|
|
571
|
+
apiKey: process.env.ATTIO_API_KEY,
|
|
572
|
+
hooks: {
|
|
573
|
+
onRequest: ({ request }) => console.log("request", request.method, request.url),
|
|
574
|
+
onResponse: ({ response }) => console.log("response", response.status),
|
|
575
|
+
onError: ({ error }) => console.error("error", error.message),
|
|
576
|
+
},
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
// Or wire a logger (debug/info/warn/error)
|
|
580
|
+
const clientWithLogger = createAttioClient({
|
|
581
|
+
apiKey: process.env.ATTIO_API_KEY,
|
|
582
|
+
logger: console,
|
|
583
|
+
});
|
|
584
|
+
```
|
|
585
|
+
|
|
221
586
|
Note: `createAttioClient` always creates a new client instance. Use `getAttioClient` when you want caching behavior.
|
|
222
587
|
|
|
223
588
|
### Metadata Helpers
|
|
@@ -397,35 +762,10 @@ const { data: webhook } = await postV2Webhooks({
|
|
|
397
762
|
const { data: webhooks } = await getV2Webhooks({ client });
|
|
398
763
|
```
|
|
399
764
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
```typescript
|
|
403
|
-
import { postV2ObjectsByObjectRecords } from 'attio-ts-sdk';
|
|
765
|
+
## See Also
|
|
404
766
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
path: { object: 'companies' },
|
|
408
|
-
body: { data: { values: { name: [{ value: 'Test' }] } } },
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
if (result.error) {
|
|
412
|
-
console.error('API Error:', result.error);
|
|
413
|
-
} else {
|
|
414
|
-
console.log('Created:', result.data);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Or use throwOnError for exceptions
|
|
418
|
-
try {
|
|
419
|
-
const { data } = await postV2ObjectsByObjectRecords({
|
|
420
|
-
client,
|
|
421
|
-
path: { object: 'companies' },
|
|
422
|
-
body: { data: { values: { name: [{ value: 'Test' }] } } },
|
|
423
|
-
throwOnError: true,
|
|
424
|
-
});
|
|
425
|
-
} catch (error) {
|
|
426
|
-
console.error('Request failed:', error);
|
|
427
|
-
}
|
|
428
|
-
```
|
|
767
|
+
- [attio-js](https://github.com/d-stoll/attio-js) - an alternative SDK generated with Speakeasy
|
|
768
|
+
- [attio-tui](https://github.com/hbmartin/attio-tui) - a TUI for using Attio built with this library
|
|
429
769
|
|
|
430
770
|
## Development
|
|
431
771
|
|