Skip to main content

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
  • Dot notation access for resource properties (e.g., badge.id instead of badge['id'])
  • Backward compatible with bracket notation
  • 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 - use clean dot notation
for org in client.organizations.list():
    print(org.name, org.id)

# Get a specific organization
org = client.organizations.get("org_id")
print(org.name)  # Dot notation (recommended)
print(org['name'])  # Bracket notation (also works)

# 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

  1. Log in to your Credly account
  2. Navigate to Settings > API Keys
  3. 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"))

Accessing Resource Properties

All resources returned by the API support both dot notation and bracket notation for accessing properties.

Dot Notation (Recommended)

The cleaner, more Pythonic way to access resource properties:

badge = client.badges.get(org_id, badge_id)

# Access properties with dot notation
print(badge.id)
print(badge.recipient_email)
print(badge.state)
print(badge.issued_at)

Bracket Notation (Backward Compatible)

Traditional dictionary-style access still works:

badge = client.badges.get(org_id, badge_id)

# Access properties with bracket notation
print(badge['id'])
print(badge['recipient_email'])
print(badge['state'])

Additional Methods

# Get with default value
email = badge.get('recipient_email', 'unknown@example.com')

# Check if property exists
if 'expired_at' in badge:
    print(f"Expired: {badge.expired_at}")

# Convert to plain dictionary
badge_dict = badge.to_dict()

# Works with iteration too
for org in client.organizations.list():
    print(f"{org.name} - {org.id}")

Usage

Organizations

# List all organizations
for org in client.organizations.list():
    print(org.name)

# Get a specific organization
org = client.organizations.get("org_id")
print(org.name, 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")
print(badge.id, badge.state)

# 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")
print(employee.first_name, employee.last_name)

# 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 SDK
  • badge_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 exception
  • UnauthorizedError (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

  1. Fork the repository
  2. Clone your fork: git clone https://github.com/kallewesterling/credly-python-api.git
  3. Install dependencies: pip install -r requirements.txt
  4. Set up pre-commit hooks: pre-commit install
  5. Create a feature branch: git checkout -b feature/your-feature-name
  6. Make your changes
  7. Run tests: pytest
  8. Commit your changes (pre-commit hooks will run automatically)
  9. Push to your fork: git push origin feature/your-feature-name
  10. Open a Pull Request

Adding New Resources

To add a new API resource:

  1. Create a new file in credly/resources/ (e.g., new_resource.py)
  2. Create a class that inherits from BaseResource
  3. Implement the resource methods using self.http.get(), self.http.post(), etc.
  4. Add pagination support using self._paginate() for list methods
  5. Export the class in credly/resources/__init__.py
  6. Add the resource to the Client class in credly/client.py
  7. 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:

Changelog

0.2.0 (2026-01-20)

  • New Feature: Added dot notation access for resource properties
    • Access properties using badge.id instead of badge['id']
    • Fully backward compatible with bracket notation
    • Works with all resource types and paginated results
  • Added ResourceData wrapper class for enhanced property access
  • Added comprehensive tests for dot notation functionality
  • Updated documentation with dot notation examples

0.1.0 (2026-01-20)

  • Initial release
  • Support for all major Credly API v1 endpoints
  • Automatic pagination
  • Comprehensive error handling
  • Full documentation and examples

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

credly_python_api-0.2.0.tar.gz (32.0 kB view details)

Uploaded Source

Built Distribution

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

credly_python_api-0.2.0-py3-none-any.whl (25.0 kB view details)

Uploaded Python 3

File details

Details for the file credly_python_api-0.2.0.tar.gz.

File metadata

  • Download URL: credly_python_api-0.2.0.tar.gz
  • Upload date:
  • Size: 32.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for credly_python_api-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5d60600a401a4d79794b398967edac664775cf8bc04c8e7f5dd030164c3f92e9
MD5 d3eedaa2b51a0248cc8d0dc04a822881
BLAKE2b-256 2689ce1173d3be01d328a47cae5945fc51adfa667e41beea2f51dd3e5bca6aa7

See more details on using hashes here.

File details

Details for the file credly_python_api-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for credly_python_api-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 efee6c0ac38ecd0a5b44400ca9909e4e257f72454c0a87d70d7aabc24fe211da
MD5 8c31caef2079971bf9a51577fdbb4e10
BLAKE2b-256 70ae57fa7b340122f50aacb8b65180c2ede31ade3977039dff62bb6dad3f21e9

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