# haloitsm-python
This is a Python library for the HaloITSM tool. It is written and maintained by BDQ.cloud, a Halo partner as a useful resource for the HaloITSM community. This library is not supported or endorsed by Halo.
# Halo API Client
A clean, Pythonic client library for the Halo ITSM REST API. This library provides a simple interface for interacting with Halo while maintaining a clear separation between API operations and business logic.
## Features
- **Clean API**: Intuitive, Pythonic interface similar to popular clients like `jira-python`
- **Automatic Authentication**: Handles OAuth2 token management and refresh
- **Resource-based Design**: Work with tickets, ticket types, and fields as Python objects
- **Error Handling**: Comprehensive exception hierarchy for different error scenarios
- **Retry Logic**: Built-in retry mechanisms for transient failures
- **Type Hints**: Full type hint coverage for better IDE support
## Installation
```bash
pip install halo-api-client
```
## Quick Start
```python
from halo import HaloClient
# Initialize the client
client = HaloClient(
base_url="https://your-instance.haloservicedesk.com/api",
client_id="your-client-id",
client_secret="your-client-secret"
)
# List all ticket types
for ticket_type in client.ticket_types.list():
print(f"{ticket_type.id}: {ticket_type.name}")
# Get a specific ticket type with field details
ticket_type = client.ticket_types.get(24, include_details=True)
fields = ticket_type.get_fields()
# Create a new ticket
ticket = client.tickets.create({
'tickettype_id': 24,
'summary': 'Server down',
'details': 'Production server is not responding'
})
# Update the ticket
ticket.update({'status_id': 2})
# Add a comment
ticket.add_action({
'note_html': '<p>Looking into this issue</p>',
'outcome_id': 1
})
```
## Authentication
The client supports multiple authentication methods:
### Client Credentials (Recommended for server-to-server)
```python
client = HaloClient(
base_url="https://your-instance.haloservicedesk.com/api",
client_id="your-client-id",
client_secret="your-client-secret"
)
```
### Username/Password
```python
client = HaloClient(
base_url="https://your-instance.haloservicedesk.com/api",
client_id="your-client-id",
username="user@example.com",
password="your-password"
)
```
### Existing Token
```python
client = HaloClient(
base_url="https://your-instance.haloservicedesk.com/api",
token="existing-access-token",
refresh_token="existing-refresh-token"
)
```
## Working with Resources
### Ticket Types
```python
# List ticket types with filters
ticket_types = client.ticket_types.list(
show_inactive=False,
can_create_only=True
)
# Get a specific ticket type
ticket_type = client.ticket_types.get(24)
# Get fields for a ticket type
ticket_type = client.ticket_types.get(24, include_details=True)
fields = ticket_type.get_fields()
# Access field properties
for field in fields:
print(f"{field.name}: {field.field_type}")
if field.is_mandatory:
print(" - Required field")
if field.lookup_values:
print(" - Lookup values:", field.lookup_values)
```
### Tickets
```python
# Search tickets
tickets = client.tickets.search("server down", limit=10)
# List tickets with filters
tickets = client.tickets.list(
ticket_type_id=24,
status_id=1,
page_size=50
)
# Get a specific ticket
ticket = client.tickets.get(12345)
# Create a ticket
ticket = client.tickets.create({
'tickettype_id': 24,
'summary': 'New issue',
'details': 'Issue description',
'priority_id': 3
})
# Update a ticket
ticket.update({
'status_id': 2,
'summary': 'Updated summary'
})
# Add attachments
ticket.add_attachment(
filename="screenshot.png",
file_content=image_bytes,
description="Error screenshot"
)
```
## Error Handling
The client provides specific exceptions for different error scenarios:
```python
from halo import (
HaloAuthenticationError,
HaloResourceNotFound,
HaloValidationError,
HaloRateLimitError
)
try:
ticket = client.tickets.get(99999)
except HaloResourceNotFound as e:
print(f"Ticket not found: {e}")
except HaloAuthenticationError as e:
print(f"Authentication failed: {e}")
except HaloValidationError as e:
print(f"Validation error: {e.errors}")
except HaloRateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
```
## Advanced Usage
### Raw API Access
For endpoints not yet wrapped by the client:
```python
# Make raw API calls
response = client.get('/custom/endpoint', params={'filter': 'value'})
response = client.post('/custom/endpoint', json={'data': 'value'})
```
### Custom Session Configuration
```python
client = HaloClient(
base_url="https://your-instance.haloservicedesk.com/api",
client_id="your-client-id",
client_secret="your-client-secret",
timeout=60, # Request timeout in seconds
max_retries=5 # Maximum retry attempts
)
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the LICENSE file for details.
Raw data
{
"_id": null,
"home_page": null,
"name": "haloitsm-python",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Chris Bland <cbland@bdq.cloud>",
"keywords": "halo, itsm, api, client, service desk, ticketing",
"author": null,
"author_email": "Chris Bland <cbland@bdq.cloud>",
"download_url": "https://files.pythonhosted.org/packages/b7/35/56de8b73d1e9550f5515263d3e793ebbd17602349c59f346c71c9cb94fd7/haloitsm_python-0.1.0.tar.gz",
"platform": null,
"description": "# haloitsm-python\r\n\r\nThis is a Python library for the HaloITSM tool. It is written and maintained by BDQ.cloud, a Halo partner as a useful resource for the HaloITSM community. This library is not supported or endorsed by Halo.\r\n\r\n# Halo API Client\r\n\r\nA clean, Pythonic client library for the Halo ITSM REST API. This library provides a simple interface for interacting with Halo while maintaining a clear separation between API operations and business logic.\r\n\r\n## Features\r\n\r\n- **Clean API**: Intuitive, Pythonic interface similar to popular clients like `jira-python`\r\n- **Automatic Authentication**: Handles OAuth2 token management and refresh\r\n- **Resource-based Design**: Work with tickets, ticket types, and fields as Python objects\r\n- **Error Handling**: Comprehensive exception hierarchy for different error scenarios\r\n- **Retry Logic**: Built-in retry mechanisms for transient failures\r\n- **Type Hints**: Full type hint coverage for better IDE support\r\n\r\n## Installation\r\n\r\n```bash\r\npip install halo-api-client\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom halo import HaloClient\r\n\r\n# Initialize the client\r\nclient = HaloClient(\r\n base_url=\"https://your-instance.haloservicedesk.com/api\",\r\n client_id=\"your-client-id\",\r\n client_secret=\"your-client-secret\"\r\n)\r\n\r\n# List all ticket types\r\nfor ticket_type in client.ticket_types.list():\r\n print(f\"{ticket_type.id}: {ticket_type.name}\")\r\n\r\n# Get a specific ticket type with field details\r\nticket_type = client.ticket_types.get(24, include_details=True)\r\nfields = ticket_type.get_fields()\r\n\r\n# Create a new ticket\r\nticket = client.tickets.create({\r\n 'tickettype_id': 24,\r\n 'summary': 'Server down',\r\n 'details': 'Production server is not responding'\r\n})\r\n\r\n# Update the ticket\r\nticket.update({'status_id': 2})\r\n\r\n# Add a comment\r\nticket.add_action({\r\n 'note_html': '<p>Looking into this issue</p>',\r\n 'outcome_id': 1\r\n})\r\n```\r\n\r\n## Authentication\r\n\r\nThe client supports multiple authentication methods:\r\n\r\n### Client Credentials (Recommended for server-to-server)\r\n\r\n```python\r\nclient = HaloClient(\r\n base_url=\"https://your-instance.haloservicedesk.com/api\",\r\n client_id=\"your-client-id\",\r\n client_secret=\"your-client-secret\"\r\n)\r\n```\r\n\r\n### Username/Password\r\n\r\n```python\r\nclient = HaloClient(\r\n base_url=\"https://your-instance.haloservicedesk.com/api\",\r\n client_id=\"your-client-id\",\r\n username=\"user@example.com\",\r\n password=\"your-password\"\r\n)\r\n```\r\n\r\n### Existing Token\r\n\r\n```python\r\nclient = HaloClient(\r\n base_url=\"https://your-instance.haloservicedesk.com/api\",\r\n token=\"existing-access-token\",\r\n refresh_token=\"existing-refresh-token\"\r\n)\r\n```\r\n\r\n## Working with Resources\r\n\r\n### Ticket Types\r\n\r\n```python\r\n# List ticket types with filters\r\nticket_types = client.ticket_types.list(\r\n show_inactive=False,\r\n can_create_only=True\r\n)\r\n\r\n# Get a specific ticket type\r\nticket_type = client.ticket_types.get(24)\r\n\r\n# Get fields for a ticket type\r\nticket_type = client.ticket_types.get(24, include_details=True)\r\nfields = ticket_type.get_fields()\r\n\r\n# Access field properties\r\nfor field in fields:\r\n print(f\"{field.name}: {field.field_type}\")\r\n if field.is_mandatory:\r\n print(\" - Required field\")\r\n if field.lookup_values:\r\n print(\" - Lookup values:\", field.lookup_values)\r\n```\r\n\r\n### Tickets\r\n\r\n```python\r\n# Search tickets\r\ntickets = client.tickets.search(\"server down\", limit=10)\r\n\r\n# List tickets with filters\r\ntickets = client.tickets.list(\r\n ticket_type_id=24,\r\n status_id=1,\r\n page_size=50\r\n)\r\n\r\n# Get a specific ticket\r\nticket = client.tickets.get(12345)\r\n\r\n# Create a ticket\r\nticket = client.tickets.create({\r\n 'tickettype_id': 24,\r\n 'summary': 'New issue',\r\n 'details': 'Issue description',\r\n 'priority_id': 3\r\n})\r\n\r\n# Update a ticket\r\nticket.update({\r\n 'status_id': 2,\r\n 'summary': 'Updated summary'\r\n})\r\n\r\n# Add attachments\r\nticket.add_attachment(\r\n filename=\"screenshot.png\",\r\n file_content=image_bytes,\r\n description=\"Error screenshot\"\r\n)\r\n```\r\n\r\n## Error Handling\r\n\r\nThe client provides specific exceptions for different error scenarios:\r\n\r\n```python\r\nfrom halo import (\r\n HaloAuthenticationError,\r\n HaloResourceNotFound,\r\n HaloValidationError,\r\n HaloRateLimitError\r\n)\r\n\r\ntry:\r\n ticket = client.tickets.get(99999)\r\nexcept HaloResourceNotFound as e:\r\n print(f\"Ticket not found: {e}\")\r\nexcept HaloAuthenticationError as e:\r\n print(f\"Authentication failed: {e}\")\r\nexcept HaloValidationError as e:\r\n print(f\"Validation error: {e.errors}\")\r\nexcept HaloRateLimitError as e:\r\n print(f\"Rate limited. Retry after {e.retry_after} seconds\")\r\n```\r\n\r\n## Advanced Usage\r\n\r\n### Raw API Access\r\n\r\nFor endpoints not yet wrapped by the client:\r\n\r\n```python\r\n# Make raw API calls\r\nresponse = client.get('/custom/endpoint', params={'filter': 'value'})\r\nresponse = client.post('/custom/endpoint', json={'data': 'value'})\r\n```\r\n\r\n### Custom Session Configuration\r\n\r\n```python\r\nclient = HaloClient(\r\n base_url=\"https://your-instance.haloservicedesk.com/api\",\r\n client_id=\"your-client-id\",\r\n client_secret=\"your-client-secret\",\r\n timeout=60, # Request timeout in seconds\r\n max_retries=5 # Maximum retry attempts\r\n)\r\n```\r\n\r\n## Contributing\r\n\r\nContributions are welcome! Please feel free to submit a Pull Request.\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the LICENSE file for details.\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A clean Python client for the Halo ITSM REST API",
"version": "0.1.0",
"project_urls": {
"Bug Reports": "https://github.com/yourusername/haloitsm-python/issues",
"Changelog": "https://github.com/yourusername/haloitsm-python/blob/main/CHANGELOG.md",
"Documentation": "https://github.com/yourusername/haloitsm-python#readme",
"Homepage": "https://github.com/yourusername/haloitsm-python",
"Repository": "https://github.com/yourusername/haloitsm-python.git"
},
"split_keywords": [
"halo",
" itsm",
" api",
" client",
" service desk",
" ticketing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "802ff3d4065ebc2016b1071de1b581682a47fae7b0faa1d6d101cead943c2c37",
"md5": "85a1e63ea7f0c8b622f3812ed4fb4d0d",
"sha256": "e54da85af1c7e299e84129ca532207cce20d0af0f4d820db576bed41101ad99f"
},
"downloads": -1,
"filename": "haloitsm_python-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "85a1e63ea7f0c8b622f3812ed4fb4d0d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 31311,
"upload_time": "2025-09-01T13:47:01",
"upload_time_iso_8601": "2025-09-01T13:47:01.572365Z",
"url": "https://files.pythonhosted.org/packages/80/2f/f3d4065ebc2016b1071de1b581682a47fae7b0faa1d6d101cead943c2c37/haloitsm_python-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "b73556de8b73d1e9550f5515263d3e793ebbd17602349c59f346c71c9cb94fd7",
"md5": "15ce3e66d4ffebde58fde02e627c5cc2",
"sha256": "ac3f717e695a1ad894c2e62fc1dc893c0ae77c0c9375ea7ae3417f2e80c7395a"
},
"downloads": -1,
"filename": "haloitsm_python-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "15ce3e66d4ffebde58fde02e627c5cc2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 26644,
"upload_time": "2025-09-01T13:47:02",
"upload_time_iso_8601": "2025-09-01T13:47:02.819857Z",
"url": "https://files.pythonhosted.org/packages/b7/35/56de8b73d1e9550f5515263d3e793ebbd17602349c59f346c71c9cb94fd7/haloitsm_python-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-01 13:47:02",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "haloitsm-python",
"github_not_found": true,
"lcname": "haloitsm-python"
}