deere-sdk 0.1.3 → 0.2.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.
Files changed (147) hide show
  1. package/README.md +474 -116
  2. package/dist/api/aemp.d.ts +19 -0
  3. package/dist/api/aemp.d.ts.map +1 -0
  4. package/dist/api/aemp.js +22 -0
  5. package/dist/api/aemp.js.map +1 -0
  6. package/dist/api/assets.d.ts +7 -7
  7. package/dist/api/assets.d.ts.map +1 -1
  8. package/dist/api/assets.js.map +1 -1
  9. package/dist/api/boundaries.d.ts +8 -7
  10. package/dist/api/boundaries.d.ts.map +1 -1
  11. package/dist/api/boundaries.js.map +1 -1
  12. package/dist/api/clients.d.ts +5 -5
  13. package/dist/api/clients.d.ts.map +1 -1
  14. package/dist/api/clients.js.map +1 -1
  15. package/dist/api/crop-types.d.ts +7 -6
  16. package/dist/api/crop-types.d.ts.map +1 -1
  17. package/dist/api/crop-types.js.map +1 -1
  18. package/dist/api/equipment-measurement.d.ts +20 -0
  19. package/dist/api/equipment-measurement.d.ts.map +1 -0
  20. package/dist/api/equipment-measurement.js +22 -0
  21. package/dist/api/equipment-measurement.js.map +1 -0
  22. package/dist/api/equipment.d.ts +6 -6
  23. package/dist/api/equipment.d.ts.map +1 -1
  24. package/dist/api/equipment.js.map +1 -1
  25. package/dist/api/farms.d.ts +6 -6
  26. package/dist/api/farms.d.ts.map +1 -1
  27. package/dist/api/farms.js.map +1 -1
  28. package/dist/api/field-operations-api.d.ts +5 -4
  29. package/dist/api/field-operations-api.d.ts.map +1 -1
  30. package/dist/api/field-operations-api.js.map +1 -1
  31. package/dist/api/fields.d.ts +9 -8
  32. package/dist/api/fields.d.ts.map +1 -1
  33. package/dist/api/fields.js.map +1 -1
  34. package/dist/api/files.d.ts +7 -6
  35. package/dist/api/files.d.ts.map +1 -1
  36. package/dist/api/files.js.map +1 -1
  37. package/dist/api/flags.d.ts +8 -7
  38. package/dist/api/flags.d.ts.map +1 -1
  39. package/dist/api/flags.js.map +1 -1
  40. package/dist/api/guidance-lines.d.ts +3 -2
  41. package/dist/api/guidance-lines.d.ts.map +1 -1
  42. package/dist/api/guidance-lines.js.map +1 -1
  43. package/dist/api/harvest-id.d.ts +41 -0
  44. package/dist/api/harvest-id.d.ts.map +1 -0
  45. package/dist/api/harvest-id.js +59 -0
  46. package/dist/api/harvest-id.js.map +1 -0
  47. package/dist/api/index.d.ts +20 -0
  48. package/dist/api/index.d.ts.map +1 -1
  49. package/dist/api/index.js +10 -0
  50. package/dist/api/index.js.map +1 -1
  51. package/dist/api/machine-alerts.d.ts +33 -0
  52. package/dist/api/machine-alerts.d.ts.map +1 -0
  53. package/dist/api/machine-alerts.js +46 -0
  54. package/dist/api/machine-alerts.js.map +1 -0
  55. package/dist/api/machine-device-state-reports.d.ts +24 -0
  56. package/dist/api/machine-device-state-reports.d.ts.map +1 -0
  57. package/dist/api/machine-device-state-reports.js +30 -0
  58. package/dist/api/machine-device-state-reports.js.map +1 -0
  59. package/dist/api/machine-engine-hours.d.ts +33 -0
  60. package/dist/api/machine-engine-hours.d.ts.map +1 -0
  61. package/dist/api/machine-engine-hours.js +46 -0
  62. package/dist/api/machine-engine-hours.js.map +1 -0
  63. package/dist/api/machine-hours-of-operation.d.ts +33 -0
  64. package/dist/api/machine-hours-of-operation.d.ts.map +1 -0
  65. package/dist/api/machine-hours-of-operation.js +46 -0
  66. package/dist/api/machine-hours-of-operation.js.map +1 -0
  67. package/dist/api/machine-locations.d.ts +24 -0
  68. package/dist/api/machine-locations.d.ts.map +1 -0
  69. package/dist/api/machine-locations.js +30 -0
  70. package/dist/api/machine-locations.js.map +1 -0
  71. package/dist/api/map-layers.d.ts +1 -1
  72. package/dist/api/map-layers.d.ts.map +1 -1
  73. package/dist/api/map-layers.js.map +1 -1
  74. package/dist/api/notifications.d.ts +61 -0
  75. package/dist/api/notifications.d.ts.map +1 -0
  76. package/dist/api/notifications.js +93 -0
  77. package/dist/api/notifications.js.map +1 -0
  78. package/dist/api/operators.d.ts +2 -2
  79. package/dist/api/operators.d.ts.map +1 -1
  80. package/dist/api/operators.js.map +1 -1
  81. package/dist/api/partnerships.d.ts +55 -0
  82. package/dist/api/partnerships.d.ts.map +1 -0
  83. package/dist/api/partnerships.js +75 -0
  84. package/dist/api/partnerships.js.map +1 -0
  85. package/dist/api/products.d.ts +4 -4
  86. package/dist/api/products.d.ts.map +1 -1
  87. package/dist/api/products.js.map +1 -1
  88. package/dist/api/webhook.d.ts +3 -2
  89. package/dist/api/webhook.d.ts.map +1 -1
  90. package/dist/api/webhook.js.map +1 -1
  91. package/dist/client.d.ts +34 -0
  92. package/dist/client.d.ts.map +1 -1
  93. package/dist/client.js +127 -35
  94. package/dist/client.js.map +1 -1
  95. package/dist/deere.d.ts +30 -0
  96. package/dist/deere.d.ts.map +1 -1
  97. package/dist/deere.js +40 -0
  98. package/dist/deere.js.map +1 -1
  99. package/dist/types/generated/aemp.d.ts +255 -0
  100. package/dist/types/generated/aemp.d.ts.map +1 -0
  101. package/dist/types/generated/aemp.js +6 -0
  102. package/dist/types/generated/aemp.js.map +1 -0
  103. package/dist/types/generated/equipment-measurement.d.ts +380 -0
  104. package/dist/types/generated/equipment-measurement.d.ts.map +1 -0
  105. package/dist/types/generated/equipment-measurement.js +6 -0
  106. package/dist/types/generated/equipment-measurement.js.map +1 -0
  107. package/dist/types/generated/harvest-id.d.ts +397 -0
  108. package/dist/types/generated/harvest-id.d.ts.map +1 -0
  109. package/dist/types/generated/harvest-id.js +6 -0
  110. package/dist/types/generated/harvest-id.js.map +1 -0
  111. package/dist/types/generated/index.d.ts +21 -1
  112. package/dist/types/generated/index.d.ts.map +1 -1
  113. package/dist/types/generated/index.js +11 -1
  114. package/dist/types/generated/index.js.map +1 -1
  115. package/dist/types/generated/machine-alerts.d.ts +321 -0
  116. package/dist/types/generated/machine-alerts.d.ts.map +1 -0
  117. package/dist/types/generated/machine-alerts.js +6 -0
  118. package/dist/types/generated/machine-alerts.js.map +1 -0
  119. package/dist/types/generated/machine-device-state-reports.d.ts +330 -0
  120. package/dist/types/generated/machine-device-state-reports.d.ts.map +1 -0
  121. package/dist/types/generated/machine-device-state-reports.js +6 -0
  122. package/dist/types/generated/machine-device-state-reports.js.map +1 -0
  123. package/dist/types/generated/machine-engine-hours.d.ts +123 -0
  124. package/dist/types/generated/machine-engine-hours.d.ts.map +1 -0
  125. package/dist/types/generated/machine-engine-hours.js +6 -0
  126. package/dist/types/generated/machine-engine-hours.js.map +1 -0
  127. package/dist/types/generated/machine-hours-of-operation.d.ts +130 -0
  128. package/dist/types/generated/machine-hours-of-operation.d.ts.map +1 -0
  129. package/dist/types/generated/machine-hours-of-operation.js +6 -0
  130. package/dist/types/generated/machine-hours-of-operation.js.map +1 -0
  131. package/dist/types/generated/machine-locations.d.ts +132 -0
  132. package/dist/types/generated/machine-locations.d.ts.map +1 -0
  133. package/dist/types/generated/machine-locations.js +6 -0
  134. package/dist/types/generated/machine-locations.js.map +1 -0
  135. package/dist/types/generated/notifications.d.ts +398 -0
  136. package/dist/types/generated/notifications.d.ts.map +1 -0
  137. package/dist/types/generated/notifications.js +6 -0
  138. package/dist/types/generated/notifications.js.map +1 -0
  139. package/dist/types/generated/partnerships.d.ts +388 -0
  140. package/dist/types/generated/partnerships.d.ts.map +1 -0
  141. package/dist/types/generated/partnerships.js +6 -0
  142. package/dist/types/generated/partnerships.js.map +1 -0
  143. package/dist/types/index.d.ts +10 -0
  144. package/dist/types/index.d.ts.map +1 -1
  145. package/dist/types/index.js +10 -0
  146. package/dist/types/index.js.map +1 -1
  147. package/package.json +4 -2
