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.
- package/README.md +474 -116
- package/dist/api/aemp.d.ts +19 -0
- package/dist/api/aemp.d.ts.map +1 -0
- package/dist/api/aemp.js +22 -0
- package/dist/api/aemp.js.map +1 -0
- package/dist/api/assets.d.ts +7 -7
- package/dist/api/assets.d.ts.map +1 -1
- package/dist/api/assets.js.map +1 -1
- package/dist/api/boundaries.d.ts +8 -7
- package/dist/api/boundaries.d.ts.map +1 -1
- package/dist/api/boundaries.js.map +1 -1
- package/dist/api/clients.d.ts +5 -5
- package/dist/api/clients.d.ts.map +1 -1
- package/dist/api/clients.js.map +1 -1
- package/dist/api/crop-types.d.ts +7 -6
- package/dist/api/crop-types.d.ts.map +1 -1
- package/dist/api/crop-types.js.map +1 -1
- package/dist/api/equipment-measurement.d.ts +20 -0
- package/dist/api/equipment-measurement.d.ts.map +1 -0
- package/dist/api/equipment-measurement.js +22 -0
- package/dist/api/equipment-measurement.js.map +1 -0
- package/dist/api/equipment.d.ts +6 -6
- package/dist/api/equipment.d.ts.map +1 -1
- package/dist/api/equipment.js.map +1 -1
- package/dist/api/farms.d.ts +6 -6
- package/dist/api/farms.d.ts.map +1 -1
- package/dist/api/farms.js.map +1 -1
- package/dist/api/field-operations-api.d.ts +5 -4
- package/dist/api/field-operations-api.d.ts.map +1 -1
- package/dist/api/field-operations-api.js.map +1 -1
- package/dist/api/fields.d.ts +9 -8
- package/dist/api/fields.d.ts.map +1 -1
- package/dist/api/fields.js.map +1 -1
- package/dist/api/files.d.ts +7 -6
- package/dist/api/files.d.ts.map +1 -1
- package/dist/api/files.js.map +1 -1
- package/dist/api/flags.d.ts +8 -7
- package/dist/api/flags.d.ts.map +1 -1
- package/dist/api/flags.js.map +1 -1
- package/dist/api/guidance-lines.d.ts +3 -2
- package/dist/api/guidance-lines.d.ts.map +1 -1
- package/dist/api/guidance-lines.js.map +1 -1
- package/dist/api/harvest-id.d.ts +41 -0
- package/dist/api/harvest-id.d.ts.map +1 -0
- package/dist/api/harvest-id.js +59 -0
- package/dist/api/harvest-id.js.map +1 -0
- package/dist/api/index.d.ts +20 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +10 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/machine-alerts.d.ts +33 -0
- package/dist/api/machine-alerts.d.ts.map +1 -0
- package/dist/api/machine-alerts.js +46 -0
- package/dist/api/machine-alerts.js.map +1 -0
- package/dist/api/machine-device-state-reports.d.ts +24 -0
- package/dist/api/machine-device-state-reports.d.ts.map +1 -0
- package/dist/api/machine-device-state-reports.js +30 -0
- package/dist/api/machine-device-state-reports.js.map +1 -0
- package/dist/api/machine-engine-hours.d.ts +33 -0
- package/dist/api/machine-engine-hours.d.ts.map +1 -0
- package/dist/api/machine-engine-hours.js +46 -0
- package/dist/api/machine-engine-hours.js.map +1 -0
- package/dist/api/machine-hours-of-operation.d.ts +33 -0
- package/dist/api/machine-hours-of-operation.d.ts.map +1 -0
- package/dist/api/machine-hours-of-operation.js +46 -0
- package/dist/api/machine-hours-of-operation.js.map +1 -0
- package/dist/api/machine-locations.d.ts +24 -0
- package/dist/api/machine-locations.d.ts.map +1 -0
- package/dist/api/machine-locations.js +30 -0
- package/dist/api/machine-locations.js.map +1 -0
- package/dist/api/map-layers.d.ts +1 -1
- package/dist/api/map-layers.d.ts.map +1 -1
- package/dist/api/map-layers.js.map +1 -1
- package/dist/api/notifications.d.ts +61 -0
- package/dist/api/notifications.d.ts.map +1 -0
- package/dist/api/notifications.js +93 -0
- package/dist/api/notifications.js.map +1 -0
- package/dist/api/operators.d.ts +2 -2
- package/dist/api/operators.d.ts.map +1 -1
- package/dist/api/operators.js.map +1 -1
- package/dist/api/partnerships.d.ts +55 -0
- package/dist/api/partnerships.d.ts.map +1 -0
- package/dist/api/partnerships.js +75 -0
- package/dist/api/partnerships.js.map +1 -0
- package/dist/api/products.d.ts +4 -4
- package/dist/api/products.d.ts.map +1 -1
- package/dist/api/products.js.map +1 -1
- package/dist/api/webhook.d.ts +3 -2
- package/dist/api/webhook.d.ts.map +1 -1
- package/dist/api/webhook.js.map +1 -1
- package/dist/client.d.ts +34 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +127 -35
- package/dist/client.js.map +1 -1
- package/dist/deere.d.ts +30 -0
- package/dist/deere.d.ts.map +1 -1
- package/dist/deere.js +40 -0
- package/dist/deere.js.map +1 -1
- package/dist/types/generated/aemp.d.ts +255 -0
- package/dist/types/generated/aemp.d.ts.map +1 -0
- package/dist/types/generated/aemp.js +6 -0
- package/dist/types/generated/aemp.js.map +1 -0
- package/dist/types/generated/equipment-measurement.d.ts +380 -0
- package/dist/types/generated/equipment-measurement.d.ts.map +1 -0
- package/dist/types/generated/equipment-measurement.js +6 -0
- package/dist/types/generated/equipment-measurement.js.map +1 -0
- package/dist/types/generated/harvest-id.d.ts +397 -0
- package/dist/types/generated/harvest-id.d.ts.map +1 -0
- package/dist/types/generated/harvest-id.js +6 -0
- package/dist/types/generated/harvest-id.js.map +1 -0
- package/dist/types/generated/index.d.ts +21 -1
- package/dist/types/generated/index.d.ts.map +1 -1
- package/dist/types/generated/index.js +11 -1
- package/dist/types/generated/index.js.map +1 -1
- package/dist/types/generated/machine-alerts.d.ts +321 -0
- package/dist/types/generated/machine-alerts.d.ts.map +1 -0
- package/dist/types/generated/machine-alerts.js +6 -0
- package/dist/types/generated/machine-alerts.js.map +1 -0
- package/dist/types/generated/machine-device-state-reports.d.ts +330 -0
- package/dist/types/generated/machine-device-state-reports.d.ts.map +1 -0
- package/dist/types/generated/machine-device-state-reports.js +6 -0
- package/dist/types/generated/machine-device-state-reports.js.map +1 -0
- package/dist/types/generated/machine-engine-hours.d.ts +123 -0
- package/dist/types/generated/machine-engine-hours.d.ts.map +1 -0
- package/dist/types/generated/machine-engine-hours.js +6 -0
- package/dist/types/generated/machine-engine-hours.js.map +1 -0
- package/dist/types/generated/machine-hours-of-operation.d.ts +130 -0
- package/dist/types/generated/machine-hours-of-operation.d.ts.map +1 -0
- package/dist/types/generated/machine-hours-of-operation.js +6 -0
- package/dist/types/generated/machine-hours-of-operation.js.map +1 -0
- package/dist/types/generated/machine-locations.d.ts +132 -0
- package/dist/types/generated/machine-locations.d.ts.map +1 -0
- package/dist/types/generated/machine-locations.js +6 -0
- package/dist/types/generated/machine-locations.js.map +1 -0
- package/dist/types/generated/notifications.d.ts +398 -0
- package/dist/types/generated/notifications.d.ts.map +1 -0
- package/dist/types/generated/notifications.js +6 -0
- package/dist/types/generated/notifications.js.map +1 -0
- package/dist/types/generated/partnerships.d.ts +388 -0
- package/dist/types/generated/partnerships.d.ts.map +1 -0
- package/dist/types/generated/partnerships.js +6 -0
- package/dist/types/generated/partnerships.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,19 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
12
44
|
pnpm add deere-sdk
|
|
13
|
-
|
|
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
|
|
77
|
+
This SDK requires an OAuth 2.0 access token from John Deere:
|
|
47
78
|
|
|
48
|
-
1. Register
|
|
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
|
|
51
|
-
4. Use the
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
169
|
+
</details>
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary><strong>Fields</strong></summary>
|
|
108
173
|
|
|
109
174
|
```typescript
|
|
110
|
-
// List
|
|
111
|
-
const fields = await deere.fields.
|
|
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
|
|
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', {
|
|
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
|
-
|
|
202
|
+
</details>
|
|
203
|
+
|
|
204
|
+
<details>
|
|
205
|
+
<summary><strong>Farms</strong></summary>
|
|
127
206
|
|
|
128
207
|
```typescript
|
|
129
|
-
// List
|
|
130
|
-
const farms = await deere.farms.
|
|
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
|
-
|
|
133
|
-
const allFarms = await deere.farms.list('org-id', { recordFilter: 'all' });
|
|
226
|
+
</details>
|
|
134
227
|
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
//
|
|
139
|
-
|
|
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
|
-
|
|
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
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
284
|
+
</details>
|
|
285
|
+
|
|
286
|
+
<details>
|
|
287
|
+
<summary><strong>Field Operations</strong></summary>
|
|
159
288
|
|
|
160
289
|
```typescript
|
|
161
|
-
//
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
309
|
+
</details>
|
|
310
|
+
|
|
311
|
+
<details>
|
|
312
|
+
<summary><strong>Machine Data</strong></summary>
|
|
172
313
|
|
|
173
314
|
```typescript
|
|
174
|
-
//
|
|
175
|
-
const
|
|
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
|
-
//
|
|
178
|
-
const
|
|
321
|
+
// Machine alerts
|
|
322
|
+
const alerts = await deere.machineAlerts.list('principal-id');
|
|
179
323
|
|
|
180
|
-
//
|
|
181
|
-
await deere.
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
359
|
+
</details>
|
|
188
360
|
|
|
189
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
|  | All APIs responding with valid specs |
|
|
546
|
+
|  | Some APIs unavailable or returning empty specs |
|
|
547
|
+
|  | 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
|
|
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
|
-
|
|
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>
|