proiectro 0.1.1 → 0.3.0
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 +200 -113
- package/dist/index.cjs +2437 -1188
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29706 -19967
- package/dist/index.d.ts +29706 -19967
- package/dist/index.js +2220 -1064
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -10,91 +10,112 @@ Full type safety for every endpoint, request, and response.
|
|
|
10
10
|
npm install proiectro
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
Requires Node.js >= 20 (uses native `fetch`). Works with TypeScript >= 5.0 or plain JavaScript.
|
|
14
|
+
|
|
13
15
|
## Quick Start
|
|
14
16
|
|
|
15
17
|
```typescript
|
|
16
|
-
import { client, tenantOrgs
|
|
18
|
+
import { client, tenantOrgs } from 'proiectro';
|
|
17
19
|
|
|
18
20
|
// Authenticate (baseUrl defaults to https://proiect.ro)
|
|
19
21
|
client.setConfig({
|
|
20
22
|
auth: () => 'your_api_key_here',
|
|
21
23
|
});
|
|
22
24
|
|
|
23
|
-
//
|
|
25
|
+
// Every workspace-scoped call takes the workspace path
|
|
24
26
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
25
27
|
|
|
26
|
-
// List customers
|
|
27
28
|
const { data, error } = await tenantOrgs(workspace);
|
|
28
29
|
|
|
29
30
|
if (data) {
|
|
30
|
-
console.log('Customers:', data);
|
|
31
|
+
console.log('Customers:', data.orgs);
|
|
31
32
|
}
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
## Authentication
|
|
35
36
|
|
|
36
|
-
Create an API key in your workspace under **Settings > API Keys**. The SDK sends it as a Bearer token
|
|
37
|
+
Create an API key in your workspace under **Settings > API Keys**. The SDK sends it as a Bearer token on every request.
|
|
37
38
|
|
|
38
39
|
```typescript
|
|
39
40
|
import { client } from 'proiectro';
|
|
40
41
|
|
|
41
42
|
client.setConfig({
|
|
42
|
-
auth: () =>
|
|
43
|
+
auth: () => process.env.PROIECTRO_API_KEY,
|
|
43
44
|
});
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
The `auth` callback
|
|
47
|
+
The `auth` callback runs on each request, so the key can come from an environment variable, a secret manager, or any async source.
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
```
|
|
49
|
+
An API key carries the scope it was created with (read-only or full CRUD, restricted to a team if you chose one). A call outside that scope returns `403`.
|
|
50
|
+
|
|
51
|
+
## Calling conventions
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
Every operation is a function named after its `operationId` in camelCase, taking one options object:
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
| Key | Contents |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `path` | Path parameters. Nearly always includes `tenant_path` (your workspace); entity IDs go here too. |
|
|
58
|
+
| `body` | The JSON request body for `POST` / `PATCH` / `PUT`. |
|
|
59
|
+
| `query` | Query-string filters on list endpoints (`search`, `owner`, `status`, date ranges, tags/labels …). |
|
|
60
|
+
|
|
61
|
+
Every call returns `{ data, error, request, response }`. `data` is typed to the operation's `200` schema; `error` is typed to its documented error responses.
|
|
57
62
|
|
|
58
63
|
```typescript
|
|
59
64
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
60
65
|
|
|
66
|
+
// path only
|
|
61
67
|
await tenantOrgs(workspace);
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
|
|
69
|
+
// path + body
|
|
70
|
+
await addTag({ ...workspace, body: { name: 'VIP', color: '#ff0000' } });
|
|
71
|
+
|
|
72
|
+
// path with an entity id + body
|
|
73
|
+
await markPaymentPaid({
|
|
74
|
+
path: { tenant_path: 'my-workspace', payment_id: 'payment-uuid' },
|
|
75
|
+
body: { paid_date: '2026-03-15' },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// path + query
|
|
79
|
+
await listProjects({ ...workspace, query: { search: 'rollout', owner: 'member-uuid' } });
|
|
64
80
|
```
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
IDs are the `external_id` strings the API returns; dates are ISO 8601 strings (`YYYY-MM-DD` for dates, full timestamps for datetimes).
|
|
67
83
|
|
|
68
84
|
## Usage Examples
|
|
69
85
|
|
|
70
86
|
### Customers
|
|
71
87
|
|
|
72
88
|
```typescript
|
|
73
|
-
import {
|
|
74
|
-
tenantOrgs,
|
|
75
|
-
addSubtenant,
|
|
76
|
-
editSubtenant,
|
|
77
|
-
deleteSubtenant,
|
|
78
|
-
} from 'proiectro';
|
|
89
|
+
import { tenantOrgs, addSubtenant, editSubtenant, deleteSubtenant } from 'proiectro';
|
|
79
90
|
|
|
80
91
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
81
92
|
|
|
82
93
|
// List all customers
|
|
83
|
-
const { data
|
|
94
|
+
const { data } = await tenantOrgs(workspace);
|
|
84
95
|
|
|
85
|
-
// Create a customer
|
|
86
|
-
|
|
96
|
+
// Create a customer under your workspace
|
|
97
|
+
await addSubtenant({
|
|
87
98
|
...workspace,
|
|
88
99
|
body: {
|
|
100
|
+
parent_id: 'workspace-org-uuid',
|
|
89
101
|
name: 'Acme Corp',
|
|
90
|
-
|
|
102
|
+
timezone: 'Europe/Bucharest',
|
|
103
|
+
default_currency: 'EUR',
|
|
104
|
+
country: 'RO',
|
|
105
|
+
manager: 'member-uuid',
|
|
91
106
|
},
|
|
92
107
|
});
|
|
93
108
|
|
|
94
|
-
// Update a customer
|
|
109
|
+
// Update a customer (send every field — this is a full update, not a patch)
|
|
95
110
|
await editSubtenant({
|
|
96
111
|
path: { tenant_path: 'my-workspace', subtenant_id: 'customer-uuid' },
|
|
97
|
-
body: {
|
|
112
|
+
body: {
|
|
113
|
+
name: 'Acme Corporation',
|
|
114
|
+
timezone: 'Europe/Bucharest',
|
|
115
|
+
default_currency: 'EUR',
|
|
116
|
+
country: 'RO',
|
|
117
|
+
manager: 'member-uuid',
|
|
118
|
+
},
|
|
98
119
|
});
|
|
99
120
|
|
|
100
121
|
// Delete a customer
|
|
@@ -103,15 +124,45 @@ await deleteSubtenant({
|
|
|
103
124
|
});
|
|
104
125
|
```
|
|
105
126
|
|
|
127
|
+
### Leads
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { addLead, tenantAllLeads, updateLeadStatus, markLeadConverted } from 'proiectro';
|
|
131
|
+
|
|
132
|
+
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
133
|
+
|
|
134
|
+
// Capture an inbound lead
|
|
135
|
+
const { data: lead } = await addLead({
|
|
136
|
+
...workspace,
|
|
137
|
+
body: {
|
|
138
|
+
name: 'Jane Doe',
|
|
139
|
+
company_name: 'Acme Corp',
|
|
140
|
+
email: 'jane@acme.example',
|
|
141
|
+
source: 'web_form',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// List leads, filtered
|
|
146
|
+
await tenantAllLeads({ ...workspace, query: { status: 'new', has_email: true } });
|
|
147
|
+
|
|
148
|
+
// Move a lead through the pipeline. `updated_at` is the value you last read —
|
|
149
|
+
// the API rejects the write if someone else changed the lead in between.
|
|
150
|
+
await updateLeadStatus({
|
|
151
|
+
path: { tenant_path: 'my-workspace', lead_id: 'lead-uuid' },
|
|
152
|
+
body: { status: 'qualified', updated_at: '2026-03-15T10:00:00Z' },
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Convert it into a customer
|
|
156
|
+
await markLeadConverted({
|
|
157
|
+
path: { tenant_path: 'my-workspace', lead_id: 'lead-uuid' },
|
|
158
|
+
body: { new_org_name: 'Acme Corp', updated_at: '2026-03-15T10:05:00Z' },
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
106
162
|
### Proposals
|
|
107
163
|
|
|
108
164
|
```typescript
|
|
109
|
-
import {
|
|
110
|
-
addProposal,
|
|
111
|
-
editProposal,
|
|
112
|
-
changeProposalStage,
|
|
113
|
-
orgProposals,
|
|
114
|
-
} from 'proiectro';
|
|
165
|
+
import { addProposal, orgProposals, changeProposalStage } from 'proiectro';
|
|
115
166
|
|
|
116
167
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
117
168
|
|
|
@@ -125,37 +176,34 @@ await addProposal({
|
|
|
125
176
|
...workspace,
|
|
126
177
|
body: {
|
|
127
178
|
name: 'Q1 Consulting',
|
|
128
|
-
|
|
129
|
-
|
|
179
|
+
description: 'Discovery and rollout support',
|
|
180
|
+
customer: 'customer-uuid',
|
|
181
|
+
owner: 'member-uuid',
|
|
182
|
+
manager: 'member-uuid',
|
|
183
|
+
sales_stage: 'funnel-stage-uuid',
|
|
184
|
+
proposal_currency: 'EUR',
|
|
185
|
+
wbsconfiguration: 'wbs-configuration-uuid',
|
|
130
186
|
},
|
|
131
187
|
});
|
|
132
188
|
|
|
133
|
-
// Move a proposal to
|
|
189
|
+
// Move a proposal to another funnel stage
|
|
134
190
|
await changeProposalStage({
|
|
135
|
-
|
|
136
|
-
body: {
|
|
137
|
-
proposal_id: 'proposal-uuid',
|
|
138
|
-
stage_id: 'next-stage-uuid',
|
|
139
|
-
},
|
|
191
|
+
path: { tenant_path: 'my-workspace', proposal_id: 'proposal-uuid', stage_id: 'next-stage-uuid' },
|
|
192
|
+
body: {},
|
|
140
193
|
});
|
|
141
194
|
```
|
|
142
195
|
|
|
143
196
|
### Projects & Work Items
|
|
144
197
|
|
|
145
198
|
```typescript
|
|
146
|
-
import {
|
|
147
|
-
listProjects,
|
|
148
|
-
projectWorkItems,
|
|
149
|
-
addWorkItem,
|
|
150
|
-
updateWorkItemStatus,
|
|
151
|
-
} from 'proiectro';
|
|
199
|
+
import { listProjects, projectWorkItems, addWorkItem, updateWorkItemStatus, addWorkItemComment } from 'proiectro';
|
|
152
200
|
|
|
153
201
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
154
202
|
|
|
155
|
-
// List all
|
|
156
|
-
const { data: projects } = await listProjects(workspace);
|
|
203
|
+
// List projects (all filters are optional)
|
|
204
|
+
const { data: projects } = await listProjects({ ...workspace, query: { lifecycle_status: ['active'] } });
|
|
157
205
|
|
|
158
|
-
//
|
|
206
|
+
// Work items of a project
|
|
159
207
|
const { data: workItems } = await projectWorkItems({
|
|
160
208
|
path: { tenant_path: 'my-workspace', project_id: 'project-uuid' },
|
|
161
209
|
});
|
|
@@ -166,97 +214,106 @@ await addWorkItem({
|
|
|
166
214
|
body: {
|
|
167
215
|
name: 'Design mockups',
|
|
168
216
|
project_id: 'project-uuid',
|
|
169
|
-
work_item_type_id: 'type-uuid',
|
|
217
|
+
work_item_type_id: 'work-item-type-uuid',
|
|
218
|
+
planned_start_date: '2026-03-01',
|
|
219
|
+
planned_finish_date: '2026-03-10',
|
|
170
220
|
},
|
|
171
221
|
});
|
|
172
222
|
|
|
173
|
-
//
|
|
223
|
+
// Report progress, or finish it
|
|
174
224
|
await updateWorkItemStatus({
|
|
225
|
+
path: { tenant_path: 'my-workspace', work_item_id: 'work-item-uuid' },
|
|
226
|
+
body: { percent_complete: 60 },
|
|
227
|
+
});
|
|
228
|
+
await updateWorkItemStatus({
|
|
229
|
+
path: { tenant_path: 'my-workspace', work_item_id: 'work-item-uuid' },
|
|
230
|
+
body: { finished_at: '2026-03-10T16:00:00Z' },
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Comment on it
|
|
234
|
+
await addWorkItemComment({
|
|
175
235
|
...workspace,
|
|
176
|
-
body: {
|
|
177
|
-
work_item_id: 'work-item-uuid',
|
|
178
|
-
status: 'in_progress',
|
|
179
|
-
},
|
|
236
|
+
body: { work_item_id: 'work-item-uuid', content: 'Mockups approved by the customer.' },
|
|
180
237
|
});
|
|
181
238
|
```
|
|
182
239
|
|
|
183
240
|
### Payments
|
|
184
241
|
|
|
185
242
|
```typescript
|
|
186
|
-
import {
|
|
187
|
-
addPayment,
|
|
188
|
-
markPaymentPaid,
|
|
189
|
-
} from 'proiectro';
|
|
243
|
+
import { addPayment, markPaymentPaid } from 'proiectro';
|
|
190
244
|
|
|
191
245
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
192
246
|
|
|
193
|
-
//
|
|
247
|
+
// Add a payment to a proposal's payment schedule
|
|
194
248
|
await addPayment({
|
|
195
249
|
...workspace,
|
|
196
250
|
body: {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
currency: 'EUR',
|
|
251
|
+
payment_schedule_block_id: 'schedule-block-uuid',
|
|
252
|
+
name: 'Milestone 1',
|
|
200
253
|
due_date: '2026-03-15',
|
|
254
|
+
amount: '5000.00',
|
|
201
255
|
},
|
|
202
256
|
});
|
|
203
257
|
|
|
204
|
-
// Mark
|
|
258
|
+
// Mark it paid
|
|
205
259
|
await markPaymentPaid({
|
|
206
|
-
|
|
207
|
-
body: {
|
|
260
|
+
path: { tenant_path: 'my-workspace', payment_id: 'payment-uuid' },
|
|
261
|
+
body: { paid_date: '2026-03-14' },
|
|
208
262
|
});
|
|
209
263
|
```
|
|
210
264
|
|
|
265
|
+
### Documents
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { tenantDocumentTemplatesList, generateProposalDocument, tenantDocumentsList } from 'proiectro';
|
|
269
|
+
|
|
270
|
+
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
271
|
+
|
|
272
|
+
// Templates available in the workspace
|
|
273
|
+
const { data: templates } = await tenantDocumentTemplatesList(workspace);
|
|
274
|
+
|
|
275
|
+
// Generate a numbered document for a proposal
|
|
276
|
+
await generateProposalDocument({
|
|
277
|
+
path: { tenant_path: 'my-workspace', proposal_id: 'proposal-uuid' },
|
|
278
|
+
body: { template_id: 'template-uuid' },
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Documents, filtered
|
|
282
|
+
await tenantDocumentsList({ ...workspace, query: { org_id: 'customer-uuid' } });
|
|
283
|
+
```
|
|
284
|
+
|
|
211
285
|
### Tags
|
|
212
286
|
|
|
213
287
|
```typescript
|
|
214
|
-
import {
|
|
215
|
-
tenantTags,
|
|
216
|
-
addTag,
|
|
217
|
-
tagOrg,
|
|
218
|
-
untagOrg,
|
|
219
|
-
} from 'proiectro';
|
|
288
|
+
import { tenantTags, addTag, tagOrg, untagOrg } from 'proiectro';
|
|
220
289
|
|
|
221
290
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
222
291
|
|
|
223
|
-
// List all tags
|
|
224
292
|
const { data: tags } = await tenantTags(workspace);
|
|
225
293
|
|
|
226
|
-
|
|
227
|
-
await addTag({
|
|
228
|
-
...workspace,
|
|
229
|
-
body: { name: 'VIP', color: '#ff0000' },
|
|
230
|
-
});
|
|
294
|
+
await addTag({ ...workspace, body: { name: 'VIP', color: '#ff0000' } });
|
|
231
295
|
|
|
232
|
-
//
|
|
233
|
-
await tagOrg({
|
|
234
|
-
|
|
235
|
-
body: { org_id: 'customer-uuid', tag_id: 'tag-uuid' },
|
|
236
|
-
});
|
|
296
|
+
// Tagging is addressed by path: (entity, tag)
|
|
297
|
+
await tagOrg({ path: { tenant_path: 'my-workspace', org_id: 'customer-uuid', tag_id: 'tag-uuid' } });
|
|
298
|
+
await untagOrg({ path: { tenant_path: 'my-workspace', org_id: 'customer-uuid', tag_id: 'tag-uuid' } });
|
|
237
299
|
```
|
|
238
300
|
|
|
239
301
|
### Support Requests
|
|
240
302
|
|
|
241
303
|
```typescript
|
|
242
|
-
import {
|
|
243
|
-
addInternalSupportRequest,
|
|
244
|
-
mySupportRequests,
|
|
245
|
-
} from 'proiectro';
|
|
304
|
+
import { addInternalSupportRequest, mySupportRequests } from 'proiectro';
|
|
246
305
|
|
|
247
306
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
248
307
|
|
|
249
|
-
// List my support requests
|
|
250
308
|
const { data: tickets } = await mySupportRequests(workspace);
|
|
251
309
|
|
|
252
|
-
// Create a support request
|
|
253
310
|
await addInternalSupportRequest({
|
|
254
311
|
...workspace,
|
|
255
312
|
body: {
|
|
256
313
|
title: 'Server configuration issue',
|
|
257
314
|
description: 'Need help with DNS setup',
|
|
258
|
-
|
|
259
|
-
|
|
315
|
+
request_type: 'request-type-uuid',
|
|
316
|
+
request_severity: 'severity-uuid',
|
|
260
317
|
},
|
|
261
318
|
});
|
|
262
319
|
```
|
|
@@ -264,26 +321,51 @@ await addInternalSupportRequest({
|
|
|
264
321
|
### Team
|
|
265
322
|
|
|
266
323
|
```typescript
|
|
267
|
-
import {
|
|
268
|
-
tenantTeam,
|
|
269
|
-
inviteToTeam,
|
|
270
|
-
} from 'proiectro';
|
|
324
|
+
import { tenantTeam, inviteToTeam } from 'proiectro';
|
|
271
325
|
|
|
272
326
|
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
273
327
|
|
|
274
|
-
// List team members
|
|
275
328
|
const { data: team } = await tenantTeam(workspace);
|
|
276
329
|
|
|
277
|
-
|
|
278
|
-
|
|
330
|
+
await inviteToTeam({ ...workspace, body: { email: 'colleague@example.com' } });
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Webhooks
|
|
334
|
+
|
|
335
|
+
Subscribe to platform events instead of polling:
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import { addWebhook, tenantWebhooks } from 'proiectro';
|
|
339
|
+
|
|
340
|
+
const workspace = { path: { tenant_path: 'my-workspace' } };
|
|
341
|
+
|
|
342
|
+
await addWebhook({
|
|
279
343
|
...workspace,
|
|
280
|
-
body: {
|
|
344
|
+
body: {
|
|
345
|
+
name: 'CRM sync',
|
|
346
|
+
target_url: 'https://example.com/hooks/proiectro',
|
|
347
|
+
event_types: ['changeProposalStage', 'markPaymentPaid'],
|
|
348
|
+
is_active: true,
|
|
349
|
+
is_secure: true,
|
|
350
|
+
},
|
|
281
351
|
});
|
|
352
|
+
|
|
353
|
+
const { data: hooks } = await tenantWebhooks(workspace);
|
|
282
354
|
```
|
|
283
355
|
|
|
284
|
-
##
|
|
356
|
+
## Namespaces
|
|
357
|
+
|
|
358
|
+
| Area | Namespaces |
|
|
359
|
+
|---|---|
|
|
360
|
+
| Sales | `leads`, `proposals`, `orgs`, `rfp`, `bridge` (partnerships), `partnerportal` |
|
|
361
|
+
| Delivery | `projects`, `work`, `operations`, `comments`, `timers`, `booking`, `capacity`, `resources`, `holidays`, `calendar` |
|
|
362
|
+
| Money | `costs`, `exchange`, `analytics`, `kpis` |
|
|
363
|
+
| Support & assets | `support`, `assets`, `locations`, `custom_forms` |
|
|
364
|
+
| Documents & files | `documents`, `files`, `cdn` |
|
|
365
|
+
| Workspace | `tenant`, `team`, `rbac`, `tags`, `labels`, `notifications`, `feed`, `welcome`, `auth` |
|
|
366
|
+
| Automation | `webhooks`, `automation`, `integrations`, `portal` |
|
|
285
367
|
|
|
286
|
-
|
|
368
|
+
## Error Handling
|
|
287
369
|
|
|
288
370
|
```typescript
|
|
289
371
|
const { data, error, response } = await tenantOrgs({
|
|
@@ -298,6 +380,14 @@ if (error) {
|
|
|
298
380
|
}
|
|
299
381
|
```
|
|
300
382
|
|
|
383
|
+
Validation failures come back as `422` with a field-level detail list; a permission or feature-entitlement problem is `403`; a missing entity is `404`; a conflict with the current state (a stage transition that is not allowed, a delete blocked by dependants) is `409`.
|
|
384
|
+
|
|
385
|
+
To have the SDK throw instead of returning `error`, pass `throwOnError`:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
const { data } = await tenantOrgs({ path: { tenant_path: 'my-workspace' }, throwOnError: true });
|
|
389
|
+
```
|
|
390
|
+
|
|
301
391
|
## Interceptors
|
|
302
392
|
|
|
303
393
|
Add request/response interceptors for logging, retries, or custom headers:
|
|
@@ -305,13 +395,11 @@ Add request/response interceptors for logging, retries, or custom headers:
|
|
|
305
395
|
```typescript
|
|
306
396
|
import { client } from 'proiectro';
|
|
307
397
|
|
|
308
|
-
// Log all requests
|
|
309
398
|
client.interceptors.request.use((request) => {
|
|
310
399
|
console.log(`${request.method} ${request.url}`);
|
|
311
400
|
return request;
|
|
312
401
|
});
|
|
313
402
|
|
|
314
|
-
// Log all responses
|
|
315
403
|
client.interceptors.response.use((response) => {
|
|
316
404
|
console.log(`${response.status} ${response.url}`);
|
|
317
405
|
return response;
|
|
@@ -320,21 +408,20 @@ client.interceptors.response.use((response) => {
|
|
|
320
408
|
|
|
321
409
|
## TypeScript
|
|
322
410
|
|
|
323
|
-
Every request and response is fully typed. Your editor
|
|
411
|
+
Every request and response is fully typed. Your editor autocompletes path parameters, body fields, query filters, and response shapes:
|
|
324
412
|
|
|
325
413
|
```typescript
|
|
326
|
-
import type { OutputTenantInfo, AddSubtenantData } from 'proiectro';
|
|
414
|
+
import type { OutputTenantInfo, AddSubtenantData, AddLeadData } from 'proiectro';
|
|
327
415
|
```
|
|
328
416
|
|
|
329
|
-
## Requirements
|
|
330
|
-
|
|
331
|
-
- Node.js >= 18 (uses native `fetch`)
|
|
332
|
-
- TypeScript >= 5.0 (optional, works with plain JavaScript too)
|
|
333
|
-
|
|
334
417
|
## API Documentation
|
|
335
418
|
|
|
336
419
|
Full API reference is available at [proiect.ro/api/v1/docs](https://proiect.ro/api/v1/docs).
|
|
337
420
|
|
|
421
|
+
## Changelog
|
|
422
|
+
|
|
423
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
424
|
+
|
|
338
425
|
## License
|
|
339
426
|
|
|
340
427
|
MIT
|