package/README.md CHANGED
@@ -1,19 +1,55 @@
1
- # John Deere TypeScript SDK
2
-
3
- > **Unofficial** TypeScript SDK for John Deere Operations Center API
4
-
5
- This SDK provides typed access to John Deere's agricultural APIs, auto-generated from their OpenAPI specifications.
1
+ <h1 align="center">deere-sdk</h1>
2
+
3
+ <p align="center">
4
+ <strong>Unofficial TypeScript SDK for John Deere Operations Center API</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/deere-sdk"><img src="https://img.shields.io/npm/v/deere-sdk?style=flat-square&color=blue" alt="npm version"></a>
9
+ <a href="https://www.npmjs.com/package/deere-sdk"><img src="https://img.shields.io/npm/dm/deere-sdk?style=flat-square" alt="npm downloads"></a>
10
+ <a href="https://github.com/ProductOfAmerica/deere-sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="license"></a>
11
+ <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.0+-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript"></a>
12
+ <a href="https://github.com/ProductOfAmerica/deere-sdk/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/ProductOfAmerica/deere-sdk/ci.yml?style=flat-square&label=tests" alt="Tests"></a>
13
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/ProductOfAmerica/deere-sdk/main/.github/badges/coverage.json&style=flat-square" alt="Coverage">
14
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/ProductOfAmerica/deere-sdk/main/.github/badges/api-health.json&style=flat-square" alt="API Health">
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="#installation">Installation</a> •
19
+ <a href="#quick-start">Quick Start</a> •
20
+ <a href="#api-reference">API Reference</a> •
21
+ <a href="#api-status">API Status</a>
22
+ </p>
23
+
24
+ ---
25
+
26
+ ## Highlights
27
+
28
+ - **28 APIs** with **123 operations** — Full coverage of John Deere agricultural APIs
29
+ - **Fully typed** — Auto-generated TypeScript types from OpenAPI specs
30
+ - **Auto-pagination** — `listAll()` methods handle pagination automatically
31
+ - **HAL support** — Built-in link following for John Deere's HAL-style responses
32
+ - **Automatic retries** — Exponential backoff with jitter for transient failures
33
+ - **Daily health checks** — Automated monitoring of API availability
34
+
35
+ ---
6
36
 
