Python SDK for the ServiceTrade REST API
Project description
ServiceTrade Python SDK
A Python client for the ServiceTrade REST API with OAuth2 authentication and automatic token refresh.
Installation
pip install servicetrade
Quick Start
Using Client Credentials
from servicetrade import ServicetradeClient
client = ServicetradeClient(
client_id="your-client-id",
client_secret="your-client-secret"
)
# No need to call login() — the SDK authenticates lazily on the first API call.
jobs = client.get("/job")
print(jobs)
Using Refresh Token
from servicetrade import ServicetradeClient
client = ServicetradeClient(
refresh_token="your-refresh-token"
)
jobs = client.get("/job")
Using a Pre-existing Token
from servicetrade import ServicetradeClient
client = ServicetradeClient(
token="your-bearer-token",
# Provide credentials for auto-refresh when the token expires
client_id="your-client-id",
client_secret="your-client-secret"
)
# No login needed if token is valid
jobs = client.get("/job")
API Methods
HTTP Methods
# GET request
result = client.get("/job/123")
# GET with query parameters
jobs = client.get("/job", params={"status": "scheduled", "locationId": 456})
# POST request
job = client.post("/job", {
"type": "inspection",
"description": "Quarterly HVAC Inspection",
"locationId": 123,
"vendorId": 456,
})
# PUT request
client.put("/job/123", {"description": "Updated Inspection Description"})
# DELETE request (returns None)
client.delete("/location/456")
Paginator
Iterate over all pages of a paginated endpoint automatically:
from servicetrade import Paginator, ServicetradeClient, ServicetradeAPIError
client = ServicetradeClient(
client_id="your-client-id",
client_secret="your-client-secret"
)
paginator = Paginator(client, "/job", "jobs", params={"status": "scheduled"})
try:
for job in paginator:
print(f"Job #{job['id']}: {job['description']}")
except ServicetradeAPIError as e:
print(f"Error during pagination: {e.message}")
The Paginator constructor takes:
client— aServicetradeClientinstancepath— the API endpoint path (e.g.,"/job")items_key— the key in the response that contains the list of items (e.g.,"jobs")params— optional dict of query parameters to include on every request
File Attachments
from servicetrade import ServicetradeClient, FileAttachment
client = ServicetradeClient(client_id="your-client-id", client_secret="your-client-secret")
# Upload a file
file = FileAttachment(
value=b"file contents here",
filename="document.pdf",
content_type="application/pdf"
)
result = client.attach(
{"entityType": 3, "entityId": 123, "purposeId": 7},
file
)
Reading from a file path
from pathlib import Path
from servicetrade import FileAttachment
file = FileAttachment(
value=Path("/path/to/document.pdf"),
filename="document.pdf",
content_type="application/pdf"
)
Response Handling
Return values
get(),post(),put()return thedatafield from the response when present, or the full response dict/list otherwise.delete()returnsNone.- When fetching a single resource by ID (e.g.,
/job/123), the response is adict. When querying a collection (e.g.,/job), the response may be adictcontaining a list under a resource-specific key (e.g.,"jobs").
Accessing the full response
Use get_last_response() to access status code, headers, and full body:
result = client.get("/job/123")
response = client.get_last_response()
print(response.status_code) # 200
print(response.is_success()) # True
print(response.body) # Full response body (dict)
print(response.headers) # Response headers (dict)
Accessing the auth token
token = client.get_auth_token()
Configuration Options
client = ServicetradeClient(
# API Configuration
base_url="https://api.servicetrade.com", # Default
api_prefix="/api", # Default
user_agent="My App/1.0", # Custom user agent
# Authentication (pick one)
client_id="your-client-id",
client_secret="your-client-secret",
# OR
refresh_token="your-refresh-token",
# OR
token="your-bearer-token",
# Options
auto_refresh_auth=True, # Auto-refresh tokens (default)
# Callbacks
on_set_auth=lambda token: save_token(token),
on_unset_auth=lambda: clear_token(),
)
Custom Headers
client.set_custom_header("X-Custom-Header", "value")
Error Handling
from servicetrade import (
ServicetradeClient,
ServicetradeAuthError,
ServicetradeAPIError,
)
client = ServicetradeClient(client_id="your-client-id", client_secret="your-client-secret")
try:
result = client.get("/nonexistent")
except ServicetradeAPIError as e:
print(f"API error: {e.message}")
print(f"Status code: {e.status_code}")
print(f"Response data: {e.response_data}")
# Structured errors from ServiceTrade API
if e.error_messages:
print(f"Errors: {e.error_messages}")
if e.validation:
print(f"Validation: {e.validation}")
Authentication Flow
The SDK supports two OAuth2 grant types, prioritized in this order:
- Refresh Token Grant — Most secure, only stores refresh token
- Client Credentials Grant — For service-to-service authentication
Lazy Authentication
The SDK automatically authenticates on the first API call if no token exists. You can also call login() explicitly for eager authentication:
client = ServicetradeClient(client_id="your-client-id", client_secret="your-client-secret")
# Eager authentication (optional)
client.login()
# Or just make API calls — login happens automatically
jobs = client.get("/job")
Automatic Token Refresh
By default, the SDK automatically refreshes tokens when:
- A request returns a 401 Unauthorized response
- The token is about to expire (within 5 minutes of expiry)
To disable automatic refresh:
client = ServicetradeClient(
client_id="id",
client_secret="secret",
auto_refresh_auth=False
)
Development
Setup
# Clone the repository
git clone https://github.com/servicetrade/servicetrade-python-sdk.git
cd servicetrade-python-sdk
# Install development dependencies
pip install -e ".[dev]"
Running Tests
pytest
Type Checking
mypy src
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file servicetrade-1.0.0.tar.gz.
File metadata
- Download URL: servicetrade-1.0.0.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
708df3245209322e86749548592c4903799843946cb90ea2c96241da6e57b25f
|
|
| MD5 |
eed2b5bc730d42c796f7ec0bdb10f67f
|
|
| BLAKE2b-256 |
3c28d5a8694a46f379524abd73c0609284377fd0e8c08d07fe79eb4d4fe63f43
|
Provenance
The following attestation bundles were made for servicetrade-1.0.0.tar.gz:
Publisher:
publish.yml on servicetrade/servicetrade-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
servicetrade-1.0.0.tar.gz -
Subject digest:
708df3245209322e86749548592c4903799843946cb90ea2c96241da6e57b25f - Sigstore transparency entry: 1162777865
- Sigstore integration time:
-
Permalink:
servicetrade/servicetrade-python-sdk@5d3e541b508e0d75d919d30d65cb46b96bf247aa -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/servicetrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5d3e541b508e0d75d919d30d65cb46b96bf247aa -
Trigger Event:
push
-
Statement type:
File details
Details for the file servicetrade-1.0.0-py3-none-any.whl.
File metadata
- Download URL: servicetrade-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02d93e85dd46af295797ea8a025d5d49a1e8894b62378623abd1e1f3334ca413
|
|
| MD5 |
6c849fc9768019d835d1504c5fead549
|
|
| BLAKE2b-256 |
6ae8a53fcfbc4a6f6ea4e408a064d845dded553ee817a6f18f1daca49f7c454c
|
Provenance
The following attestation bundles were made for servicetrade-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on servicetrade/servicetrade-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
servicetrade-1.0.0-py3-none-any.whl -
Subject digest:
02d93e85dd46af295797ea8a025d5d49a1e8894b62378623abd1e1f3334ca413 - Sigstore transparency entry: 1162777932
- Sigstore integration time:
-
Permalink:
servicetrade/servicetrade-python-sdk@5d3e541b508e0d75d919d30d65cb46b96bf247aa -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/servicetrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5d3e541b508e0d75d919d30d65cb46b96bf247aa -
Trigger Event:
push
-
Statement type: