samsara-api 4.0.0__py3-none-any.whl → 4.0.1__py3-none-any.whl
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.
- samsara/core/client_wrapper.py +2 -2
- samsara_api-4.0.1.dist-info/METADATA +670 -0
- {samsara_api-4.0.0.dist-info → samsara_api-4.0.1.dist-info}/RECORD +5 -5
- samsara_api-4.0.0.dist-info/METADATA +0 -238
- {samsara_api-4.0.0.dist-info → samsara_api-4.0.1.dist-info}/LICENSE +0 -0
- {samsara_api-4.0.0.dist-info → samsara_api-4.0.1.dist-info}/WHEEL +0 -0
samsara/core/client_wrapper.py
CHANGED
|
@@ -22,10 +22,10 @@ class BaseClientWrapper:
|
|
|
22
22
|
|
|
23
23
|
def get_headers(self) -> typing.Dict[str, str]:
|
|
24
24
|
headers: typing.Dict[str, str] = {
|
|
25
|
-
"User-Agent": "samsara-api/4.0.
|
|
25
|
+
"User-Agent": "samsara-api/4.0.1",
|
|
26
26
|
"X-Fern-Language": "Python",
|
|
27
27
|
"X-Fern-SDK-Name": "samsara-api",
|
|
28
|
-
"X-Fern-SDK-Version": "4.0.
|
|
28
|
+
"X-Fern-SDK-Version": "4.0.1",
|
|
29
29
|
**(self.get_custom_headers() or {}),
|
|
30
30
|
}
|
|
31
31
|
token = self._get_token()
|
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: samsara-api
|
|
3
|
+
Version: 4.0.1
|
|
4
|
+
Summary:
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.8,<4.0
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: MacOS
|
|
10
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Operating System :: POSIX
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Dist: httpx (>=0.21.2)
|
|
24
|
+
Requires-Dist: pydantic (>=1.9.2)
|
|
25
|
+
Requires-Dist: pydantic-core (>=2.18.2)
|
|
26
|
+
Requires-Dist: typing_extensions (>=4.0.0)
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Samsara Python Library
|
|
30
|
+
|
|
31
|
+
[](https://buildwithfern.com?utm_source=github&utm_medium=github&utm_campaign=readme&utm_source=https%3A%2F%2Fgithub.com%2Fsamsarahq%2Fsamsara-python-sdk)
|
|
32
|
+
[](https://pypi.python.org/pypi/samsara-api)
|
|
33
|
+
|
|
34
|
+
The Samsara Python library provides convenient access to the Samsara API from Python.
|
|
35
|
+
|
|
36
|
+
## Table of Contents
|
|
37
|
+
|
|
38
|
+
- [Requirements](#requirements)
|
|
39
|
+
- [Documentation](#documentation)
|
|
40
|
+
- [Installation](#installation)
|
|
41
|
+
- [Quick Start](#quick-start)
|
|
42
|
+
- [Features](#features)
|
|
43
|
+
- [Usage](#usage)
|
|
44
|
+
- [Basic Usage](#basic-usage)
|
|
45
|
+
- [Async Client](#async-client)
|
|
46
|
+
- [Exception Handling](#exception-handling)
|
|
47
|
+
- [Pagination](#pagination)
|
|
48
|
+
- [Webhook Signature Verification](#webhook-signature-verification)
|
|
49
|
+
- [Advanced](#advanced)
|
|
50
|
+
- [Access Raw Response Data](#access-raw-response-data)
|
|
51
|
+
- [Retries](#retries)
|
|
52
|
+
- [Timeouts](#timeouts)
|
|
53
|
+
- [Custom Client](#custom-client)
|
|
54
|
+
- [AWS Lambda / Serverless](#aws-lambda--serverless)
|
|
55
|
+
- [Examples](#examples)
|
|
56
|
+
- [Troubleshooting](#troubleshooting)
|
|
57
|
+
- [Contributing](#contributing)
|
|
58
|
+
|
|
59
|
+
## Requirements
|
|
60
|
+
|
|
61
|
+
- Python 3.7+
|
|
62
|
+
- A Samsara account with API access
|
|
63
|
+
- An API token (available from your [Samsara Dashboard](https://cloud.samsara.com/) > Settings > Developer > API Tokens)
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
API reference documentation is available [here](https://developers.samsara.com/reference/overview).
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
pip install samsara-api
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
Get started with the Samsara SDK in just a few lines of code:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from samsara import Samsara
|
|
81
|
+
|
|
82
|
+
# Initialize the client with your API token
|
|
83
|
+
client = Samsara(
|
|
84
|
+
token="YOUR_TOKEN", # Get your token at https://cloud.samsara.com/settings/api-tokens
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Get your organization information
|
|
88
|
+
org_info = client.organization_info.get_organization_info()
|
|
89
|
+
print(f"Organization: {org_info.data.name}")
|
|
90
|
+
|
|
91
|
+
# List all vehicles in your fleet
|
|
92
|
+
vehicles = client.vehicles.list()
|
|
93
|
+
for vehicle in vehicles:
|
|
94
|
+
print(f"Vehicle: {vehicle.name} (ID: {vehicle.id})")
|
|
95
|
+
|
|
96
|
+
# Get specific vehicle details
|
|
97
|
+
vehicle = client.vehicles.get(id="YOUR_VEHICLE_ID")
|
|
98
|
+
print(f"Vehicle VIN: {vehicle.data.vin}")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
For more detailed examples, see the [Examples](#examples) section.
|
|
102
|
+
|
|
103
|
+
## Features
|
|
104
|
+
|
|
105
|
+
The Samsara Python SDK provides:
|
|
106
|
+
|
|
107
|
+
- **Type Safety**: Full type hints for better IDE support and autocomplete
|
|
108
|
+
- **Automatic Pagination**: Seamlessly iterate through large result sets
|
|
109
|
+
- **Async Support**: Both synchronous and asynchronous clients
|
|
110
|
+
- **Smart Retries**: Automatic retry logic with exponential backoff
|
|
111
|
+
- **Error Handling**: Comprehensive exception handling for all API errors
|
|
112
|
+
- **Webhook Verification**: Built-in utilities for webhook signature validation
|
|
113
|
+
- **Raw Response Access**: Get headers and raw response data when needed
|
|
114
|
+
- **Flexible Configuration**: Customize timeouts, retries, and HTTP clients
|
|
115
|
+
|
|
116
|
+
## Reference
|
|
117
|
+
|
|
118
|
+
A full reference for this library is available [here](https://github.com/samsarahq/samsara-python/blob/HEAD/./reference.md).
|
|
119
|
+
|
|
120
|
+
## Usage
|
|
121
|
+
|
|
122
|
+
### Basic Usage
|
|
123
|
+
|
|
124
|
+
Instantiate and use the client with the following:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from samsara import Samsara
|
|
128
|
+
|
|
129
|
+
client = Samsara(
|
|
130
|
+
token="YOUR_TOKEN",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# The SDK handles pagination automatically - just iterate through results
|
|
134
|
+
response = client.vehicles.list()
|
|
135
|
+
for item in response:
|
|
136
|
+
print(item) # Process each vehicle stat
|
|
137
|
+
|
|
138
|
+
# Alternatively, you can paginate page-by-page for more control
|
|
139
|
+
for page in response.iter_pages():
|
|
140
|
+
print(f"Processing page with {len(page.items)} items")
|
|
141
|
+
for item in page.items:
|
|
142
|
+
print(item)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Async Client
|
|
146
|
+
|
|
147
|
+
The SDK also exports an `async` client so that you can make non-blocking calls to our API.
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
import asyncio
|
|
151
|
+
from samsara import AsyncSamsara
|
|
152
|
+
|
|
153
|
+
client = AsyncSamsara(
|
|
154
|
+
token="YOUR_TOKEN",
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
async def main() -> None:
|
|
159
|
+
# The SDK handles pagination automatically - just iterate through results
|
|
160
|
+
response = await client.vehicles.list()
|
|
161
|
+
async for item in response:
|
|
162
|
+
print(item) # Process each vehicle stat
|
|
163
|
+
|
|
164
|
+
# Alternatively, you can paginate page-by-page for more control
|
|
165
|
+
async for page in response.iter_pages():
|
|
166
|
+
print(f"Processing page with {len(page.items)} items")
|
|
167
|
+
for item in page.items:
|
|
168
|
+
print(item)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
asyncio.run(main())
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Exception Handling
|
|
175
|
+
|
|
176
|
+
When the API returns a non-success status code (4xx or 5xx response), a subclass of the following error
|
|
177
|
+
will be thrown.
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from samsara.core.api_error import ApiError
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
client.vehicles.list()
|
|
184
|
+
except ApiError as e:
|
|
185
|
+
print(f"API Error: {e.status_code}")
|
|
186
|
+
print(f"Response: {e.body}")
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Pagination
|
|
190
|
+
|
|
191
|
+
Paginated requests will return a `SyncPager` or `AsyncPager`, which can be used as iterators for the underlying objects.
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from samsara import Samsara
|
|
195
|
+
|
|
196
|
+
client = Samsara(
|
|
197
|
+
token="YOUR_TOKEN",
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Automatic pagination - SDK fetches pages as needed
|
|
201
|
+
response = client.addresses.list()
|
|
202
|
+
for address in response:
|
|
203
|
+
print(f"Address: {address.formatted_address}")
|
|
204
|
+
|
|
205
|
+
# Manual page-by-page iteration for more control
|
|
206
|
+
response = client.addresses.list()
|
|
207
|
+
for page in response.iter_pages():
|
|
208
|
+
print(f"Page contains {len(page.items)} addresses")
|
|
209
|
+
for address in page.items:
|
|
210
|
+
print(f" - {address.formatted_address}")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Webhook Signature Verification
|
|
214
|
+
|
|
215
|
+
The SDK provides utility methods that allow you to verify webhook signatures and ensure
|
|
216
|
+
that all webhook events originate from Samsara. This is a critical security measure to validate
|
|
217
|
+
that incoming webhook requests are authentic.
|
|
218
|
+
|
|
219
|
+
### Setting Up Webhooks
|
|
220
|
+
|
|
221
|
+
1. Configure webhooks in your [Samsara Dashboard](https://cloud.samsara.com/) > Settings > Developer > Webhooks
|
|
222
|
+
2. Note your webhook signature key (used for verification)
|
|
223
|
+
3. Specify the notification URL where Samsara will send events
|
|
224
|
+
|
|
225
|
+
### Verifying Webhook Signatures
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from samsara.utils.webhooks_helper import verify_signature
|
|
229
|
+
|
|
230
|
+
# In your webhook endpoint handler (e.g., Flask, FastAPI)
|
|
231
|
+
def webhook_handler(request):
|
|
232
|
+
# Verify the webhook signature
|
|
233
|
+
is_valid = verify_signature(
|
|
234
|
+
request_body=request.body, # Raw request body as string
|
|
235
|
+
signature_header=request.headers['x-samsara-signature'],
|
|
236
|
+
signature_key="YOUR_SIGNATURE_KEY", # From Samsara Dashboard
|
|
237
|
+
notification_url="https://example.com/webhook", # Your webhook URL
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
if not is_valid:
|
|
241
|
+
return {"error": "Invalid signature"}, 401
|
|
242
|
+
|
|
243
|
+
# Process the webhook event
|
|
244
|
+
event_data = request.json()
|
|
245
|
+
print(f"Received event: {event_data['eventType']}")
|
|
246
|
+
|
|
247
|
+
return {"status": "success"}, 200
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Example with Flask
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from flask import Flask, request, jsonify
|
|
254
|
+
from samsara.utils.webhooks_helper import verify_signature
|
|
255
|
+
|
|
256
|
+
app = Flask(__name__)
|
|
257
|
+
|
|
258
|
+
@app.route('/webhook', methods=['POST'])
|
|
259
|
+
def samsara_webhook():
|
|
260
|
+
# Verify signature
|
|
261
|
+
is_valid = verify_signature(
|
|
262
|
+
request_body=request.get_data(as_text=True),
|
|
263
|
+
signature_header=request.headers.get('x-samsara-signature'),
|
|
264
|
+
signature_key="YOUR_SIGNATURE_KEY",
|
|
265
|
+
notification_url="https://yourdomain.com/webhook",
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
if not is_valid:
|
|
269
|
+
return jsonify({"error": "Invalid signature"}), 401
|
|
270
|
+
|
|
271
|
+
# Handle the event
|
|
272
|
+
event = request.get_json()
|
|
273
|
+
print(f"Event type: {event.get('eventType')}")
|
|
274
|
+
|
|
275
|
+
return jsonify({"status": "received"}), 200
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Advanced
|
|
279
|
+
|
|
280
|
+
### Access Raw Response Data
|
|
281
|
+
|
|
282
|
+
The SDK provides access to raw response data, including headers, through the `.with_raw_response` property.
|
|
283
|
+
The `.with_raw_response` property returns a "raw" client that can be used to access the `.headers` and `.data` attributes.
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from samsara import Samsara
|
|
287
|
+
|
|
288
|
+
client = Samsara(
|
|
289
|
+
...,
|
|
290
|
+
)
|
|
291
|
+
response = client.vehicles.with_raw_response.list(...)
|
|
292
|
+
print(response.headers) # access the response headers
|
|
293
|
+
print(response.data) # access the underlying object
|
|
294
|
+
pager = client.addresses.list(...)
|
|
295
|
+
print(pager.response.headers) # access the response headers for the first page
|
|
296
|
+
for item in pager:
|
|
297
|
+
print(item) # access the underlying object(s)
|
|
298
|
+
for page in pager.iter_pages():
|
|
299
|
+
print(page.response.headers) # access the response headers for each page
|
|
300
|
+
for item in page:
|
|
301
|
+
print(item) # access the underlying object(s)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Retries
|
|
305
|
+
|
|
306
|
+
The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long
|
|
307
|
+
as the request is deemed retryable and the number of retry attempts has not grown larger than the configured
|
|
308
|
+
retry limit (default: 2).
|
|
309
|
+
|
|
310
|
+
A request is deemed retryable when any of the following HTTP status codes is returned:
|
|
311
|
+
|
|
312
|
+
- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)
|
|
313
|
+
- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)
|
|
314
|
+
- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)
|
|
315
|
+
|
|
316
|
+
Use the `max_retries` request option to configure this behavior.
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
client.vehicles.list(..., request_options={
|
|
320
|
+
"max_retries": 1
|
|
321
|
+
})
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Timeouts
|
|
325
|
+
|
|
326
|
+
The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level.
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
|
|
330
|
+
from samsara import Samsara
|
|
331
|
+
|
|
332
|
+
client = Samsara(
|
|
333
|
+
...,
|
|
334
|
+
timeout=20.0,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
# Override timeout for a specific method
|
|
339
|
+
client.vehicles.list(..., request_options={
|
|
340
|
+
"timeout_in_seconds": 1
|
|
341
|
+
})
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Custom Client
|
|
345
|
+
|
|
346
|
+
You can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies
|
|
347
|
+
and transports.
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
import httpx
|
|
351
|
+
from samsara import Samsara
|
|
352
|
+
|
|
353
|
+
client = Samsara(
|
|
354
|
+
...,
|
|
355
|
+
httpx_client=httpx.Client(
|
|
356
|
+
proxies="http://my.test.proxy.example.com",
|
|
357
|
+
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
|
|
358
|
+
),
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Examples
|
|
363
|
+
|
|
364
|
+
### Getting Vehicle Locations
|
|
365
|
+
|
|
366
|
+
Track your fleet in real-time by fetching current vehicle locations:
|
|
367
|
+
|
|
368
|
+
```python
|
|
369
|
+
from samsara import Samsara
|
|
370
|
+
from datetime import datetime, timedelta
|
|
371
|
+
|
|
372
|
+
client = Samsara(token="YOUR_TOKEN")
|
|
373
|
+
|
|
374
|
+
# Get current locations for all vehicles
|
|
375
|
+
locations = client.vehicle_locations.get_vehicle_locations()
|
|
376
|
+
for vehicle_data in locations.data:
|
|
377
|
+
print(f"Vehicle {vehicle_data.name}: {vehicle_data.location.latitude}, {vehicle_data.location.longitude}")
|
|
378
|
+
print(f" Speed: {vehicle_data.location.speed} mph")
|
|
379
|
+
print(f" Time: {vehicle_data.location.time}")
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Monitoring Driver Hours of Service
|
|
383
|
+
|
|
384
|
+
Check driver HOS status to ensure compliance:
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from samsara import Samsara
|
|
388
|
+
|
|
389
|
+
client = Samsara(token="YOUR_TOKEN")
|
|
390
|
+
|
|
391
|
+
# List all drivers
|
|
392
|
+
drivers = client.drivers.list()
|
|
393
|
+
for driver in drivers:
|
|
394
|
+
print(f"Driver: {driver.name}")
|
|
395
|
+
|
|
396
|
+
# Get HOS logs for a specific driver
|
|
397
|
+
hos_logs = client.hours_of_service.get_hos_logs(driver_ids=[driver.id])
|
|
398
|
+
for hos_log in hos_logs.data:
|
|
399
|
+
for log in hos_log.hos_logs:
|
|
400
|
+
print(f" Status: {log.hos_status_type} at {log.log_start_time}")
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Managing Vehicle Maintenance
|
|
404
|
+
|
|
405
|
+
Track vehicle health and maintenance schedules:
|
|
406
|
+
|
|
407
|
+
```python
|
|
408
|
+
from samsara import Samsara
|
|
409
|
+
|
|
410
|
+
client = Samsara(token="YOUR_TOKEN")
|
|
411
|
+
|
|
412
|
+
# Get vehicle stats including engine hours and odometer
|
|
413
|
+
stats = client.vehicles.list()
|
|
414
|
+
for stat in stats:
|
|
415
|
+
print(f"Vehicle: {stat.name}")
|
|
416
|
+
print(f" Engine Hours: {stat.engine_hours}")
|
|
417
|
+
print(f" Odometer: {stat.odometer_meters / 1609.34:.1f} miles")
|
|
418
|
+
|
|
419
|
+
# List maintenance issues
|
|
420
|
+
issues = client.issues.list()
|
|
421
|
+
for issue in issues:
|
|
422
|
+
print(f"Issue: {issue.type} - {issue.description}")
|
|
423
|
+
print(f" Vehicle: {issue.vehicle.name}")
|
|
424
|
+
print(f" Severity: {issue.severity}")
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Retrieving Historical Trip Data
|
|
428
|
+
|
|
429
|
+
Analyze past trips for reporting and optimization:
|
|
430
|
+
|
|
431
|
+
```python
|
|
432
|
+
from samsara import Samsara
|
|
433
|
+
from datetime import datetime, timedelta
|
|
434
|
+
|
|
435
|
+
client = Samsara(token="YOUR_TOKEN")
|
|
436
|
+
|
|
437
|
+
# Get trips from the last 7 days
|
|
438
|
+
end_time = datetime.now()
|
|
439
|
+
start_time = end_time - timedelta(days=7)
|
|
440
|
+
|
|
441
|
+
trips = client.trips.list(
|
|
442
|
+
start_time=start_time.isoformat(),
|
|
443
|
+
end_time=end_time.isoformat()
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
total_distance = 0
|
|
447
|
+
for trip in trips:
|
|
448
|
+
print(f"Trip: {trip.start_location} -> {trip.end_location}")
|
|
449
|
+
print(f" Distance: {trip.distance_meters / 1609.34:.1f} miles")
|
|
450
|
+
print(f" Duration: {trip.duration_ms / 60000:.1f} minutes")
|
|
451
|
+
total_distance += trip.distance_meters
|
|
452
|
+
|
|
453
|
+
print(f"\nTotal distance traveled: {total_distance / 1609.34:.1f} miles")
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Working with Vehicle Groups (Tags)
|
|
457
|
+
|
|
458
|
+
Organize and filter your fleet using tags:
|
|
459
|
+
|
|
460
|
+
```python
|
|
461
|
+
from samsara import Samsara
|
|
462
|
+
|
|
463
|
+
client = Samsara(token="YOUR_TOKEN")
|
|
464
|
+
|
|
465
|
+
# List all tags (vehicle groups)
|
|
466
|
+
tags = client.tags.list()
|
|
467
|
+
for tag in tags:
|
|
468
|
+
print(f"Tag: {tag.name}")
|
|
469
|
+
print(f" Vehicles: {len(tag.vehicles)}")
|
|
470
|
+
|
|
471
|
+
# Get vehicles with a specific tag
|
|
472
|
+
tag_id = "YOUR_TAG_ID"
|
|
473
|
+
vehicles = client.vehicles.list(tag_ids=[tag_id])
|
|
474
|
+
for vehicle in vehicles:
|
|
475
|
+
print(f" - {vehicle.name}")
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Batch Operations with Async Client
|
|
479
|
+
|
|
480
|
+
Process multiple API calls concurrently for better performance:
|
|
481
|
+
|
|
482
|
+
```python
|
|
483
|
+
import asyncio
|
|
484
|
+
from samsara import AsyncSamsara
|
|
485
|
+
|
|
486
|
+
async def get_fleet_summary():
|
|
487
|
+
client = AsyncSamsara(token="YOUR_TOKEN")
|
|
488
|
+
|
|
489
|
+
# Fetch multiple resources concurrently
|
|
490
|
+
vehicles_task = client.vehicles.list()
|
|
491
|
+
drivers_task = client.drivers.list()
|
|
492
|
+
assets_task = client.assets.list()
|
|
493
|
+
|
|
494
|
+
# Wait for all requests to complete
|
|
495
|
+
vehicles = []
|
|
496
|
+
async for vehicle in vehicles_task:
|
|
497
|
+
vehicles.append(vehicle)
|
|
498
|
+
drivers = []
|
|
499
|
+
async for driver in drivers_task:
|
|
500
|
+
drivers.append(driver)
|
|
501
|
+
assets = []
|
|
502
|
+
async for asset in assets_task:
|
|
503
|
+
assets.append(asset)
|
|
504
|
+
|
|
505
|
+
print(f"Fleet Summary:")
|
|
506
|
+
print(f" Vehicles: {len(vehicles)}")
|
|
507
|
+
print(f" Drivers: {len(drivers)}")
|
|
508
|
+
print(f" Assets: {len(assets)}")
|
|
509
|
+
|
|
510
|
+
asyncio.run(get_fleet_summary())
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## AWS Lambda / Serverless
|
|
514
|
+
|
|
515
|
+
The Samsara SDK works seamlessly in serverless environments like AWS Lambda. Here's how to set it up:
|
|
516
|
+
|
|
517
|
+
### Creating a Lambda Layer
|
|
518
|
+
|
|
519
|
+
The SDK can be packaged as a Lambda Layer for reuse across multiple functions:
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
# Create a directory for the layer
|
|
523
|
+
mkdir -p python/lib/python3.9/site-packages
|
|
524
|
+
|
|
525
|
+
# Install the SDK and dependencies
|
|
526
|
+
pip install samsara-api -t python/lib/python3.9/site-packages
|
|
527
|
+
|
|
528
|
+
# Create a zip file
|
|
529
|
+
zip -r samsara-layer.zip python
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Lambda Function Example
|
|
533
|
+
|
|
534
|
+
```python
|
|
535
|
+
import json
|
|
536
|
+
from samsara import Samsara
|
|
537
|
+
|
|
538
|
+
def lambda_handler(event, context):
|
|
539
|
+
# Initialize client (API token from environment variable)
|
|
540
|
+
import os
|
|
541
|
+
client = Samsara(token=os.environ['SAMSARA_API_TOKEN'])
|
|
542
|
+
|
|
543
|
+
# Get vehicle locations
|
|
544
|
+
locations = client.vehicle_locations.list()
|
|
545
|
+
|
|
546
|
+
result = []
|
|
547
|
+
for location in locations:
|
|
548
|
+
result.append({
|
|
549
|
+
'name': location.name,
|
|
550
|
+
'latitude': location.latitude,
|
|
551
|
+
'longitude': location.longitude,
|
|
552
|
+
'speed': location.speed_miles_per_hour
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
return {
|
|
556
|
+
'statusCode': 200,
|
|
557
|
+
'body': json.dumps(result)
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Lambda Configuration Tips
|
|
562
|
+
|
|
563
|
+
- **Memory**: Allocate at least 256 MB for optimal performance
|
|
564
|
+
- **Timeout**: Set timeout to 30+ seconds for API calls with pagination
|
|
565
|
+
- **Environment Variables**: Store your API token in `SAMSARA_API_TOKEN`
|
|
566
|
+
- **VPC**: Not required unless you need to access private resources
|
|
567
|
+
- **Cold Starts**: The SDK initializes quickly, but consider using provisioned concurrency for time-sensitive applications
|
|
568
|
+
|
|
569
|
+
## Troubleshooting
|
|
570
|
+
|
|
571
|
+
### Authentication Errors
|
|
572
|
+
|
|
573
|
+
**Problem**: `401 Unauthorized` errors
|
|
574
|
+
|
|
575
|
+
**Solution**:
|
|
576
|
+
- Verify your API token is correct
|
|
577
|
+
- Check that the token hasn't expired
|
|
578
|
+
- Ensure the token has the necessary permissions for the endpoints you're accessing
|
|
579
|
+
- Get your token from [Samsara Dashboard → API Tokens](https://cloud.samsara.com/settings/api-tokens)
|
|
580
|
+
|
|
581
|
+
### Rate Limiting
|
|
582
|
+
|
|
583
|
+
**Problem**: `429 Too Many Requests` errors
|
|
584
|
+
|
|
585
|
+
**Solution**:
|
|
586
|
+
- The SDK automatically retries with exponential backoff
|
|
587
|
+
- Reduce request frequency or implement batching
|
|
588
|
+
- Contact Samsara support to increase your rate limits
|
|
589
|
+
- Use pagination to fetch data in smaller chunks
|
|
590
|
+
|
|
591
|
+
### Timeout Errors
|
|
592
|
+
|
|
593
|
+
**Problem**: Requests timing out
|
|
594
|
+
|
|
595
|
+
**Solution**:
|
|
596
|
+
```python
|
|
597
|
+
# Increase timeout at client level
|
|
598
|
+
client = Samsara(token="YOUR_TOKEN", timeout=120.0)
|
|
599
|
+
|
|
600
|
+
# Or per request
|
|
601
|
+
client.vehicles.list(request_options={"timeout_in_seconds": 60})
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### SSL/Certificate Errors
|
|
605
|
+
|
|
606
|
+
**Problem**: SSL verification failures
|
|
607
|
+
|
|
608
|
+
**Solution**:
|
|
609
|
+
```python
|
|
610
|
+
import httpx
|
|
611
|
+
from samsara import Samsara
|
|
612
|
+
|
|
613
|
+
# For corporate proxies or custom certificates
|
|
614
|
+
client = Samsara(
|
|
615
|
+
token="YOUR_TOKEN",
|
|
616
|
+
httpx_client=httpx.Client(verify=False) # Not recommended for production
|
|
617
|
+
)
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Import Errors
|
|
621
|
+
|
|
622
|
+
**Problem**: `ModuleNotFoundError: No module named 'samsara'`
|
|
623
|
+
|
|
624
|
+
**Solution**:
|
|
625
|
+
```bash
|
|
626
|
+
# Ensure the package is installed
|
|
627
|
+
pip install samsara-api
|
|
628
|
+
|
|
629
|
+
# Verify installation
|
|
630
|
+
pip show samsara-api
|
|
631
|
+
|
|
632
|
+
# Check Python version (requires 3.7+)
|
|
633
|
+
python --version
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Pagination Issues
|
|
637
|
+
|
|
638
|
+
**Problem**: Not all results are returned
|
|
639
|
+
|
|
640
|
+
**Solution**:
|
|
641
|
+
```python
|
|
642
|
+
# Always iterate through the pager object
|
|
643
|
+
response = client.vehicles.list()
|
|
644
|
+
all_vehicles = []
|
|
645
|
+
for vehicle in response: # This automatically handles pagination
|
|
646
|
+
all_vehicles.append(vehicle)
|
|
647
|
+
|
|
648
|
+
print(f"Total vehicles: {len(all_vehicles)}")
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### Type Hints Not Working
|
|
652
|
+
|
|
653
|
+
**Problem**: IDE not showing autocomplete
|
|
654
|
+
|
|
655
|
+
**Solution**:
|
|
656
|
+
- Ensure you're using Python 3.7+
|
|
657
|
+
- Update your IDE's Python language server
|
|
658
|
+
- The SDK includes full type hints via `py.typed`
|
|
659
|
+
- Try restarting your IDE or Python language server
|
|
660
|
+
|
|
661
|
+
## Contributing
|
|
662
|
+
|
|
663
|
+
While we value open-source contributions to this SDK, this library is generated programmatically.
|
|
664
|
+
Additions made directly to this library would have to be moved over to our generation code,
|
|
665
|
+
otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
|
|
666
|
+
a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
|
|
667
|
+
an issue first to discuss with us!
|
|
668
|
+
|
|
669
|
+
On the other hand, contributions to the README are always very welcome!
|
|
670
|
+
|
|
@@ -58,7 +58,7 @@ samsara/contacts/client.py,sha256=cjWeQqB4KnyZ1kP8wJKIsVIP6y8v3c5aUl0tRwt-XHY,20
|
|
|
58
58
|
samsara/contacts/raw_client.py,sha256=fYgYXyCONzUxCB95APJ5KtoR8pmoPtPXz1DuXXhybpI,25991
|
|
59
59
|
samsara/core/__init__.py,sha256=LS5PHdFxqIeDNAKS0etuTxkpIkpm7Xi6gnJhhaUK49Q,3774
|
|
60
60
|
samsara/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
|
|
61
|
-
samsara/core/client_wrapper.py,sha256=
|
|
61
|
+
samsara/core/client_wrapper.py,sha256=yeqrkuJwvw8AIoeW-_EhwPWGV785gmRwHHMECoM145g,2817
|
|
62
62
|
samsara/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
|
63
63
|
samsara/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
|
|
64
64
|
samsara/core/force_multipart.py,sha256=cH981xLy0kZVKiZZkFoeUjgJ2Zuq7KXB2aRAnmHzRDc,477
|
|
@@ -3381,7 +3381,7 @@ samsara/work_orders/types/work_orders_patch_work_orders_request_body_priority.py
|
|
|
3381
3381
|
samsara/work_orders/types/work_orders_patch_work_orders_request_body_status.py,sha256=HCbiTTKvZhHCnsfipa-7_u4ZXx1uToFt4cEljXUd9l8,375
|
|
3382
3382
|
samsara/work_orders/types/work_orders_post_work_orders_request_body_category.py,sha256=f4ymEFlM2n2Rl4RTq8HCmJLfjiiFV25meugT2WscLys,253
|
|
3383
3383
|
samsara/work_orders/types/work_orders_post_work_orders_request_body_priority.py,sha256=5XQBG4kltC3s19wLXysQlPTK_h82LG5RszQSxk1hd14,208
|
|
3384
|
-
samsara_api-4.0.
|
|
3385
|
-
samsara_api-4.0.
|
|
3386
|
-
samsara_api-4.0.
|
|
3387
|
-
samsara_api-4.0.
|
|
3384
|
+
samsara_api-4.0.1.dist-info/LICENSE,sha256=uX-nl5hOEHp4uvQPCcpde-doNbQhV5uRQNwkB474IoQ,1064
|
|
3385
|
+
samsara_api-4.0.1.dist-info/METADATA,sha256=gRop5Vi_vGn3OXhVNudqqLq8ZUP0qbUq1rLf7ni9u-g,18974
|
|
3386
|
+
samsara_api-4.0.1.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
|
3387
|
+
samsara_api-4.0.1.dist-info/RECORD,,
|
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: samsara-api
|
|
3
|
-
Version: 4.0.0
|
|
4
|
-
Summary:
|
|
5
|
-
License: MIT
|
|
6
|
-
Requires-Python: >=3.8,<4.0
|
|
7
|
-
Classifier: Intended Audience :: Developers
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Operating System :: MacOS
|
|
10
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
12
|
-
Classifier: Operating System :: POSIX
|
|
13
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
-
Classifier: Programming Language :: Python
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
-
Classifier: Typing :: Typed
|
|
23
|
-
Requires-Dist: httpx (>=0.21.2)
|
|
24
|
-
Requires-Dist: pydantic (>=1.9.2)
|
|
25
|
-
Requires-Dist: pydantic-core (>=2.18.2)
|
|
26
|
-
Requires-Dist: typing_extensions (>=4.0.0)
|
|
27
|
-
Description-Content-Type: text/markdown
|
|
28
|
-
|
|
29
|
-
# Samsara Python Library
|
|
30
|
-
|
|
31
|
-
[](https://buildwithfern.com?utm_source=github&utm_medium=github&utm_campaign=readme&utm_source=https%3A%2F%2Fgithub.com%2Fsamsarahq%2Fsamsara-python-sdk)
|
|
32
|
-
[](https://pypi.python.org/pypi/samsara-api)
|
|
33
|
-
|
|
34
|
-
The Samsara Python library provides convenient access to the Samsara API from Python.
|
|
35
|
-
|
|
36
|
-
## Documentation
|
|
37
|
-
|
|
38
|
-
API reference documentation is available [here](https://developers.samsara.com/reference/overview).
|
|
39
|
-
|
|
40
|
-
## Installation
|
|
41
|
-
|
|
42
|
-
```sh
|
|
43
|
-
pip install samsara-api
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Reference
|
|
47
|
-
|
|
48
|
-
A full reference for this library is available [here](https://github.com/samsarahq/samsara-python-sdk/blob/HEAD/./reference.md).
|
|
49
|
-
|
|
50
|
-
## Usage
|
|
51
|
-
|
|
52
|
-
Instantiate and use the client with the following:
|
|
53
|
-
|
|
54
|
-
```python
|
|
55
|
-
from samsara import Samsara
|
|
56
|
-
|
|
57
|
-
client = Samsara(
|
|
58
|
-
token="YOUR_TOKEN",
|
|
59
|
-
)
|
|
60
|
-
response = client.vehicles.stats.list()
|
|
61
|
-
for item in response:
|
|
62
|
-
yield item
|
|
63
|
-
# alternatively, you can paginate page-by-page
|
|
64
|
-
for page in response.iter_pages():
|
|
65
|
-
yield page
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Async Client
|
|
69
|
-
|
|
70
|
-
The SDK also exports an `async` client so that you can make non-blocking calls to our API.
|
|
71
|
-
|
|
72
|
-
```python
|
|
73
|
-
import asyncio
|
|
74
|
-
|
|
75
|
-
from samsara import AsyncSamsara
|
|
76
|
-
|
|
77
|
-
client = AsyncSamsara(
|
|
78
|
-
token="YOUR_TOKEN",
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
async def main() -> None:
|
|
83
|
-
response = await client.vehicles.stats.list()
|
|
84
|
-
async for item in response:
|
|
85
|
-
yield item
|
|
86
|
-
|
|
87
|
-
# alternatively, you can paginate page-by-page
|
|
88
|
-
async for page in response.iter_pages():
|
|
89
|
-
yield page
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
asyncio.run(main())
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Exception Handling
|
|
96
|
-
|
|
97
|
-
When the API returns a non-success status code (4xx or 5xx response), a subclass of the following error
|
|
98
|
-
will be thrown.
|
|
99
|
-
|
|
100
|
-
```python
|
|
101
|
-
from samsara.core.api_error import ApiError
|
|
102
|
-
|
|
103
|
-
try:
|
|
104
|
-
client.vehicles.stats.list(...)
|
|
105
|
-
except ApiError as e:
|
|
106
|
-
print(e.status_code)
|
|
107
|
-
print(e.body)
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Pagination
|
|
111
|
-
|
|
112
|
-
Paginated requests will return a `SyncPager` or `AsyncPager`, which can be used as generators for the underlying object.
|
|
113
|
-
|
|
114
|
-
```python
|
|
115
|
-
from samsara import Samsara
|
|
116
|
-
|
|
117
|
-
client = Samsara(
|
|
118
|
-
token="YOUR_TOKEN",
|
|
119
|
-
)
|
|
120
|
-
response = client.addresses.list()
|
|
121
|
-
for item in response:
|
|
122
|
-
yield item
|
|
123
|
-
# alternatively, you can paginate page-by-page
|
|
124
|
-
for page in response.iter_pages():
|
|
125
|
-
yield page
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Webhook Signature Verification
|
|
129
|
-
|
|
130
|
-
The SDK provides utility methods that allow you to verify webhook signatures and ensure
|
|
131
|
-
that all webhook events originate from Samsara. The `verify_signature` method will verify
|
|
132
|
-
the signature.
|
|
133
|
-
|
|
134
|
-
```python
|
|
135
|
-
from samsara.utils.webhooks_helper import verify_signature
|
|
136
|
-
|
|
137
|
-
is_valid = verify_signature(
|
|
138
|
-
request_body=request_body,
|
|
139
|
-
signature_header=request.headers['x-samsara-hmacsha256-signature'],
|
|
140
|
-
signature_key="YOUR_SIGNATURE_KEY",
|
|
141
|
-
notification_url="https://example.com/webhook", # The URL where event notifications are sent.
|
|
142
|
-
)
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Advanced
|
|
146
|
-
|
|
147
|
-
### Access Raw Response Data
|
|
148
|
-
|
|
149
|
-
The SDK provides access to raw response data, including headers, through the `.with_raw_response` property.
|
|
150
|
-
The `.with_raw_response` property returns a "raw" client that can be used to access the `.headers` and `.data` attributes.
|
|
151
|
-
|
|
152
|
-
```python
|
|
153
|
-
from samsara import Samsara
|
|
154
|
-
|
|
155
|
-
client = Samsara(
|
|
156
|
-
...,
|
|
157
|
-
)
|
|
158
|
-
response = client.vehicles.stats.with_raw_response.list(...)
|
|
159
|
-
print(response.headers) # access the response headers
|
|
160
|
-
print(response.data) # access the underlying object
|
|
161
|
-
pager = client.addresses.list(...)
|
|
162
|
-
print(pager.response.headers) # access the response headers for the first page
|
|
163
|
-
for item in pager:
|
|
164
|
-
print(item) # access the underlying object(s)
|
|
165
|
-
for page in pager.iter_pages():
|
|
166
|
-
print(page.response.headers) # access the response headers for each page
|
|
167
|
-
for item in page:
|
|
168
|
-
print(item) # access the underlying object(s)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### Retries
|
|
172
|
-
|
|
173
|
-
The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long
|
|
174
|
-
as the request is deemed retryable and the number of retry attempts has not grown larger than the configured
|
|
175
|
-
retry limit (default: 2).
|
|
176
|
-
|
|
177
|
-
A request is deemed retryable when any of the following HTTP status codes is returned:
|
|
178
|
-
|
|
179
|
-
- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)
|
|
180
|
-
- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)
|
|
181
|
-
- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)
|
|
182
|
-
|
|
183
|
-
Use the `max_retries` request option to configure this behavior.
|
|
184
|
-
|
|
185
|
-
```python
|
|
186
|
-
client.vehicles.stats.list(..., request_options={
|
|
187
|
-
"max_retries": 1
|
|
188
|
-
})
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Timeouts
|
|
192
|
-
|
|
193
|
-
The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level.
|
|
194
|
-
|
|
195
|
-
```python
|
|
196
|
-
|
|
197
|
-
from samsara import Samsara
|
|
198
|
-
|
|
199
|
-
client = Samsara(
|
|
200
|
-
...,
|
|
201
|
-
timeout=20.0,
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
# Override timeout for a specific method
|
|
206
|
-
client.vehicles.stats.list(..., request_options={
|
|
207
|
-
"timeout_in_seconds": 1
|
|
208
|
-
})
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Custom Client
|
|
212
|
-
|
|
213
|
-
You can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies
|
|
214
|
-
and transports.
|
|
215
|
-
|
|
216
|
-
```python
|
|
217
|
-
import httpx
|
|
218
|
-
from samsara import Samsara
|
|
219
|
-
|
|
220
|
-
client = Samsara(
|
|
221
|
-
...,
|
|
222
|
-
httpx_client=httpx.Client(
|
|
223
|
-
proxies="http://my.test.proxy.example.com",
|
|
224
|
-
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
|
|
225
|
-
),
|
|
226
|
-
)
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## Contributing
|
|
230
|
-
|
|
231
|
-
While we value open-source contributions to this SDK, this library is generated programmatically.
|
|
232
|
-
Additions made directly to this library would have to be moved over to our generation code,
|
|
233
|
-
otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
|
|
234
|
-
a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
|
|
235
|
-
an issue first to discuss with us!
|
|
236
|
-
|
|
237
|
-
On the other hand, contributions to the README are always very welcome!
|
|
238
|
-
|
|
File without changes
|
|
File without changes
|