7
37
  ## Installation
8
38
 
9
39
  ```bash
10
40
  npm install deere-sdk
11
- # or
41
+ ```
42
+
43
+ ```bash
12
44
  pnpm add deere-sdk
13
- # or
45
+ ```
46
+
47
+ ```bash
14
48
  yarn add deere-sdk
15
49
  ```
16
50
 
51
+ ---
52
+
17
53
  ## Quick Start
18
54
 
19
55
  ```typescript
@@ -26,95 +62,135 @@ const deere = new Deere({
26
62
 
27
63
  // List all organizations
28
64
  const orgs = await deere.organizations.listAll();
29
- console.log('Organizations:', orgs);
30
65
 
31
66
  // Get fields for an organization
32
67
  const fields = await deere.fields.listAll(orgs[0].id);
33
- console.log('Fields:', fields);
34
-
35
- // Get farms
36
- const farms = await deere.farms.listAll(orgs[0].id);
37
- console.log('Farms:', farms);
38
68
 
39
69
  // Get equipment
40
70
  const equipment = await deere.equipment.get();
41
- console.log('Equipment:', equipment);
42
71
  ```
43
72
 
73
+ ---
74
+
44
75
  ## Authentication
45
76
 
46
- This SDK requires an OAuth 2.0 access token from John Deere. You'll need to:
77
+ This SDK requires an OAuth 2.0 access token from John Deere:
47
78
 
