Aircall API
A Python client library for the Aircall.io API, providing easy access to Aircall's telephony services.
Features
- Full type hints with Pydantic models
- Comprehensive API coverage for Aircall endpoints
- Simple and intuitive interface
- Built-in authentication handling
- Custom exceptions for proper error handling
- Automatic request/response serialization
- Comprehensive logging support for debugging and monitoring
- Python 3.13+ support
Installation
pip install aircall-api
Or using uv:
uv add aircall-api
Quick Start
from aircall import AircallClient
client = AircallClient(
api_id="your_api_id",
api_token="your_api_token"
)
numbers = client.number.list()
number = client.number.get(12345)
Authentication
To use this library, you'll need your Aircall API credentials:
- Log in to your Aircall Dashboard
- Navigate to Settings > Integrations > API Keys
- Create a new API key or use an existing one
- Use the API ID and API Token to initialize the client
client = AircallClient(
api_id="YOUR_API_ID",
api_token="YOUR_API_TOKEN",
timeout=30,
verbose=False
)
Available Resources
The library provides access to the following Aircall API resources:
- Calls - List, search, retrieve call details, voicemails, and insights
- Contacts - Manage contact information
- Numbers - Manage phone numbers
- Users - Manage team members
- Teams - Manage teams
- Tags - Organize calls and contacts with tags
- Messages - SMS messaging
- Webhooks - Configure webhook endpoints
- Integrations - Manage third-party integrations
- Dialer Campaigns - Manage dialer campaigns
- Companies - Company information
- AI Voice Agents - AI-powered voice agent management
- Conversation Intelligence - Call analytics and insights
Usage Examples
Working with Calls
calls = client.call.list(page=1, per_page=20)
call = client.call.get(call_id=12345)
calls = client.call.search(from_date="2024-01-01", to_date="2024-01-31")
Working with Contacts
contacts = client.contact.list()
contact = client.contact.create(
first_name="John",
last_name="Doe",
phone_numbers=[{"label": "Work", "value": "+1234567890"}],
emails=[{"label": "Office", "value": "john.doe@example.com"}]
)
client.contact.update(
contact_id=12345,
emails=[{"label": "Personal", "value": "john@example.com"}]
)
contacts = client.contact.search(phone_number="+1234567890")
Working with Numbers
numbers = client.number.list()
number = client.number.get(number_id=12345)
Error Handling
The library provides custom exceptions for different error scenarios. All exceptions inherit from AircallError:
from aircall import (
AircallClient,
ValidationError,
AuthenticationError,
NotFoundError,
UnprocessableEntityError,
RateLimitError,
ServerError,
AircallConnectionError,
AircallTimeoutError,
)
client = AircallClient(api_id="your_id", api_token="your_token")
try:
contact = client.contact.get(12345)
except NotFoundError:
print("Contact not found")
except AuthenticationError:
print("Invalid API credentials")
except RateLimitError as e:
print(f"Rate limit exceeded. Retry after {e.retry_after} seconds")
except ValidationError as e:
print(f"Invalid request: {e.message}")
except AircallTimeoutError:
print("Request timed out")
except AircallConnectionError:
print("Failed to connect to Aircall API")
Available Exceptions
ValidationError (400) - Invalid request payload or bad request
AuthenticationError (401, 403) - Invalid API credentials
NotFoundError (404) - Resource not found
UnprocessableEntityError (422) - Server unable to process the request
RateLimitError (429) - Rate limit exceeded (includes retry_after attribute)
ServerError (5xx) - Aircall server error
AircallConnectionError - Network connection failed
AircallTimeoutError - Request timed out
All exceptions include:
message: Error description
status_code: HTTP status code (for API errors)
response_data: Full error response from the API (if available)
Logging
The Aircall SDK includes comprehensive logging capabilities to help you debug issues, monitor API requests, and track application behavior.
Quick Start with Logging
Enable debug logging with the verbose parameter:
from aircall import AircallClient
client = AircallClient(
api_id="your_api_id",
api_token="your_api_token",
verbose=True
)
numbers = client.number.list()
Configuring Logging Levels
For more control, configure logging manually using Python's standard logging module:
import logging
from aircall import AircallClient, configure_logging
configure_logging(logging.INFO)
logging.getLogger('aircall.client').setLevel(logging.DEBUG)
logging.getLogger('aircall.resources').setLevel(logging.INFO)
client = AircallClient(api_id="your_id", api_token="your_token")
Log Levels and What They Capture
-
DEBUG: Detailed request/response information
- Request method, URL, query parameters, request body
- Response status codes and timing
- Example:
Request: GET https://api.aircall.io/v1/numbers?page=1
-
INFO: High-level operation information
- Client initialization
- Critical operations (call transfers, deletions)
- Example:
Aircall client initialized
-
WARNING: Important events that may need attention
- API errors and HTTP error status codes
- Rate limit warnings
- Destructive operations (deleting recordings/voicemails)
- Example:
API error: 404 GET /calls/999 - Not Found (took 0.34s)
-
ERROR: Failures and exceptions
- Connection errors
- Timeout errors
- Example:
Request timeout: GET /calls - Failed after 30s
Advanced Logging Configuration
Logging to a File
import logging
from aircall import AircallClient
logging.basicConfig(
filename='aircall_api.log',
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
client = AircallClient(api_id="your_id", api_token="your_token")
Custom Logger Configuration
import logging
from aircall import AircallClient
logger = logging.getLogger('aircall')
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'%(asctime)s [%(name)s] %(levelname)s: %(message)s'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
client = AircallClient(api_id="your_id", api_token="your_token")
Filtering Logs by Resource
Each resource has its own logger namespace:
import logging
logging.getLogger('aircall.resources.CallResource').setLevel(logging.DEBUG)
logging.getLogger('aircall.resources.ContactResource').setLevel(logging.CRITICAL)
Example Log Output
With verbose=True or DEBUG level logging enabled:
2025-11-09 10:30:45 - aircall.client - INFO - Aircall client initialized
2025-11-09 10:30:46 - aircall.client - DEBUG - Request: GET https://api.aircall.io/v1/numbers
2025-11-09 10:30:46 - aircall.client - DEBUG - Query params: {'page': 1, 'per_page': 20}
2025-11-09 10:30:46 - aircall.client - DEBUG - Response: 200 GET https://api.aircall.io/v1/numbers (took 0.23s)
2025-11-09 10:30:47 - aircall.resources.CallResource - INFO - Transferring call 12345 to number 67890
2025-11-09 10:30:47 - aircall.client - DEBUG - Request: POST https://api.aircall.io/v1/calls/12345/transfers
2025-11-09 10:30:47 - aircall.client - DEBUG - Request body: {'number_id': 67890}
2025-11-09 10:30:48 - aircall.client - DEBUG - Response: 200 POST https://api.aircall.io/v1/calls/12345/transfers (took 0.45s)
2025-11-09 10:30:48 - aircall.resources.CallResource - INFO - Successfully transferred call 12345
Best Practices
- Production: Use
INFO or WARNING level to avoid logging sensitive request/response data
- Development: Use
DEBUG level or verbose=True for detailed troubleshooting
- Monitoring: Use
WARNING level to track API errors and rate limits
- File Logging: Always use file logging in production for audit trails
- Sensitive Data: Be cautious about logging request bodies that might contain PII
Development
Setup
This project uses uv for dependency management.
git clone https://github.com/yourusername/aircall-api.git
cd aircall-api
uv sync
source .venv/bin/activate
.venv\Scripts\activate
Testing
pytest
pytest --cov=aircall
Linting
ruff check .
pylint src/aircall
Project Structure
aircall-api/
├── src/
│ └── aircall/
│ ├── __init__.py
│ ├── client.py # Main API client
│ ├── exceptions.py # Custom exceptions
│ ├── models/ # Pydantic models
│ │ ├── call.py
│ │ ├── contact.py
│ │ ├── user.py
│ │ └── ...
│ └── resources/ # API resource handlers
│ ├── base.py
│ ├── call.py
│ ├── contact.py
│ └── ...
├── tests/ # Test suite
├── pyproject.toml # Project configuration
└── README.md
Requirements
- Python >= 3.13
- requests >= 2.32.5
- pydantic >= 2.12.4
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature)
- Commit your changes (
git commit -m 'Add some amazing feature')
- Push to the branch (
git push origin feature/amazing-feature)
- Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Resources
Support
For issues and questions: