Skip to main content

Official Python SDK for the Avela Education Platform API

Project description

Avela Python SDK

Official Python SDK for the Avela Education Platform API.

PyPI version Python 3.10+ License: MIT

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 environment
  • qa - QA/Testing environment
  • uat - User Acceptance Testing environment
  • prod - 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

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

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

avela-0.1.0.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

avela-0.1.0-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file avela-0.1.0.tar.gz.

File metadata

  • Download URL: avela-0.1.0.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for avela-0.1.0.tar.gz
Algorithm Hash digest
SHA256 734ce814da59669197e63ffa3d60f133312b5f8c001dcbff72b370a9d4bb3546
MD5 36c5b9a610cf1a615f4d7526caec1856
BLAKE2b-256 5fcb47384caf9bd71379de729b4b292ab37f836ed8bbebb9dddd09ebd5e7544a

See more details on using hashes here.

File details

Details for the file avela-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: avela-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for avela-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6efe09008165705a58a62c69003f03011371e927e082bd4e73580e2f92f32b34
MD5 2226c837f6b0deed3ce9219dee64330c
BLAKE2b-256 4b27f535d30e3509773c66ed3b9ff2f961ef0c45d3094b71d9cb9d1f82b0a43e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page