48
- 1. Register as a developer at [developer.deere.com](https://developer.deere.com)
79
+ 1. Register at [developer.deere.com](https://developer.deere.com)
49
80
  2. Create an application and get your client ID/secret
50
- 3. Implement the OAuth 2.0 flow to obtain access tokens
51
- 4. Use the `accessToken` in the SDK configuration
52
-
53
- ### OAuth Scopes
54
-
55
- Common scopes you may need:
56
- - `ag1` - Read access to agricultural data
57
- - `ag2` - Write access to agricultural data
58
- - `ag3` - Additional agricultural data access
59
- - `offline_access` - Refresh token support
60
-
61
- ## Available APIs
62
-
63
- The SDK provides access to 18 John Deere APIs:
64
-
65
- | API | Property | Description |
66
- |-----|----------|-------------|
67
- | Organizations | `deere.organizations` | Organization management |
68
- | Fields | `deere.fields` | Field CRUD and boundaries |
69
- | Farms | `deere.farms` | Farm management |
70
- | Boundaries | `deere.boundaries` | Field boundary management |
71
- | Clients | `deere.clients` | Client/customer management |
72
- | Equipment | `deere.equipment` | Machines and implements |
73
- | Field Operations | `deere.fieldOperations` | Harvests, plantings, applications |
74
- | Crop Types | `deere.cropTypes` | Crop type catalog |
75
- | Products | `deere.products` | Product catalog (seeds, chemicals) |
76
- | Map Layers | `deere.mapLayers` | Map layer management |
77
- | Files | `deere.files` | File management |
78
- | Flags | `deere.flags` | Field flags/markers |
79
- | Guidance Lines | `deere.guidanceLines` | GPS guidance lines |
80
- | Operators | `deere.operators` | Machine operator management |
81
- | Users | `deere.users` | User management |
82
- | Assets | `deere.assets` | Asset management |
83
- | Webhook | `deere.webhook` | Webhook subscriptions |
84
- | Connection Management | `deere.connectionManagement` | OAuth connection management |
85
-
86
- ## API Examples
87
-
88
- ### Organizations
81
+ 3. Implement the OAuth 2.0 authorization code flow
82
+ 4. Use the access token in the SDK
83
+
84
+ <details>
85
+ <summary><strong>OAuth Scopes</strong></summary>
86
+
87
+ | Scope | Description |
88
+ |-------|-------------|
89
+ | `ag1` | Read access to agricultural data |
90
+ | `ag2` | Write access to agricultural data |
91
+ | `ag3` | Additional agricultural data access |
92
+ | `offline_access` | Refresh token support |
93
+
94
+ </details>
95
+
96
+ <details>
97
+ <summary><strong>Environments</strong></summary>
98
+
99
+ | Environment | URL | Use Case |
100
+ |-------------|-----|----------|
101
+ | `production` | api.deere.com | Live data |
102
+ | `sandbox` | sandboxapi.deere.com | Development |
103
+ | `partner` | partnerapi.deere.com | Partner integrations |
104
+ | `cert` | apicert.deere.com | Certification |
105
+
106
+ </details>
107
+
108
+ ---
109
+
110
+ ## API Reference
111
+
112
+ ### Operations Center APIs
113
+
114
+ | API | Property | Methods | Description |
115
+ |-----|----------|---------|-------------|
116
+ | [Organizations](https://developer.deere.com/documentation/organizations) | `deere.organizations` | 4 | Organization management |
117
+ | [Fields](https://developer.deere.com/documentation/fields) | `deere.fields` | 7 | Field CRUD and boundaries |
118
+ | [Farms](https://developer.deere.com/documentation/farms) | `deere.farms` | 7 | Farm management |
119
+ | [Boundaries](https://developer.deere.com/documentation/boundaries) | `deere.boundaries` | 7 | Field boundary management |
120
+ | [Clients](https://developer.deere.com/documentation/clients) | `deere.clients` | 7 | Customer management |
121
+ | [Equipment](https://developer.deere.com/documentation/equipment) | `deere.equipment` | 15 | Machines and implements |
122
+ | [Field Operations](https://developer.deere.com/documentation/field-operations-api) | `deere.fieldOperations` | 4 | Harvests, plantings, applications |
123
+ | [Crop Types](https://developer.deere.com/documentation/crop-types) | `deere.cropTypes` | 4 | Crop type catalog |
124
+ | [Products](https://developer.deere.com/documentation/products) | `deere.products` | 9 | Seeds and chemicals catalog |
125
+ | [Map Layers](https://developer.deere.com/documentation/map-layers) | `deere.mapLayers` | 4 | Map layer management |
126
+ | [Files](https://developer.deere.com/documentation/files) | `deere.files` | 5 | File management |
127
+ | [Flags](https://developer.deere.com/documentation/flags) | `deere.flags` | 6 | Field flags/markers |
128
+ | [Guidance Lines](https://developer.deere.com/documentation/guidance-lines) | `deere.guidanceLines` | 4 | GPS guidance lines |
129
+ | [Operators](https://developer.deere.com/documentation/operators) | `deere.operators` | 6 | Machine operator management |
130
+ | [Users](https://developer.deere.com/documentation/users) | `deere.users` | 1 | User information |
131
+ | [Assets](https://developer.deere.com/documentation/assets) | `deere.assets` | 8 | Asset tracking |
132
+ | [Webhooks](https://developer.deere.com/documentation/webhook) | `deere.webhook` | 4 | Event subscriptions |
133
+ | [Connections](https://developer.deere.com/documentation/connection-management) | `deere.connectionManagement` | 3 | OAuth connections |
134
+
135
+ ### Machine Data APIs
136
+
137
+ | API | Property | Methods | Description |
138
+ |-----|----------|---------|-------------|
139
+ | [Machine Locations](https://developer.deere.com/documentation/machine-locations) | `deere.machineLocations` | 1 | GPS location history |
140
+ | [Machine Alerts](https://developer.deere.com/documentation/machine-alerts) | `deere.machineAlerts` | 1 | DTC alerts |
141
+ | [Engine Hours](https://developer.deere.com/documentation/machine-engine-hours) | `deere.machineEngineHours` | 1 | Engine hours tracking |
142
+ | [Hours of Operation](https://developer.deere.com/documentation/machine-hours-of-operation) | `deere.machineHoursOfOperation` | 1 | On/off duration |
143
+ | [Device State](https://developer.deere.com/documentation/machine-device-state-reports) | `deere.machineDeviceStateReports` | 1 | Terminal state reports |
144
+ | [Notifications](https://developer.deere.com/documentation/notifications) | `deere.notifications` | 4 | Push notifications |
145
+ | [Harvest ID](https://developer.deere.com/documentation/harvest-id) | `deere.harvestId` | 2 | Cotton module data |
146
+ | [AEMP](https://developer.deere.com/documentation/aemp) | `deere.aemp` | 1 | ISO 15143-3 fleet data |
147
+ | [Equipment Measurement](https://developer.deere.com/documentation/equipment-measurement) | `deere.equipmentMeasurement` | 1 | Third-party measurements |
148
+ | [Partnerships](https://developer.deere.com/documentation/partnerships) | `deere.partnerships` | 6 | Organization partnerships |
149
+
150
+ ---
151
+
152
+ ## Usage Examples
153
+
154
+ <details>
155
+ <summary><strong>Organizations</strong></summary>
89
156
 
90
157
  ```typescript
91
158
  // List all organizations
92
- const orgs = await deere.organizations.listAll();
159
+ const orgs = await deere.organizations.list();
160
+ const allOrgs = await deere.organizations.listAll();
93
161
 
94
- // Get specific organization
162
+ // Get a specific organization
95
163
  const org = await deere.organizations.get('org-id');
96
164
 
97
- // Search organizations
98
- const filtered = await deere.organizations.list({ orgName: 'Farm' });
99
-
100
165
  // List users in an organization
101
166
  const users = await deere.organizations.listUsers('org-id');
102
- for (const user of users.values) {
103
- console.log(`${user.givenName} ${user.familyName} (${user.userType})`);
104
- }
105
167
  ```
106
168
 
107
- ### Fields
169
+ </details>
170
+
171
+ <details>
172
+ <summary><strong>Fields</strong></summary>
108
173
 
109
174
  ```typescript
110
- // List all fields
111
- const fields = await deere.fields.listAll('org-id');
175
+ // List fields in an organization
176
+ const fields = await deere.fields.list('org-id');
177
+ const allFields = await deere.fields.listAll('org-id');
178
+
179
+ // Filter fields
180
+ const filtered = await deere.fields.list('org-id', {
181
+ farmName: 'North Farm',
182
+ recordFilter: 'AVAILABLE'
183
+ });
112
184
 
113
- // Get field details
185
+ // Get a specific field
114
186
  const field = await deere.fields.get('org-id', 'field-id');
115
187
 
116
188
  // Create a field
117
- await deere.fields.create('org-id', { name: 'North Field', ... });
189
+ await deere.fields.create('org-id', {
190
+ name: 'North Field',
191
+ farmName: 'Smith Farm',
192
+ clientName: 'John Smith'
193
+ });
118
194
 
119
195
  // Update a field
120
196
  await deere.fields.update('org-id', 'field-id', { name: 'Updated Name' });
@@ -123,70 +199,250 @@ await deere.fields.update('org-id', 'field-id', { name: 'Updated Name' });
123
199
  await deere.fields.delete('org-id', 'field-id');
124
200
  ```
125
201
 
126
- ### Farms
202
+ </details>
203
+
204
+ <details>
205
+ <summary><strong>Farms</strong></summary>
127
206
 
128
207
  ```typescript
129
- // List all farms
130
- const farms = await deere.farms.listAll('org-id');
208
+ // List farms
209
+ const farms = await deere.farms.list('org-id');
210
+ const allFarms = await deere.farms.listAll('org-id');
211
+
212
+ // Include archived
213
+ const all = await deere.farms.list('org-id', { recordFilter: 'all' });
214
+
215
+ // CRUD operations
216
+ const farm = await deere.farms.get('org-id', 'farm-id');
217
+ await deere.farms.create('org-id', { name: 'North Farm' });
218
+ await deere.farms.update('org-id', 'farm-id', { name: 'Updated' });
219
+ await deere.farms.delete('org-id', 'farm-id');
220
+
221
+ // Related resources
222
+ const clients = await deere.farms.listClients('org-id', 'farm-id');
223
+ const fields = await deere.farms.listFields('org-id', 'farm-id');
224
+ ```
131
225
 
132
- // Get farm with archived filter
133
- const allFarms = await deere.farms.list('org-id', { recordFilter: 'all' });
226
+ </details>
134
227
 
135
- // Create a farm
136
- await deere.farms.create('org-id', { name: 'Smith Farm', clientUri: '...' });
228
+ <details>
229
+ <summary><strong>Boundaries</strong></summary>
230
+
231
+ ```typescript
232
+ // List boundaries
233
+ const boundaries = await deere.boundaries.list('org-id');
234
+ const fieldBoundaries = await deere.boundaries.listBoundaries('org-id', 'field-id');
235
+
236
+ // Get specific boundary
237
+ const boundary = await deere.boundaries.getBoundaries('org-id', 'field-id', 'boundary-id');
238
+
239
+ // Generate from field operation
240
+ const generated = await deere.boundaries.get('operation-id');
241
+
242
+ // Create boundary
243
+ await deere.boundaries.create('org-id', 'field-id', {
244
+ name: 'Main Boundary',
245
+ active: true,
246
+ multipolygons: [/* GeoJSON */]
247
+ });
137
248
 
138
- // Get fields for a farm
139
- const farmFields = await deere.farms.listFields('org-id', 'farm-id');
249
+ // Update/Delete
250
+ await deere.boundaries.update('org-id', 'field-id', 'boundary-id', { name: 'New Name' });
251
+ await deere.boundaries.delete('org-id', 'field-id', 'boundary-id');
140
252
  ```
141
253
 
142
- ### Equipment
254
+ </details>
255
+
256
+ <details>
257
+ <summary><strong>Equipment</strong></summary>
143
258
 
144
259
  ```typescript
145
260
  // Get all equipment
146
261
  const equipment = await deere.equipment.get();
147
262
 
148
- // Filter by organization
149
- const orgEquipment = await deere.equipment.get({ organizationIds: [123] });
150
-
151
- // Filter by type
152
- const machines = await deere.equipment.get({ categories: 'Machine' });
263
+ // Filter equipment
264
+ const filtered = await deere.equipment.get({
265
+ organizationIds: [123],
266
+ categories: 'Machine',
267
+ capableOf: 'Connectivity'
268
+ });
153
269
 
154
270
  // Get equipment details
155
271
  const machine = await deere.equipment.getEquipment('equipment-id');
272
+
273
+ // CRUD
274
+ await deere.equipment.create('org-id', { type: 'Machine', name: 'Tractor 1' });
275
+ await deere.equipment.update('equipment-id', { name: 'Updated' });
276
+ await deere.equipment.delete('equipment-id');
277
+
278
+ // Reference data
279
+ const makes = await deere.equipment.list();
280
+ const types = await deere.equipment.listEquipmenttypes();
281
+ const models = await deere.equipment.listEquipmentmodels({ equipmentModelName: '9RX*' });
156
282
  ```
157
283
 
158
- ### Field Operations
284
+ </details>
285
+
286
+ <details>
287
+ <summary><strong>Field Operations</strong></summary>
159
288
 
160
289
  ```typescript
161
- // Get field operations
162
- const ops = await deere.fieldOperations.list('org-id');
290
+ // List field operations
291
+ const ops = await deere.fieldOperations.list('org-id', 'field-id');
163
292
 
164
- // Filter by crop season and type
165
- const harvests = await deere.fieldOperations.list('org-id', {
293
+ // Filter by type and season
294
+ const harvests = await deere.fieldOperations.list('org-id', 'field-id', {
166
295
  cropSeason: '2024',
167
- fieldOperationTypes: 'harvest'
296
+ fieldOperationType: 'harvest'
297
+ });
298
+
299
+ // Get operation details
300
+ const op = await deere.fieldOperations.get('operation-id');
301
+
302
+ // Download shapefile
303
+ const shapefile = await deere.fieldOperations.getFieldops('operation-id', {
304
+ shapeType: 'Polygon',
305
+ resolution: 'EachSection'
168
306
  });
169
307
  ```
170
308
 
171
- ### Boundaries
309
+ </details>
310
+
311
+ <details>
312
+ <summary><strong>Machine Data</strong></summary>
172
313
 
173
314
  ```typescript
174
- // List boundaries for a field
175
- const boundaries = await deere.boundaries.listAll('org-id', 'field-id');
315
+ // Machine locations
316
+ const locations = await deere.machineLocations.get('principal-id', {
317
+ startDate: '2024-01-01T00:00:00Z',
318
+ endDate: '2024-01-31T23:59:59Z'
319
+ });
176
320
 
177
- // Get active boundary
178
- const active = await deere.boundaries.getActiveBoundary('org-id', 'field-id');
321
+ // Machine alerts
322
+ const alerts = await deere.machineAlerts.list('principal-id');
179
323
 
180
- // Create boundary
181
- await deere.boundaries.create('org-id', 'field-id', {
182
- name: 'Main Boundary',
183
- multipolygons: [...]
324
+ // Engine hours
325
+ const hours = await deere.machineEngineHours.list('principal-id', { lastKnown: true });
326
+
327
+ // Hours of operation
328
+ const opHours = await deere.machineHoursOfOperation.list('principal-id');
329
+
330
+ // Device state reports
331
+ const state = await deere.machineDeviceStateReports.get('principal-id');
332
+ ```
333
+
334
+ </details>
335
+
336
+ <details>
337
+ <summary><strong>Notifications</strong></summary>
338
+
339
+ ```typescript
340
+ // List notifications
341
+ const notifications = await deere.notifications.list('org-id');
342
+
343
+ // Filter by severity
344
+ const critical = await deere.notifications.list('org-id', {
345
+ severities: 'HIGH,CRITICAL'
184
346
  });
347
+
348
+ // Create notification
349
+ await deere.notifications.create({
350
+ sourceEvent: 'my-app-event-123',
351
+ title: 'Action Required',
352
+ message: 'Please review the prescription map'
353
+ });
354
+
355
+ // Delete notification
356
+ await deere.notifications.delete('source-event-id');
185
357
  ```
186
358
 
187
- ### Low-Level Client
359
+ </details>
188
360
 
189
- For endpoints not covered by the typed APIs:
361
+ <details>
362
+ <summary><strong>Assets</strong></summary>
363
+
364
+ ```typescript
365
+ // List assets
366
+ const assets = await deere.assets.listAll('org-id');
367
+
368
+ // Get asset
369
+ const asset = await deere.assets.get('asset-id');
370
+
371
+ // Create asset
372
+ await deere.assets.create('org-id', {
373
+ title: 'Fuel Tank #1',
374
+ assetCategory: 'DEVICE',
375
+ assetType: 'SENSOR'
376
+ });
377
+
378
+ // Asset locations
379
+ const locations = await deere.assets.listLocations('asset-id', {
380
+ startDate: '2024-01-01T00:00:00Z',
381
+ endDate: '2024-12-31T23:59:59Z'
382
+ });
383
+
384
+ await deere.assets.createLocations('asset-id', {
385
+ timestamp: '2024-06-15T12:00:00Z',
386
+ geometry: { type: 'Point', coordinates: [-93.5, 42.5] }
387
+ });
388
+ ```
389
+
390
+ </details>
391
+
392
+ <details>
393
+ <summary><strong>Webhooks</strong></summary>
394
+
395
+ ```typescript
396
+ // List subscriptions
397
+ const subs = await deere.webhook.listAll();
398
+
399
+ // Create subscription
400
+ await deere.webhook.create({
401
+ clientKey: 'your-client-key',
402
+ eventTypeId: 'equipment-status',
403
+ callbackUrl: 'https://your-server.com/webhook'
404
+ });
405
+
406
+ // Update subscription
407
+ await deere.webhook.update('subscription-id', {
408
+ callbackUrl: 'https://new-server.com/webhook'
409
+ });
410
+ ```
411
+
412
+ </details>
413
+
414
+ <details>
415
+ <summary><strong>Partnerships</strong></summary>
416
+
417
+ ```typescript
418
+ // List partnerships
419
+ const partnerships = await deere.partnerships.listAll();
420
+
421
+ // Create partnership request
422
+ await deere.partnerships.create({
423
+ toOrganizationId: 'partner-org-id',
424
+ message: 'Request to share data'
425
+ });
426
+
427
+ // Get/delete partnership
428
+ const partnership = await deere.partnerships.get('token');
429
+ await deere.partnerships.delete('token');
430
+
431
+ // Permissions
432
+ const perms = await deere.partnerships.listPermissions('token');
433
+ await deere.partnerships.createPermissions('token', {
434
+ permissionType: 'ViewData',
435
+ enabled: true
436
+ });
437
+ ```
438
+
439
+ </details>
440
+
441
+ ---
442
+
443
+ ## Low-Level Client
444
+
445
+ For custom endpoints or advanced use cases:
190
446
 
191
447
  ```typescript
192
448
  import { DeereClient } from 'deere-sdk';
@@ -194,9 +450,11 @@ import { DeereClient } from 'deere-sdk';
194
450
  const client = new DeereClient({
195
451
  accessToken: 'your-token',
196
452
  environment: 'sandbox',
453
+ timeout: 30000, // Request timeout in ms (default: 30000)
454
+ maxRetries: 3, // Retry attempts (default: 3, set to 0 to disable)
197
455
  });
198
456
 
199
- // Make raw requests
457
+ // Raw requests
200
458
  const response = await client.get<CustomType>('/some/endpoint');
201
459
  const created = await client.post('/some/endpoint', { data: 'value' });
202
460
 
@@ -209,8 +467,41 @@ for await (const items of client.paginate('/large/collection')) {
209
467
  }
210
468
  ```
211
469
 
470
+ ---
471
+
212
472
  ## Error Handling
213
473
 
474
+ ### Automatic Retries
475
+
476
+ The SDK automatically retries failed requests with exponential backoff and jitter:
477
+
478
+ | Error Type | Retried? | Notes |
479
+ |------------|----------|-------|
480
+ | `429` Rate Limit | Yes | Respects `Retry-After` header |
481
+ | `500`, `502`, `503`, `504` | Yes | Server errors |
482
+ | Network failures | Yes | Connection issues |
483
+ | Timeouts | Yes | Request took too long |
484
+ | `401`, `403` Auth errors | No | Refresh your token |
485
+ | `400`, `404`, `422` | No | Fix your request |
486
+
487
+ **Default behavior:** 3 retries with exponential backoff (delays of ~1s, ~2s, ~4s with jitter).
488
+
489
+ ```typescript
490
+ // Customize retry behavior
491
+ const deere = new Deere({
492
+ accessToken: 'your-token',
493
+ maxRetries: 5, // More retries (default: 3)
494
+ });
495
+
496
+ // Disable retries entirely
497
+ const deere = new Deere({
498
+ accessToken: 'your-token',
499
+ maxRetries: 0,
500
+ });
501
+ ```
502
+
503
+ ### Error Types
504
+
214
505
  ```typescript
215
506
  import { DeereError, RateLimitError, AuthError } from 'deere-sdk';
216
507
 
@@ -218,42 +509,109 @@ try {
218
509
  const fields = await deere.fields.listAll('org-id');
219
510
  } catch (error) {
220
511
  if (error instanceof RateLimitError) {
221
- console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
512
+ // Only thrown after all retries exhausted
513
+ console.log(`Rate limited. Retry after ${error.retryAfter}s`);
222
514
  } else if (error instanceof AuthError) {
223
- console.log('Authentication failed. Token may be expired.');
515
+ // Never retried - refresh your token
516
+ console.log('Token expired - refresh required');
224
517
  } else if (error instanceof DeereError) {
225
518
  console.log(`API error: ${error.status} ${error.message}`);
226
519
  }
227
520
  }
228
521
  ```
229
522
 
230
- ## Environments
231
-
232
- | Environment | URL | Use Case |
233
- |-------------|-----|----------|
234
- | `production` | api.deere.com | Live production data |
235
- | `sandbox` | sandboxapi.deere.com | Development/testing |
236
- | `partner` | partnerapi.deere.com | Partner integrations |
237
- | `cert` | apicert.deere.com | Certification testing |
523
+ ---
238
524
 
239
525
  ## TypeScript Support
240
526
 
241
- The SDK is fully typed. You can access the OpenAPI-generated types:
527
+ Access auto-generated types from OpenAPI specs:
242
528
 
243
529
  ```typescript
244
530
  import { Types } from 'deere-sdk';
245
531
 
246
- // Access specific API types
247
532
  type Farm = Types.Farms.components['schemas']['GetFarm'];
248
533
  type Field = Types.Fields.components['schemas']['FieldsResponse'];
534
+ type Equipment = Types.Equipment.components['schemas']['equipment-model'];
535
+ ```
536
+
537
+ ---
538
+
539
+ ## API Status
540
+
541
+ This SDK includes automated daily health checks to monitor John Deere API availability.
542
+
543
+ | Status | Meaning |
544
+ |--------|---------|
545
+ | ![passing](https://img.shields.io/badge/API%20Health-28%2F28-brightgreen?style=flat-square) | All APIs responding with valid specs |
546
+ | ![degraded](https://img.shields.io/badge/API%20Health-25%2F28-yellow?style=flat-square) | Some APIs unavailable or returning empty specs |
547
+ | ![failing](https://img.shields.io/badge/API%20Health-10%2F28-red?style=flat-square) | Major API outage detected |
548
+
549
+ <details>
550
+ <summary><strong>APIs Without Public Specs</strong></summary>
551
+
552
+ These APIs are listed on John Deere's portal but don't provide public OpenAPI specs:
553
+
554
+ | API | Notes |
555
+ |-----|-------|
556
+ | `work-plans` | Listed but returns empty spec |
557
+ | `retrieve-warranty-information` | Dealer-only |
558
+ | `retrieve-pip` | Dealer-only |
559
+ | `valid-pin` | Dealer-only |
560
+
561
+ </details>
562
+
563
+ <details>
564
+ <summary><strong>Additional John Deere APIs</strong></summary>
565
+
566
+ John Deere offers 40+ additional APIs not included in this SDK:
567
+
568
+ - **Dealer Solutions** (32 APIs) — Warranty, quotes, service for dealers
569
+ - **Financial** (4 APIs) — Merchant transactions, credit applications
570
+ - **Supply Chain** (1 API) — Supplier quoting
571
+
572
+ These target dealers rather than farmers. See [developer.deere.com](https://developer.deere.com) for full documentation.
573
+
574
+ </details>
575
+
576
+ ---
577
+
578
+ ## Contributing
579
+
580
+ Contributions are welcome! Please read the contributing guidelines before submitting a PR.
581
+
582
+ ```bash
583
+ # Clone the repo
584
+ git clone https://github.com/ProductOfAmerica/deere-sdk.git
585
+
586
+ # Install dependencies
587
+ pnpm install
588
+
589
+ # Fetch specs and generate SDK
590
+ pnpm generate
591
+
592
+ # Build
593
+ pnpm build
594
+
595
+ # Run tests
596
+ pnpm test
249
597
  ```
250
598
 
599
+ ---
600
+
251
601
  ## Disclaimer
252
602
 
253
- This is an **unofficial** SDK and is not affiliated with, endorsed by, or connected to John Deere or Deere & Company. Use at your own risk.
603
+ > **This is an unofficial SDK** and is not affiliated with, endorsed by, or connected to John Deere or Deere & Company. Use at your own risk.
604
+ >
605
+ > John Deere, Operations Center, and the leaping deer logo are trademarks of Deere & Company.
254
606
 
255
- John Deere and Operations Center are trademarks of Deere & Company.
607
+ ---
256
608
 
257
609
  ## License
258
610
 
259
- MIT
611
+ MIT © 2024
612
+
613
+ ---
614
+
615
+ <p align="center">
616
+ <sub>Built with TypeScript and auto-generated from John Deere OpenAPI specs</sub>
617
+ </p>