@unifetch/fortnox 2.1.1 → 2.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/CHANGELOG.md +12 -0
- package/README.md +231 -183
- package/dist/create-fortnox-mini-COurqL1e.d.mts +24524 -0
- package/dist/create-fortnox-mini-COurqL1e.d.mts.map +1 -0
- package/dist/create-fortnox-mini-DfNjIlYm.d.cts +24524 -0
- package/dist/create-fortnox-mini-DfNjIlYm.d.cts.map +1 -0
- package/dist/{index-BWHJmubR.d.cts → index-IeYuLkvO.d.mts} +15 -4
- package/dist/index-IeYuLkvO.d.mts.map +1 -0
- package/dist/{index-CqOhNC_h.d.mts → index-hOzXwnXm.d.cts} +15 -4
- package/dist/index-hOzXwnXm.d.cts.map +1 -0
- package/dist/index.cjs +1660 -2
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1676 -2
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +1676 -2
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1660 -2
- package/dist/index.mjs.map +1 -0
- package/dist/mini.cjs +27 -0
- package/dist/mini.cjs.map +1 -0
- package/dist/mini.d.cts +16 -0
- package/dist/mini.d.cts.map +1 -0
- package/dist/mini.d.mts +16 -0
- package/dist/mini.d.mts.map +1 -0
- package/dist/mini.mjs +26 -0
- package/dist/mini.mjs.map +1 -0
- package/dist/request-DyylPAyE.mjs +66 -0
- package/dist/request-DyylPAyE.mjs.map +1 -0
- package/dist/request-QlzK3EWz.cjs +78 -0
- package/dist/request-QlzK3EWz.cjs.map +1 -0
- package/dist/types/custom/index.d.cts +1 -1
- package/dist/types/custom/index.d.mts +1 -1
- package/package.json +4 -9
- package/dist/create-fortnox-BB_0mFBL.mjs +0 -1717
- package/dist/create-fortnox-BB_0mFBL.mjs.map +0 -1
- package/dist/create-fortnox-BQgaBk5m.d.cts +0 -1697
- package/dist/create-fortnox-BQgaBk5m.d.cts.map +0 -1
- package/dist/create-fortnox-DGjVOKfm.cjs +0 -1723
- package/dist/create-fortnox-DGjVOKfm.cjs.map +0 -1
- package/dist/create-fortnox-DiGzUeVa.d.mts +0 -1697
- package/dist/create-fortnox-DiGzUeVa.d.mts.map +0 -1
- package/dist/index-BWHJmubR.d.cts.map +0 -1
- package/dist/index-CqOhNC_h.d.mts.map +0 -1
- package/dist/official-BFBd-NeQ.d.cts +0 -12259
- package/dist/official-BFBd-NeQ.d.cts.map +0 -1
- package/dist/official-DeZGQsNS.d.mts +0 -12259
- package/dist/official-DeZGQsNS.d.mts.map +0 -1
- package/dist/official.cjs +0 -9
- package/dist/official.cjs.map +0 -1
- package/dist/official.d.cts +0 -2
- package/dist/official.d.mts +0 -2
- package/dist/official.mjs +0 -8
- package/dist/official.mjs.map +0 -1
- package/dist/patched.cjs +0 -9
- package/dist/patched.cjs.map +0 -1
- package/dist/patched.d.cts +0 -12256
- package/dist/patched.d.cts.map +0 -1
- package/dist/patched.d.mts +0 -12256
- package/dist/patched.d.mts.map +0 -1
- package/dist/patched.mjs +0 -8
- package/dist/patched.mjs.map +0 -1
- package/dist/utility-types-CXs8tUw_.d.mts +0 -15
- package/dist/utility-types-CXs8tUw_.d.mts.map +0 -1
- package/dist/utility-types-DLzshE5r.d.cts +0 -15
- package/dist/utility-types-DLzshE5r.d.cts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @unifetch/fortnox
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Export the full client and mini client from sperate paths for better tree-shaking. Create official/patched client by providing a genering to the init function.
|
|
8
|
+
|
|
9
|
+
## 2.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Add new initializer - createFortnoxMini() which only exposes the .path() method. It still has full type safety but results in very small bundle size compared to initFortnox()
|
|
14
|
+
|
|
3
15
|
## 2.1.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,183 +1,231 @@
|
|
|
1
|
-
# @unifetch/fortnox
|
|
2
|
-
|
|
3
|
-
TypeScript SDK for the [Fortnox API](https://api.fortnox.se/apidocs), fully typed from the official OpenAPI specification — with corrections applied where the spec has incorrect or overly permissive types.
|
|
4
|
-
|
|
5
|
-
Zero dependencies. Fully compatible with edge runtimes such as [Cloudflare Workers](https://workers.cloudflare.com/) and Vercel Edge Functions.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @unifetch/fortnox
|
|
11
|
-
# or
|
|
12
|
-
pnpm add @unifetch/fortnox
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
1
|
+
# @unifetch/fortnox
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the [Fortnox API](https://api.fortnox.se/apidocs), fully typed from the official OpenAPI specification — with corrections applied where the spec has incorrect or overly permissive types.
|
|
4
|
+
|
|
5
|
+
Zero dependencies. Fully compatible with edge runtimes such as [Cloudflare Workers](https://workers.cloudflare.com/) and Vercel Edge Functions.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @unifetch/fortnox
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @unifetch/fortnox
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Clients
|
|
18
|
+
|
|
19
|
+
There are two clients to choose from.
|
|
20
|
+
|
|
21
|
+
### `initFortnox` — full client
|
|
22
|
+
|
|
23
|
+
Includes both the resource-based API (`fortnox.invoices.getList()`) and the path-based API (`fortnox.path()`). This is the right choice for most server-side applications where bundle size is not a concern.
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { initFortnox } from "@unifetch/fortnox";
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### `initFortnoxMini` — minimal client
|
|
30
|
+
|
|
31
|
+
Includes **only** the path-based API (`fortnox.path()`). The entire resource-based layer — including the map of all routes and operation IDs — is absent from this client, which means a bundler can **tree-shake it away entirely**. Use this when bundle size is a hard constraint, such as in [Cloudflare Workers](https://workers.cloudflare.com/) or Vercel Edge Functions.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { initFortnoxMini } from "@unifetch/fortnox/mini";
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Route variant
|
|
40
|
+
|
|
41
|
+
Both clients accept an optional `"official" | "patched"` generic that controls which type definitions are used. It defaults to `"patched"`.
|
|
42
|
+
|
|
43
|
+
| Variant | Description |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `"patched"` *(default)* | Corrected types — fixes inaccuracies in Fortnox's official spec (e.g. response wrapper properties incorrectly marked as optional). Recommended for most projects. |
|
|
46
|
+
| `"official"` | Raw, unmodified types exactly as they appear in Fortnox's official OpenAPI specification. |
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// "patched" is the default — no generic needed
|
|
50
|
+
const fortnox = initFortnox({ accessToken: "..." });
|
|
51
|
+
|
|
52
|
+
// Explicitly patched
|
|
53
|
+
const fortnox = initFortnox<"patched">({ accessToken: "..." });
|
|
54
|
+
|
|
55
|
+
// Official, unmodified Fortnox types
|
|
56
|
+
const fortnox = initFortnox<"official">({ accessToken: "..." });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The same generic is available on `initFortnoxMini`:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { initFortnoxMini } from "@unifetch/fortnox/mini";
|
|
63
|
+
|
|
64
|
+
const fortnox = initFortnoxMini<"official">({ accessToken: "..." });
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Initialization
|
|
70
|
+
|
|
71
|
+
Both clients support two authentication options.
|
|
72
|
+
|
|
73
|
+
### Option 1 — Access token
|
|
74
|
+
|
|
75
|
+
Use this if you manage your own OAuth flow and already have a Fortnox access token.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { initFortnox } from "@unifetch/fortnox";
|
|
79
|
+
|
|
80
|
+
const fortnox = initFortnox({ accessToken: "your-access-token" });
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Option 2 — Proxy via unifetch.dev
|
|
84
|
+
|
|
85
|
+
[unifetch.dev](https://unifetch.dev) acts as a proxy layer that internally handles OAuth and token rotation, removing the complecity of managing credentials yourself.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { initFortnox } from "@unifetch/fortnox";
|
|
89
|
+
|
|
90
|
+
const fortnox = initFortnox({
|
|
91
|
+
proxy: {
|
|
92
|
+
baseUrl: "https://proxy.unifetch.dev/fortnox",
|
|
93
|
+
apiKey: "your-api-key", // Generate on the unifetch.dev dashboard
|
|
94
|
+
tenantId: "your-tenant-id", // Your company's unique Fortnox ID, visible on the unifetch.dev dashboard
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
Every response is a discriminated union of `{ error: null; data: T }` or `{ error: ErrorResponse; data: null }`. Once you handle (or narrow) the error branch, TypeScript automatically infers that `data` is non-null.
|
|
104
|
+
|
|
105
|
+
`initFortnox` supports both APIs below. `initFortnoxMini` supports only the path-based API.
|
|
106
|
+
|
|
107
|
+
### Resource-based API (recommended)
|
|
108
|
+
|
|
109
|
+
Access resources by name and call operations by their ID. Both the resource name and the operation ID are autocompleted by TypeScript.
|
|
110
|
+
|
|
111
|
+
> **Note:** Operation names (e.g. `getList`, `create`, `bookkeep`) are **manually curated** and are not derived from the official Fortnox OpenAPI spec. The official spec uses operation IDs that are inconsistent and ambiguous across endpoints. The names used here follow a consistent, human-readable convention defined in [`overrides/operation-ids.json`](overrides/operation-ids.json).
|
|
112
|
+
|
|
113
|
+
#### Fetching a list
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const { data, error } = await fortnox.invoices.getList();
|
|
117
|
+
|
|
118
|
+
if (error) {
|
|
119
|
+
console.error(error.ErrorInformation.message);
|
|
120
|
+
} else {
|
|
121
|
+
// data is non-null here — TypeScript knows this after the error check
|
|
122
|
+
console.log(data.Invoices);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### With query parameters
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const { data, error } = await fortnox.invoices.getList({
|
|
130
|
+
query: { fromdate: "2024-01-01", todate: "2024-12-31" },
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (error) throw error;
|
|
134
|
+
|
|
135
|
+
for (const invoice of data.Invoices) {
|
|
136
|
+
console.log(invoice.DocumentNumber, invoice.Total);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Fetching a single resource
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const { data, error } = await fortnox.invoices.get({
|
|
144
|
+
params: { DocumentNumber: "100" },
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (error) throw error;
|
|
148
|
+
|
|
149
|
+
console.log(data.Invoice.CustomerName);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Creating a resource
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
const { data, error } = await fortnox.invoices.create({
|
|
156
|
+
body: {
|
|
157
|
+
Invoice: {
|
|
158
|
+
CustomerNumber: "1",
|
|
159
|
+
InvoiceRows: [
|
|
160
|
+
{ ArticleNumber: "A1", DeliveredQuantity: 2 },
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
if (error) throw error;
|
|
167
|
+
|
|
168
|
+
console.log(data.Invoice.DocumentNumber);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Calling an action on a resource
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const { data, error } = await fortnox.invoices.bookkeep({
|
|
175
|
+
params: { DocumentNumber: "100" },
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Path-based API
|
|
180
|
+
|
|
181
|
+
Call any endpoint directly by its raw path. The path, parameters, and response are fully typed.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const { data, error } = await fortnox.path("/3/invoices").get();
|
|
185
|
+
|
|
186
|
+
if (error) throw error;
|
|
187
|
+
|
|
188
|
+
console.log(data.Invoices);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const { data, error } = await fortnox.path("/3/invoices/{DocumentNumber}").get({
|
|
193
|
+
params: { DocumentNumber: "100" },
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
This is the only API available on `initFortnoxMini`:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
import { initFortnoxMini } from "@unifetch/fortnox/mini";
|
|
201
|
+
|
|
202
|
+
const fortnox = initFortnoxMini({ accessToken: "your-access-token" });
|
|
203
|
+
|
|
204
|
+
const { data, error } = await fortnox.path("/3/invoices").get();
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Error handling
|
|
210
|
+
|
|
211
|
+
The error object has the following shape:
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
type ErrorResponse = {
|
|
215
|
+
ErrorSource: "fortnox" | "unknown";
|
|
216
|
+
ErrorInformation: {
|
|
217
|
+
error: number;
|
|
218
|
+
message: string;
|
|
219
|
+
code: number;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- `ErrorSource: "fortnox"` — the Fortnox API returned a non-2xx response.
|
|
225
|
+
- `ErrorSource: "unknown"` — a network or unexpected error occurred.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
ISC
|