Avela Python SDK
Official Python SDK for the Avela Education Platform API.
Features
- ✅ Dynamic endpoint access - No need to update SDK when new endpoints are added
- ✅ OAuth2 authentication - Automatic token management and refresh
- ✅ Type hints - Full type annotations for better IDE support
- ✅ Modern Python - Built for Python 3.10+
- ✅ Session management - Connection pooling for better performance
- ✅ Error handling - Comprehensive exception hierarchy
- ✅ Environment support - Works with dev, qa, uat, and production
Installation
pip install avela
Quick Start
from avela import AvelaAPI
# Initialize the client
api = AvelaAPI(
client_id="your_client_id",
client_secret="your_client_secret",
environment="uat" # or "dev", "qa", "prod"
)
# List applicants
applicants = api.applicants.list(limit=100, offset=0)
# Get a specific form
form = api.forms.get("form-id-123")
# Update form questions
api.forms.call("POST", "form-id/questions", json={
"questions": [
{
"key": "student_name",
"type": "FreeText",
"answer": {"free_text": {"value": "John Doe"}}
}
]
})
Authentication
Getting API Credentials
Contact Avela Support for API credentials at info@avela.org.
Environment Options
dev- Development environmentqa- QA/Testing environmentuat- User Acceptance Testing environmentprod- Production environment
Resource-Specific Request Formats
Important: Different API resources require data to be wrapped in resource-specific keys. This is an API requirement, not an SDK limitation.
Common Wrapper Patterns
# Applicants - require "applicant" wrapper for create/update/patch
api.applicants.create({
"applicant": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com"
}
})
api.applicants.update("applicant-id", {
"applicant": {
"middle_name": "test"
}
})
# Forms questions - require "questions" array wrapper
api.forms.call("POST", "form-id/questions", json={
"questions": [
{
"key": "internal1",
"type": "FreeText",
"answer": {"free_text": {"value": "Updated value"}}
}
]
})
Note: Consult the Avela API Documentation for specific wrapper requirements for each resource type.
Usage Examples
Listing Resources
# List all applicants with pagination
applicants = api.applicants.list(limit=100, offset=0)
# List with filters
applicants = api.applicants.list(
limit=50,
reference_id=["450156", "450157"]
)
Getting a Single Resource
# Get a specific form by ID
form = api.forms.get("e4c2f10d-b94a-49eb-b6b2-a129b0840f90")
# Get an applicant
applicant = api.applicants.get("b28a524c-1c3d-43be-8620-02319bb8fbaa")
Creating Resources
# Create a new applicant (note: requires "applicant" wrapper)
new_applicant = api.applicants.create({
"applicant": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"birth_date": "2005-03-15"
}
})
Updating Resources
# Update an applicant (note: requires "applicant" wrapper)
updated = api.applicants.update("b28a524c-1c3d-43be-8620-02319bb8fbaa", {
"applicant": {
"middle_name": "test"
}
})
# Partial update (PATCH) - also requires wrapper
patched = api.applicants.patch("applicant-id", {
"applicant": {
"phone_number": "555-0123"
}
})
Custom Endpoint Calls
For endpoints that don't fit the standard REST pattern:
# Update form questions (custom endpoint)
api.forms.call("POST", "form-id/questions", json={
"questions": [
{
"key": "internal1",
"type": "FreeText",
"answer": {"free_text": {"value": "Updated value"}}
}
]
})
# Any custom endpoint
response = api.custom_resource.call("GET", "special/endpoint", params={"filter": "value"})
Context Manager
Use with a context manager to automatically close sessions:
with AvelaAPI(client_id, client_secret, environment="uat") as api:
applicants = api.applicants.list()
# Session automatically closed when exiting the block
Dynamic Endpoint Access
The SDK uses dynamic endpoint proxies, which means you can access any API endpoint without the SDK needing an update:
# These all work automatically:
api.applicants.list()
api.forms.get("id")
api.organizations.list()
api.any_new_resource.create({...}) # Works even if endpoint was just added!
Available Methods on All Resources
Every resource proxy provides these methods:
list(**params)- GET /{resource}get(id)- GET /{resource}/{id}create(data)- POST /{resource}update(id, data)- PUT /{resource}/{id}patch(id, data)- PATCH /{resource}/{id}delete(id)- DELETE /{resource}/{id}call(method, path, **kwargs)- Custom requests
Error Handling
The SDK provides a comprehensive exception hierarchy:
from avela import (
AvelaAPI,
AvelaError, # Base exception
APIError, # General API errors
AuthenticationError, # Auth failures
ValidationError, # 400 errors
NotFoundError, # 404 errors
RateLimitError, # 429 errors
ServerError, # 5xx errors
)
try:
api = AvelaAPI(client_id, client_secret)
applicants = api.applicants.list()
except AuthenticationError as e:
print(f"Authentication failed: {e}")
except NotFoundError as e:
print(f"Resource not found: {e}")
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
except ValidationError as e:
print(f"Validation error: {e}")
except ServerError as e:
print(f"Server error [{e.status_code}]: {e}")
except APIError as e:
print(f"API error: {e}")
Advanced Usage
Custom Timeout
# Set custom timeout (default is 30 seconds)
api = AvelaAPI(
client_id,
client_secret,
environment="uat",
timeout=60 # 60 seconds
)
Manual Token Refresh
# The SDK automatically refreshes tokens, but you can do it manually:
api.auth.authenticate()
# Check if token is expired
if api.auth.is_token_expired():
api.auth.authenticate()
Direct HTTP Access
# Access the underlying session for custom requests
response = api.session.get(
"https://custom.api.endpoint.com/resource",
headers=api.auth.get_auth_headers()
)
Generating Custom Examples with AI
You can use an LLM to generate custom examples tailored to your specific use case. Here's a prompt template:
I'm using the Avela Python SDK to interact with the Avela Education Platform API.
SDK Installation:
pip install avela
Basic SDK Usage:
- Initialize: api = AvelaAPI(client_id="...", client_secret="...", environment="uat")
- Dynamic endpoints: api.{resource}.list(), api.{resource}.get(id), api.{resource}.create(data)
- Custom calls: api.{resource}.call(method, path, **kwargs)
Important API Requirements:
- Applicants require {"applicant": {...}} wrapper for create/update/patch
- Forms questions require {"questions": [...]} wrapper
- Refer to https://avela.org/api for specific wrapper requirements
My use case:
[Describe what you want to accomplish, e.g., "Fetch all applicants born after 2020 and export to Excel"]
Please generate a complete Python script with:
1. Proper error handling
2. Pagination if needed
3. Progress indicators
4. Comments explaining each step
Complete Examples
Fetching and Processing Applicants
from avela import AvelaAPI
import csv
# Initialize API
api = AvelaAPI(
client_id="your_client_id",
client_secret="your_client_secret",
environment="uat"
)
# Fetch all applicants with pagination
all_applicants = []
offset = 0
limit = 1000
while True:
batch = api.applicants.list(limit=limit, offset=offset)
if not batch:
break
all_applicants.extend(batch)
offset += limit
# Export to CSV
with open("applicants.csv", "w") as f:
writer = csv.DictWriter(f, fieldnames=all_applicants[0].keys())
writer.writeheader()
writer.writerows(all_applicants)
print(f"Exported {len(all_applicants)} applicants")
Bulk Updating Forms
from avela import AvelaAPI
import csv
api = AvelaAPI(client_id, client_secret, environment="uat")
# Read updates from CSV
with open("form_updates.csv") as f:
reader = csv.DictReader(f)
for row in reader:
form_id = row["form_id"]
question_key = row["question_key"]
answer_value = row["answer_value"]
# Update form question
api.forms.call("POST", f"{form_id}/questions", json={
"questions": [{
"key": question_key,
"type": "FreeText",
"answer": {"free_text": {"value": answer_value}}
}]
})
print(f"✓ Updated {form_id} - {question_key}")
Contributing
Contributions are welcome! We'd love your help improving the Avela Python SDK.
For development setup, testing, and publishing instructions, see CONTRIBUTING.md
Quick links:
Support
- Issues: GitHub Issues
- Email: info@avela.org
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
0.1.0 (2025-01-12)
- Initial release
- OAuth2 authentication with automatic token refresh
- Dynamic endpoint access for all API resources
- Comprehensive error handling
- Support for all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Type hints throughout
- Context manager support
Metadata
Release files for avela 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| avela-0.1.0.tar.gz | 14.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| avela-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.8 kB
Release files / avela-0.1.0.tar.gz
| Download URL | avela-0.1.0.tar.gz |
|---|---|
| Size | 14.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
734ce814da59669197e63ffa3d60f133312b5f8c001dcbff72b370a9d4bb3546
|
|
BLAKE2b-256 checksum How to use checksums |
5fcb47384caf9bd71379de729b4b292ab37f836ed8bbebb9dddd09ebd5e7544a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|
Release files / avela-0.1.0-py3-none-any.whl
| Download URL | avela-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6efe09008165705a58a62c69003f03011371e927e082bd4e73580e2f92f32b34
|
|
BLAKE2b-256 checksum How to use checksums |
4b27f535d30e3509773c66ed3b9ff2f961ef0c45d3094b71d9cb9d1f82b0a43e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|