Unofficial TypeScript SDK for John Deere Operations Center API
Installation • Quick Start • API Reference • API Status
- 28 APIs with 146 operations — Full coverage of John Deere agricultural APIs
- Fully typed — Auto-generated TypeScript types from OpenAPI specs
- Auto-pagination —
listAll()methods handle pagination automatically - HAL support — Built-in link following for John Deere's HAL-style responses
- Automatic retries — Exponential backoff with jitter for transient failures
- Daily health checks — Automated monitoring of API availability
npm install deere-sdkpnpm add deere-sdkyarn add deere-sdkimport {Deere} from 'deere-sdk';
const deere = new Deere({
accessToken: 'your-oauth-access-token',
environment: 'sandbox', // or 'production'
});
// List all organizations
const orgs = await deere.organizations.listAll();
// Get fields for an organization
const fields = await deere.fields.listAll(orgs[0].id);
// Get equipment
const equipment = await deere.equipment.get();This SDK requires an OAuth 2.0 access token from John Deere:
- Register at developer.deere.com
- Create an application and get your client ID/secret
- Implement the OAuth 2.0 authorization code flow
- Use the access token in the SDK
OAuth Scopes
| Scope | Description |
|---|---|
ag1 |
Read access to agricultural data |
ag2 |
Write access to agricultural data |
ag3 |
Additional agricultural data access |
offline_access |
Refresh token support |
Environments
| Environment | URL | Use Case |
|---|---|---|
production |
api.deere.com | Live data |
sandbox |
sandboxapi.deere.com | Development |
partner |
partnerapi.deere.com | Partner integrations |
cert |
apicert.deere.com | Certification |
qa |
apiqa.tal.deere.com | QA testing |
| API | Property | Methods | Description |
|---|---|---|---|
| Organizations | deere.organizations |
5 | Organization management |
| Fields | deere.fields |
8 | Field CRUD and boundaries |
| Farms | deere.farms |
8 | Farm management |
| Boundaries | deere.boundaries |
8 | Field boundary management |
| Clients | deere.clients |
8 | Customer management |
| Equipment | deere.equipment |
16 | Machines and implements |
| Field Operations | deere.fieldOperations |
4 | Harvests, plantings, applications |
| Crop Types | deere.cropTypes |
5 | Crop type catalog |
| Products | deere.products |
10 | Seeds and chemicals catalog |
| Map Layers | deere.mapLayers |
5 | Map layer management |
| Files | deere.files |
6 | File management |
| Flags | deere.flags |
7 | Field flags/markers |
| Guidance Lines | deere.guidanceLines |
5 | GPS guidance lines |
| Operators | deere.operators |
7 | Machine operator management |
| Users | deere.users |
1 | User information |
| Assets | deere.assets |
9 | Asset tracking |
| Webhooks | deere.webhook |
5 | Event subscriptions |
| Connections | deere.connectionManagement |
4 | OAuth connections |
| API | Property | Methods | Description |
|---|---|---|---|
| Machine Locations | deere.machineLocations |
1 | GPS location history |
| Machine Alerts | deere.machineAlerts |
2 | DTC alerts |
| Engine Hours | deere.machineEngineHours |
2 | Engine hours tracking |
| Hours of Operation | deere.machineHoursOfOperation |
2 | On/off duration |
| Device State | deere.machineDeviceStateReports |
1 | Terminal state reports |
| Notifications | deere.notifications |
5 | Push notifications |
| Harvest ID | deere.harvestId |
3 | Cotton module data |
| AEMP | deere.aemp |
1 | ISO 15143-3 fleet data |
| Equipment Measurement | deere.equipmentMeasurement |
1 | Third-party measurements |
| Partnerships | deere.partnerships |
7 | Organization partnerships |
Organizations
// List all organizations
const orgs = await deere.organizations.list();
const allOrgs = await deere.organizations.listAll();
// Get a specific organization
const org = await deere.organizations.get('org-id');
// List users in an organization
const users = await deere.organizations.listUsers('org-id');Fields
// List fields in an organization
const fields = await deere.fields.list('org-id');
const allFields = await deere.fields.listAll('org-id');
// Filter fields
const filtered = await deere.fields.list('org-id', {
farmName: 'North Farm',
recordFilter: 'AVAILABLE'
});
// Get a specific field
const field = await deere.fields.get('org-id', 'field-id');
// Create a field
await deere.fields.create('org-id', {
name: 'North Field',
farmName: 'Smith Farm',
clientName: 'John Smith'
});
// Update a field
await deere.fields.update('org-id', 'field-id', {name: 'Updated Name'});
// Delete a field
await deere.fields.delete('org-id', 'field-id');Farms
// List farms
const farms = await deere.farms.list('org-id');
const allFarms = await deere.farms.listAll('org-id');
// Include archived
const all = await deere.farms.list('org-id', {recordFilter: 'all'});
// CRUD operations
const farm = await deere.farms.get('org-id', 'farm-id');
await deere.farms.create('org-id', {name: 'North Farm'});
await deere.farms.update('org-id', 'farm-id', {name: 'Updated'});
await deere.farms.delete('org-id', 'farm-id');
// Related resources
const clients = await deere.farms.listClients('org-id', 'farm-id');
const fields = await deere.farms.listFields('org-id', 'farm-id');Boundaries
// List boundaries
const boundaries = await deere.boundaries.list('org-id');
const fieldBoundaries = await deere.boundaries.listBoundaries('org-id', 'field-id');
// Get specific boundary
const boundary = await deere.boundaries.getBoundaries('org-id', 'field-id', 'boundary-id');
// Generate from field operation
const generated = await deere.boundaries.get('operation-id');
// Create boundary
await deere.boundaries.create('org-id', 'field-id', {
name: 'Main Boundary',
active: true,
multipolygons: [/* GeoJSON */]
});
// Update/Delete
await deere.boundaries.update('org-id', 'field-id', 'boundary-id', {name: 'New Name'});
await deere.boundaries.delete('org-id', 'field-id', 'boundary-id');Equipment
// Get all equipment
const equipment = await deere.equipment.get();
// Filter equipment
const filtered = await deere.equipment.get({
organizationIds: [123],
categories: 'Machine',
capableOf: 'Connectivity'
});
// Get equipment details
const machine = await deere.equipment.getEquipment('equipment-id');
// CRUD
await deere.equipment.create('org-id', {type: 'Machine', name: 'Tractor 1'});
await deere.equipment.update('equipment-id', {name: 'Updated'});
await deere.equipment.delete('equipment-id');
// Reference data
const makes = await deere.equipment.list();
const types = await deere.equipment.listEquipmenttypes();
const models = await deere.equipment.listEquipmentmodels({equipmentModelName: '9RX*'});Field Operations
// List field operations
const ops = await deere.fieldOperations.list('org-id', 'field-id');
// Filter by type and season
const harvests = await deere.fieldOperations.list('org-id', 'field-id', {
cropSeason: '2026',
fieldOperationType: 'harvest'
});
// Get operation details
const op = await deere.fieldOperations.get('operation-id');
// Download shapefile
const shapefile = await deere.fieldOperations.getFieldops('operation-id', {
shapeType: 'Polygon',
resolution: 'EachSection'
});Machine Data
// Machine locations
const locations = await deere.machineLocations.get('principal-id', {
startDate: '2026-01-01T00:00:00Z',
endDate: '2026-01-31T23:59:59Z'
});
// Machine alerts
const alerts = await deere.machineAlerts.list('principal-id');
// Engine hours
const hours = await deere.machineEngineHours.list('principal-id', {lastKnown: true});
// Hours of operation
const opHours = await deere.machineHoursOfOperation.list('principal-id');
// Device state reports
const state = await deere.machineDeviceStateReports.get('principal-id');Notifications
// List notifications
const notifications = await deere.notifications.list('org-id');
// Filter by severity
const critical = await deere.notifications.list('org-id', {
severities: 'HIGH,CRITICAL'
});
// Create notification
await deere.notifications.create({
sourceEvent: 'my-app-event-123',
title: 'Action Required',
message: 'Please review the prescription map'
});
// Delete notification
await deere.notifications.delete('source-event-id');Assets
// List assets
const assets = await deere.assets.listAll('org-id');
// Get asset
const asset = await deere.assets.get('asset-id');
// Create asset
await deere.assets.create('org-id', {
title: 'Fuel Tank #1',
assetCategory: 'DEVICE',
assetType: 'SENSOR'
});
// Asset locations
const locations = await deere.assets.listLocations('asset-id', {
startDate: '2026-01-01T00:00:00Z',
endDate: '2026-01-31T23:59:59Z'
});
await deere.assets.createLocations('asset-id', {
timestamp: '2026-01-15T12:00:00Z',
geometry: {type: 'Point', coordinates: [-93.5, 42.5]}
});Webhooks
// List subscriptions
const subs = await deere.webhook.listAll();
// Create subscription
await deere.webhook.create({
clientKey: 'your-client-key',
eventTypeId: 'equipment-status',
callbackUrl: 'https://your-server.com/webhook'
});
// Update subscription
await deere.webhook.update('subscription-id', {
callbackUrl: 'https://new-server.com/webhook'
});Partnerships
// List partnerships
const partnerships = await deere.partnerships.listAll();
// Create partnership request
await deere.partnerships.create({
toOrganizationId: 'partner-org-id',
message: 'Request to share data'
});
// Get/delete partnership
const partnership = await deere.partnerships.get('token');
await deere.partnerships.delete('token');
// Permissions
const perms = await deere.partnerships.listPermissions('token');
await deere.partnerships.createPermissions('token', {
permissionType: 'ViewData',
enabled: true
});For custom endpoints or advanced use cases:
import {DeereClient} from 'deere-sdk';
const client = new DeereClient({
accessToken: 'your-token',
environment: 'sandbox',
timeout: 30000, // Request timeout in ms (default: 30000)
maxRetries: 3, // Retry attempts (default: 3, set to 0 to disable)
});
// Raw requests
const response = await client.get<CustomType>('/some/endpoint');
const created = await client.post('/some/endpoint', {data: 'value'});
// Follow HAL links
const nextPage = await client.followLink(response.links[0]);
// Automatic pagination
for await (const items of client.paginate('/large/collection')) {
console.log(items);
}The SDK automatically retries failed requests with exponential backoff and jitter:
| Error Type | Retried? | Notes |
|---|---|---|
429 Rate Limit |
Yes | Respects Retry-After header |
500, 502, 503, 504 |
Yes | Server errors |
| Network failures | Yes | Connection issues |
| Timeouts | Yes | Request took too long |
401, 403 Auth errors |
No | Refresh your token |
400, 404, 422 |
No | Fix your request |
Default behavior: 3 retries with exponential backoff (delays of ~1s, ~2s, ~4s with jitter).
// Customize retry behavior
const deere = new Deere({
accessToken: 'your-token',
maxRetries: 5, // More retries (default: 3)
});
// Disable retries entirely
const deere = new Deere({
accessToken: 'your-token',
maxRetries: 0,
});import {DeereError, RateLimitError, AuthError} from 'deere-sdk';
try {
const fields = await deere.fields.listAll('org-id');
} catch (error) {
if (error instanceof RateLimitError) {
// Only thrown after all retries exhausted
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof AuthError) {
// Never retried - refresh your token
console.log('Token expired - refresh required');
} else if (error instanceof DeereError) {
console.log(`API error: ${error.status} ${error.message}`);
}
}Access auto-generated types from OpenAPI specs:
import {Types} from 'deere-sdk';
type Farm = Types.Farms.components['schemas']['GetFarm'];
type Field = Types.Fields.components['schemas']['FieldsResponse'];
type Equipment = Types.Equipment.components['schemas']['equipment-model'];This SDK includes automated daily health checks to monitor John Deere API availability.
| Status | Meaning |
|---|---|
| All APIs responding with valid specs | |
| Some APIs unavailable or returning empty specs | |
| Major API outage detected |
APIs Without Public Specs
These APIs are listed on John Deere's portal but don't provide public OpenAPI specs:
| API | Notes |
|---|---|
work-plans |
Listed but returns empty spec |
retrieve-warranty-information |
Dealer-only |
retrieve-pip |
Dealer-only |
valid-pin |
Dealer-only |
Additional John Deere APIs
John Deere offers 40+ additional APIs not included in this SDK:
- Dealer Solutions (32 APIs) — Warranty, quotes, service for dealers
- Financial (4 APIs) — Merchant transactions, credit applications
- Supply Chain (1 API) — Supplier quoting
These target dealers rather than farmers. See developer.deere.com for full documentation.
Contributions are welcome! Please read the contributing guidelines before submitting a PR.
# Clone the repo
git clone https://github.com/ProductOfAmerica/deere-sdk.git
# Install dependencies
pnpm install
# Fetch specs and generate SDK
pnpm generate
# Build
pnpm build
# Run tests
pnpm testNormal development – just commit and push as usual. No release happens:
git add -A
git commit -m "fix: whatever you fixed"
git pushWhen ready to release a new version:
# 1. Update CHANGELOG.md with what changed
# 2. Bump version (auto-commits + auto-creates tag)
npm version patch # or: minor, major
# 3. Push commit and tag together
git push --follow-tagsCI sees the tag → creates GitHub Release → publishes to npm.
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.
John Deere, Operations Center, and the leaping deer logo are trademarks of Deere & Company.
MIT © 2026
Built with TypeScript and auto-generated from John Deere OpenAPI specs