Async Python client for the Autotask REST API
Project description
autotask-client
Async Python client for the Autotask REST API. Handles zone discovery, authentication, rate limiting, pagination, and all 211 entity types out of the box.
Install
pip install autotask-client
Quick Start
import asyncio
from autotask import AutotaskClient, AutotaskConfig, EntityManager
from autotask.models import Ticket, Company
from autotask.query import Q
async def main():
config = AutotaskConfig(
username="user@example.com",
secret="your-api-secret",
integration_code="your-integration-code",
)
async with AutotaskClient(config) as client:
em = EntityManager(client)
# Query tickets by status
tickets = await em.query(Ticket, Q(status=8))
# Get a single company
company = await em.get(Company, 12345)
# Create a ticket
ticket = Ticket(
title="Server down",
companyID=12345,
status=1,
priority=1,
)
created = await em.create(ticket)
# Update with PATCH (only specified fields change)
updated = await em.update(Ticket(id=created.id, status=5))
# Query any of the 211 entity types by name
items = await em.query("ConfigurationItems", Q(isActive=True))
asyncio.run(main())
Configuration
Environment Variables
export AUTOTASK_USERNAME="user@example.com"
export AUTOTASK_SECRET="your-secret"
export AUTOTASK_INTEGRATION_CODE="your-code"
# Optional
export AUTOTASK_API_URL="https://webservicesX.autotask.net/atservicesrest"
export AUTOTASK_RESOURCE_ID="12345"
config = AutotaskConfig.from_env()
AUTOTASK_SECRET_B64 is also supported for platforms that mangle special characters (base64-encoded secret).
If AUTOTASK_API_URL is not set, the client automatically discovers your zone via the Autotask zone information endpoint and caches it to ~/.cache/autotask/zone.json.
Query DSL
Django-inspired filter syntax:
from autotask.query import Q
Q(status=1) # eq (default)
Q(id__gt=100) # greater than
Q(title__contains="server") # contains
Q(status__in=[1, 5, 8]) # in list
Q(priority__gte=2, status__noteq=5) # multiple filters (AND)
# UDF (User Defined Field) filters — one per query (API limitation)
Q.udf(myCustomField__contains="value")
# Combine with &
filters = Q(status=1) & Q(companyID=123)
Supported operators: eq, noteq, gt, gte, lt, lte, beginsWith, endsWith, contains, exist, notExist, in, notIn
Entity Models
Hand-crafted Pydantic models for common entities with typed fields and validation:
| Model | API Entity |
|---|---|
Ticket |
Tickets |
Company |
Companies |
Project |
Projects |
Task |
Tasks (child of Project) |
Resource |
Resources |
TimeEntry |
TimeEntries |
TicketNote |
TicketNotes (child of Ticket) |
ProjectNote |
ProjectNotes (child of Project) |
TaskNote |
TaskNotes (child of Task) |
All models use extra="allow" to preserve unmodeled fields during round-trips.
For entity types without a hand-crafted model, pass the entity name as a string — the manager returns raw dicts:
items = await em.query("Contacts", Q(isActive=True))
CLI
Output is JSON by default (designed for scripting/AI consumption). Use --table for human-readable output.
Entity Commands
Full CRUD for the core entity types:
# Tickets
autotask tickets list --status 8 --limit 10
autotask tickets get 12345
autotask tickets create --title "Fix printer" --company-id 123
autotask tickets update 12345 --status 5 --priority 1
autotask tickets delete 12345
# Companies
autotask companies list --limit 10
autotask companies get 12345
autotask companies create --name "Acme Corp"
autotask companies update 12345 --name "Acme Inc"
# Projects
autotask projects list --limit 10
autotask projects get 12345
# Tasks (queried via projectID filter, not a child entity)
autotask tasks list --project 12345
autotask tasks get 67890
autotask tasks create --project-id 12345 --title "Migrate database"
autotask tasks update 67890 --status 5
# Time entries
autotask time-entries list --limit 10
autotask time-entries create --resource-id 456 --ticket-id 12345 --hours 1.5
autotask time-entries update 67890 --hours 2.0
# Resources (read-only)
autotask resources list --limit 10
autotask resources get 12345
Notes (Child Entities)
Notes are children of their parent entity — the parent ID is required:
# Ticket notes
autotask ticket-notes list 12345 # notes on ticket 12345
autotask ticket-notes get 12345 67890 # note 67890 on ticket 12345
autotask ticket-notes create 12345 --title "Update" --description "Fixed the issue"
# Project notes
autotask project-notes list 12345
autotask project-notes create 12345 --title "Status" --description "On track"
# Task notes
autotask task-notes list 67890
autotask task-notes create 67890 --title "Progress" --description "50% done"
Generic Commands
Work with any of the 211 Autotask entity types:
# Query any entity
autotask query ConfigurationItems isActive=true --limit 20
autotask query Contacts firstName=John --limit 10
# Get/create/update/delete by entity type
autotask get Tickets 12345
autotask create Tickets --fields '{"title":"Test","companyID":123,"status":1,"priority":2}'
autotask update Tickets 12345 --fields '{"status":5,"priority":1}'
autotask delete Tickets 12345
# Child entities use --parent-id
autotask get TicketNotes 67890 --parent-id 12345
Metadata & Utilities
autotask info Tickets # Entity capabilities (canCreate, canQuery, etc.)
autotask fields Tickets # Field definitions, types, required flags
autotask picklist Tickets status # Resolve picklist IDs to labels
autotask whoami # Authenticated user's resource record
autotask config # Show current configuration (no secrets)
# Table output
autotask --table tickets list --limit 5
MCP Server
The package includes an MCP server for LLM tool use. Install with the mcp extra:
pip install autotask-client[mcp]
Tools
| Tool | Description |
|---|---|
autotask_query |
Query any entity with filters and pagination |
autotask_get |
Get a single entity by ID |
autotask_create |
Create an entity from field values |
autotask_update |
PATCH update (only specified fields change) |
autotask_delete |
Delete an entity by ID |
autotask_entity_info |
Entity capabilities (canCreate, canQuery, etc.) |
autotask_field_info |
Field definitions, types, picklist references |
autotask_resolve_picklist |
Resolve picklist field to {id: label} mapping |
autotask_whoami |
Authenticated user's resource record |
Claude Desktop Configuration
Add to your claude_desktop_config.json:
{
"mcpServers": {
"autotask": {
"command": "autotask-mcp",
"env": {
"AUTOTASK_USERNAME": "user@example.com",
"AUTOTASK_SECRET": "your-api-secret",
"AUTOTASK_INTEGRATION_CODE": "your-integration-code"
}
}
}
}
Or if installed via pipx:
{
"mcpServers": {
"autotask": {
"command": "pipx",
"args": ["run", "--spec", "autotask-client[mcp]", "autotask-mcp"],
"env": {
"AUTOTASK_USERNAME": "user@example.com",
"AUTOTASK_SECRET": "your-api-secret",
"AUTOTASK_INTEGRATION_CODE": "your-integration-code"
}
}
}
}
Claude Code Configuration
Add to your .mcp.json:
{
"mcpServers": {
"autotask": {
"command": "autotask-mcp",
"env": {
"AUTOTASK_USERNAME": "user@example.com",
"AUTOTASK_SECRET": "your-api-secret",
"AUTOTASK_INTEGRATION_CODE": "your-integration-code"
}
}
}
}
API Behavior
Things this library handles so you don't have to:
- Zone discovery — Autotask routes tenants to different datacenters. The client discovers and caches the correct URL automatically.
- Auth via headers —
UserName,Secret,ApiIntegrationCodeon every request. - Rate limiting — Progressive throttling at 50% and 75% of the 10k req/hour shared limit. Reads usage from response headers.
- Pagination —
query_all()automatically paginates usingid > last_id(max 500 per page). - Retry — Transient failures (connection errors, timeouts) retry with exponential backoff (3 attempts).
- Concurrency — Semaphore limits to 3 concurrent requests per endpoint.
- Error mapping — 401 and 500-with-auth-pattern both raise
AutotaskAuthError. 404 raisesAutotaskNotFoundError. The API returns{item: null}instead of 404 for missing entities — this is handled correctly.
Requirements
- Python 3.12+
- httpx, pydantic, click, tenacity
License
MIT
Project details
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 autotask_client-0.3.1.tar.gz.
File metadata
- Download URL: autotask_client-0.3.1.tar.gz
- Upload date:
- Size: 52.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed5d2c8b613d320e58e4dae9460c9a01ae7d85f393b215980ed0a976cac183c1
|
|
| MD5 |
0c046986924da39f17f3f5f7378bc593
|
|
| BLAKE2b-256 |
2f2a3d79b847600d97c3ea4658668db32838c78d6a96f4892026c997abbdf9c5
|
File details
Details for the file autotask_client-0.3.1-py3-none-any.whl.
File metadata
- Download URL: autotask_client-0.3.1-py3-none-any.whl
- Upload date:
- Size: 30.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec128a20aa685c6bed8b1c55dc8aa3663fed524ead5db1adc9d96cfd716e08ea
|
|
| MD5 |
38dbfea8c116a228c52975788441da86
|
|
| BLAKE2b-256 |
fcde93b21e7b8924ca7431150d3ed8d7a4d3ae0ade760db34df7314b7df09ddd
|