Python SDK for Credly API v1
Project description
Credly Python API Client
A clean, resource-based Python SDK for Credly's API v1.
Features
- Clean, intuitive interface for all Credly API v1 endpoints
- Automatic pagination support with iterators
- Comprehensive error handling with custom exceptions
- Type hints for better IDE support
- Full support for all major resources:
- Organizations
- Badge Templates
- Issued Badges
- Employees
- Authorization Tokens
- Issuer Authorizations
Installation
Using pip
pip install credly-python-api
From source
git clone https://github.com/kallewesterling/credly-python-api.git
cd credly-python-api
pip install -e .
Quick Start
from credly import Client
# Initialize the client with your API key
client = Client(api_key="your_api_key_here")
# List all organizations
for org in client.organizations.list():
print(org['name'], org['id'])
# Get a specific organization
org = client.organizations.get("org_id")
print(org['name'])
# List badge templates with pagination
for template in client.badge_templates.list("org_id", per=10):
print(template['name'])
Authentication
The Credly API uses Basic Authentication. You need an API key from your Credly account.
Getting Your API Key
- Log in to your Credly account
- Navigate to Settings > API Keys
- Generate a new API key
Using the API Key
from credly import Client
# Method 1: Direct initialization
client = Client(api_key="your_api_key")
# Method 2: Using environment variables
import os
client = Client(api_key=os.getenv("CREDLY_API_KEY"))
Environment Variables
Create a .env file in your project root:
CREDLY_API_KEY=your_api_key_here
CREDLY_BASE_URL=https://api.credly.com
Then use it in your code:
import os
from dotenv import load_dotenv
from credly import Client
load_dotenv()
client = Client(api_key=os.getenv("CREDLY_API_KEY"))
Usage
Organizations
# List all organizations
for org in client.organizations.list():
print(org['name'])
# Get a specific organization
org = client.organizations.get("org_id")
# Update an organization
org = client.organizations.update(
"org_id",
name="New Name",
description="New description"
)
Badge Templates
# List badge templates with filtering and sorting
for template in client.badge_templates.list(
"org_id",
filter="active",
sort="name",
per=20
):
print(template['name'])
# Get a specific template
template = client.badge_templates.get("org_id", "template_id")
# Create a new badge template
template = client.badge_templates.create(
"org_id",
name="Python Expert",
description="Awarded for Python expertise",
image="https://example.com/badge.png",
skills=["Python", "Django", "FastAPI"]
)
# Update a template
template = client.badge_templates.update(
"org_id",
"template_id",
description="Updated description"
)
# Delete a template
client.badge_templates.delete("org_id", "template_id")
Issued Badges
# List issued badges
for badge in client.badges.list("org_id", per=50):
print(badge['recipient_email'])
# Get a specific badge
badge = client.badges.get("org_id", "badge_id")
# Issue a new badge
badge = client.badges.issue(
"org_id",
badge_template_id="template_id",
recipient_email="user@example.com",
issued_at="2024-01-15",
expires_at="2025-01-15"
)
# Revoke a badge
badge = client.badges.revoke(
"org_id",
"badge_id",
reason="No longer valid"
)
# Replace a badge
badge = client.badges.replace(
"org_id",
"old_badge_id",
badge_template_id="new_template_id",
recipient_email="user@example.com"
)
# Bulk search for badges
results = client.badges.bulk_search(
"org_id",
badge_template_id="template_id",
state="accepted"
)
# Delete a badge
client.badges.delete("org_id", "badge_id")
Employees
# List employees
for employee in client.employees.list("org_id"):
print(employee['email'])
# Get a specific employee
employee = client.employees.get("org_id", "employee_id")
# Get employee data
data = client.employees.get_data("org_id", "employee_id")
# Create an employee
employee = client.employees.create(
"org_id",
email="user@example.com",
first_name="John",
last_name="Doe"
)
# Update an employee
employee = client.employees.update(
"org_id",
"employee_id",
first_name="Jane"
)
# Send invitations
response = client.employees.send_invitations(
"org_id",
employee_ids=["emp1", "emp2"],
message="Join our platform!"
)
# List external badges
for badge in client.employees.external_badges("org_id"):
print(badge['name'])
# List employee skills
for skill in client.employees.skills("org_id"):
print(skill['name'])
# Delete an employee
client.employees.delete("org_id", "employee_id")
Authorization Tokens
# List authorization tokens
for token in client.authorization_tokens.list("org_id"):
print(token['name'])
# Create a new token
token = client.authorization_tokens.create(
"org_id",
name="API Token",
scopes=["read", "write"]
)
# Rotate tokens
response = client.authorization_tokens.rotate(
"org_id",
token_id="token_id"
)
Issuer Authorizations
# List issuer authorizations
for auth in client.issuer_authorizations.list("org_id"):
print(auth['id'])
# Get grantors
grantors = client.issuer_authorizations.get_grantors("org_id")
# Delete an authorization
client.issuer_authorizations.delete("org_id", "auth_id")
Pagination
The SDK supports automatic pagination for list operations:
# Automatic pagination - iterates through all pages
for template in client.badge_templates.list("org_id"):
print(template['name'])
# Manual pagination - get specific page
for template in client.badge_templates.list("org_id", page=2, per=20):
print(template['name'])
# Control items per page
for badge in client.badges.list("org_id", per=100):
print(badge['id'])
Error Handling
The SDK provides specific exceptions for different error cases:
from credly import (
Client,
NotFoundError,
ValidationError,
UnauthorizedError,
ForbiddenError,
RateLimitError,
CredlyAPIError
)
client = Client(api_key="your_api_key")
try:
template = client.badge_templates.get("org_id", "template_id")
except NotFoundError as e:
print(f"Template not found: {e.message}")
except ValidationError as e:
print(f"Validation error: {e.message}")
print(f"Response: {e.response}")
except UnauthorizedError as e:
print(f"Authentication failed: {e.message}")
except ForbiddenError as e:
print(f"Access forbidden: {e.message}")
except RateLimitError as e:
print(f"Rate limit exceeded: {e.message}")
except CredlyAPIError as e:
print(f"API error: {e.message} (status: {e.status_code})")
Examples
Check the examples/ directory for more detailed examples:
basic_usage.py- Basic operations with the SDKbadge_management.py- Complete badge lifecycle management
To run the examples:
# Copy the example environment file
cp .env.example .env
# Edit .env and add your API key
# Then run an example
python examples/basic_usage.py
Project Structure
credly-python-api/
├── credly/ # Main package
│ ├── __init__.py # Package exports (Client + exceptions)
│ ├── client.py # Main Client class
│ ├── http.py # HTTP client with auth & error handling
│ ├── exceptions.py # Custom exception classes
│ └── resources/ # API resource modules
│ ├── __init__.py # Resource exports
│ ├── base.py # Base resource class with pagination
│ ├── organizations.py # Organizations resource
│ ├── badge_templates.py # Badge Templates resource
│ ├── badges.py # Issued Badges resource
│ ├── employees.py # Employees resource
│ ├── authorization_tokens.py # Authorization Tokens resource
│ └── issuer_authorizations.py # Issuer Authorizations resource
├── examples/ # Usage examples
│ ├── basic_usage.py # Basic SDK operations
│ └── badge_management.py # Badge lifecycle management
├── setup.py # Package configuration
├── requirements.txt # Project dependencies
├── tests/ # Test suite
│ ├── __init__.py # Test package init
│ ├── test_client.py # Client tests
│ ├── test_http.py # HTTP client tests
│ ├── test_exceptions.py # Exception tests
│ └── test_resources.py # Resource tests
├── .env.example # Example environment variables
├── .gitignore # Git ignore rules
├── LICENSE # MIT License
└── README.md # This file
Core Components
credly/client.py
The main Client class that initializes all resource endpoints and manages the HTTP client instance. This is the primary entry point for users of the SDK.
credly/http.py
HTTP client wrapper that handles:
- Basic Authentication (Base64 encoded
token:format) - Request methods (GET, POST, PUT, DELETE)
- Response parsing
- Error handling and exception raising based on status codes
credly/exceptions.py
Custom exception hierarchy:
CredlyAPIError- Base exceptionUnauthorizedError(401)ForbiddenError(403)NotFoundError(404)ValidationError(422)RateLimitError(429)
credly/resources/base.py
Base resource class providing:
- Common CRUD patterns
- Automatic pagination with iterator support
- URL building helpers
credly/resources/*.py
Individual resource classes implementing specific API endpoints for each resource type (Organizations, Badge Templates, Badges, etc.). Each resource class inherits from BaseResource.
Requirements
- Python 3.7+
- requests >= 2.25.0
API Coverage
This SDK covers all major Credly API v1 endpoints:
- ✅ Organizations (list, get, update)
- ✅ Badge Templates (CRUD + filtering/sorting)
- ✅ Issued Badges (CRUD + replace, revoke, bulk search)
- ✅ Employees (CRUD + invitations, external badges, skills)
- ✅ Authorization Tokens (list, create, rotate)
- ✅ Issuer Authorizations (list, delete, grantors)
Development
Setup
# Clone the repository
git clone https://github.com/kallewesterling/credly-python-api.git
cd credly-python-api
# Install dependencies
pip install -r requirements.txt
# Install in development mode
pip install -e .
Running Tests
The project uses pytest for testing:
# Install test dependencies
pip install -r requirements.txt
# Run all tests
pytest
# Run with coverage
pytest --cov=credly
# Run specific test file
pytest tests/test_client.py
# Run with verbose output
pytest -v
Code Quality & Pre-commit Hooks
This project uses pre-commit hooks to maintain code quality. The hooks run automatically before each commit and check:
- Black: Code formatting
- isort: Import sorting
- Flake8: Linting and style checking
- mypy: Type checking
- pytest: All tests must pass
Setting up pre-commit hooks
# Install pre-commit
pip install pre-commit
# Install the git hooks
pre-commit install
# (Optional) Run against all files
pre-commit run --all-files
Once installed, the hooks will run automatically on git commit. If any hook fails, the commit will be rejected and you'll need to fix the issues.
Running linters manually
# Format code with black
black credly/ tests/
# Sort imports with isort
isort credly/ tests/
# Check with flake8
flake8 credly/ tests/
# Type check with mypy
mypy credly/
# Run all checks
pre-commit run --all-files
Running Examples
# Set up your environment variables
cp .env.example .env
# Edit .env with your API key
# Run examples
python examples/basic_usage.py
python examples/badge_management.py
Contributing
Contributions are welcome! Here's how you can help:
Getting Started
- Fork the repository
- Clone your fork:
git clone https://github.com/kallewesterling/credly-python-api.git - Install dependencies:
pip install -r requirements.txt - Set up pre-commit hooks:
pre-commit install - Create a feature branch:
git checkout -b feature/your-feature-name - Make your changes
- Run tests:
pytest - Commit your changes (pre-commit hooks will run automatically)
- Push to your fork:
git push origin feature/your-feature-name - Open a Pull Request
Adding New Resources
To add a new API resource:
- Create a new file in
credly/resources/(e.g.,new_resource.py) - Create a class that inherits from
BaseResource - Implement the resource methods using
self.http.get(),self.http.post(), etc. - Add pagination support using
self._paginate()for list methods - Export the class in
credly/resources/__init__.py - Add the resource to the
Clientclass incredly/client.py - Update the README with usage examples
Code Style
This project uses automated tools to maintain code quality:
- Black for code formatting (line length: 100)
- isort for import sorting
- Flake8 for linting
- mypy for type checking
These tools run automatically via pre-commit hooks. You can also run them manually:
# Format code
black credly/ tests/
# Check linting
flake8 credly/ tests/
# Type check
mypy credly/
Additional guidelines:
- Use type hints where appropriate
- Include docstrings for all public methods
- Keep methods focused and single-purpose
Testing
When adding new features, please ensure:
- All tests pass:
pytest - Pre-commit hooks pass (they run automatically on commit)
- Add tests for new functionality in the appropriate test file
- Test coverage remains high:
pytest --cov=credly - Code is formatted and linted:
pre-commit run --all-files - Examples demonstrate the new functionality
- Error cases are handled appropriately
License
MIT License - see LICENSE file for details
Support
For issues and questions:
- GitHub Issues: https://github.com/kallewesterling/credly-python-api/issues
- Credly API Documentation: https://www.credly.com/docs/api
Changelog
0.1.0 (2024-01-20)
- Initial release
- Support for all major Credly API v1 endpoints
- Automatic pagination
- Comprehensive error handling
- Full documentation and examples
Project details
Release history Release notifications | RSS feed
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 credly_python_api-0.1.0.tar.gz.
File metadata
- Download URL: credly_python_api-0.1.0.tar.gz
- Upload date:
- Size: 28.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d6fd0aba4cb96a9309d30bb2f7427502b027fe96c38195f5c8ae80935c0e493
|
|
| MD5 |
78f94d19419573431da5f7d997974f23
|
|
| BLAKE2b-256 |
bfa0b516b73605344eeffd0d43af6f2b2f385ca2260ff7961797529440cb266e
|
File details
Details for the file credly_python_api-0.1.0-py3-none-any.whl.
File metadata
- Download URL: credly_python_api-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
752b2b399b11d7ae09faa49ec0e3a425f34e0b966f3439850a0caf203d39fdb7
|
|
| MD5 |
34fd657b1d11eff0e1b9b6defcb289a6
|
|
| BLAKE2b-256 |
371414cb40ed2a6af7dba9732e077f4f7dd61aa589377f7dad53588f76f43bb7
|