Skip to main content

A comprehensive Python SDK for the Blaaiz RaaS (Remittance as a Service) API

Project description

Blaaiz Python SDK

A comprehensive Python SDK for the Blaaiz RaaS (Remittance as a Service) API. This SDK provides easy-to-use methods for payment processing, collections, payouts, customer management, and more.

Installation

pip install blaaiz-python-sdk

Quick Start

from blaaiz import Blaaiz

# Initialize the SDK
blaaiz = Blaaiz('your-api-key-here', base_url='https://api-dev.blaaiz.com')

# Test the connection
is_connected = blaaiz.test_connection()
print(f'API Connected: {is_connected}')

Authentication

The SDK supports two authentication methods: OAuth 2.0 client credentials (recommended) and a legacy API key.

OAuth 2.0 (client credentials)

Provide a client_id and client_secret. The SDK fetches a bearer token from POST {base_url}/oauth/token, caches it in memory, and refreshes it automatically 60 seconds before it expires.

import os
from blaaiz import Blaaiz

blaaiz = Blaaiz(
    client_id=os.environ['BLAAIZ_CLIENT_ID'],
    client_secret=os.environ['BLAAIZ_CLIENT_SECRET'],
)

By default the SDK requests the full set of scopes. Pass oauth_scope (a space-separated string) to request a narrower set:

blaaiz = Blaaiz(
    client_id=os.environ['BLAAIZ_CLIENT_ID'],
    client_secret=os.environ['BLAAIZ_CLIENT_SECRET'],
    oauth_scope='wallet:read transaction:read',
)

Legacy API key

import os
from blaaiz import Blaaiz

blaaiz = Blaaiz(os.environ['BLAAIZ_API_KEY'])

When both OAuth credentials and an API key are configured, OAuth is used. If neither a client_id/client_secret pair nor an api_key is provided, a BlaaizError is raised.

Features

  • Customer Management: Create, update, and manage customers with KYC verification
  • Collections: Support for multiple collection methods (Open Banking, Card, Crypto, Bank Transfer)
  • Payouts: Bank transfers and Interac payouts across multiple currencies
  • Virtual Bank Accounts: Create and manage virtual accounts for NGN collections
  • Wallets: Multi-currency wallet management
  • Transactions: Transaction history and status tracking
  • Webhooks: Webhook configuration and management with signature verification
  • Files: Document upload with pre-signed URLs
  • Fees: Real-time fee calculations and breakdowns
  • Banks & Currencies: Access to supported banks and currencies

Supported Currencies & Methods

Collections

  • CAD: Interac (push mechanism)
  • NGN: Bank Transfer (VBA) and Card Payment
  • USD: Card Payment
  • EUR/GBP: Open Banking

Payouts

  • Bank Transfer: All supported currencies
  • Interac: CAD transactions

API Reference

Customer Management

Create a Customer

# Individual customer
customer = blaaiz.customers.create({
    'first_name': "John",  # Required for individual
    'last_name': "Doe",    # Required for individual
    'type': "individual",
    'email': "john.doe@example.com",
    'country': "NG",
    'id_type': "passport",  # drivers_license, passport, id_card, resident_permit
    'id_number': "A12345678",
})

# Business customer
business_customer = blaaiz.customers.create({
    'type': "business",
    'business_name': "Company Name",  # Required for business
    'email': "business@example.com",
    'country': "NG",
    'id_type': "certificate_of_incorporation",
    'id_number': "RC123456",
})

print(f'Customer ID: {customer["data"]["data"]["id"]}')

Get Customer

customer = blaaiz.customers.get('customer-id')
print(f'Customer: {customer["data"]}')

List All Customers

customers = blaaiz.customers.list()
print(f'Customers: {customers["data"]}')

You can also pass optional filters and opt-in pagination. Supported filters are email, id_number, registration_number, verification_status, and type. Set paginate=True to receive a paginated response that includes links and meta (with current_page, total, etc.) alongside data.

verified = blaaiz.customers.list({
    "email": "john@example.com",
    "verification_status": "VERIFIED",
    "type": "individual",
    "paginate": True,
})
print(f'Page: {verified["data"]["meta"]["current_page"]}')
print(f'Customers: {verified["data"]["data"]}')

Update Customer

updated_customer = blaaiz.customers.update('customer-id', {
    'first_name': "Jane",
    'email': "jane.doe@example.com"
})

List Customer Beneficiaries

beneficiaries = blaaiz.customers.list_beneficiaries('customer-id')
print(f'Beneficiaries: {beneficiaries["data"]}')

Get Specific Beneficiary

beneficiary = blaaiz.customers.get_beneficiary('customer-id', 'beneficiary-id')
print(f'Beneficiary: {beneficiary["data"]}')

### File Management & KYC

#### Upload Customer Documents

**Method 1: Complete File Upload (Recommended)**
```python
# Option A: Upload from bytes
with open('passport.jpg', 'rb') as f:
    file_data = f.read()

result = blaaiz.customers.upload_file_complete('customer-id', {
    'file': file_data,
    'file_category': 'identity',  # identity, proof_of_address, liveness_check
    'filename': 'passport.jpg',
    'content_type': 'image/jpeg'
})

# Option B: Upload from Base64 string
result = blaaiz.customers.upload_file_complete('customer-id', {
    'file': 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
    'file_category': 'identity'
})

# Option C: Upload from Data URL
result = blaaiz.customers.upload_file_complete('customer-id', {
    'file': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
    'file_category': 'identity'
})

# Option D: Upload from Public URL
result = blaaiz.customers.upload_file_complete('customer-id', {
    'file': 'https://example.com/documents/passport.jpg',
    'file_category': 'identity'
})

print(f'Upload complete: {result["data"]}')
print(f'File ID: {result["file_id"]}')

Method 2: Manual 3-Step Process

# Step 1: Get pre-signed URL
presigned_url = blaaiz.files.get_presigned_url({
    'customer_id': 'customer-id',
    'file_category': 'identity'
})

# Step 2: Upload file to the pre-signed URL (implement your file upload logic)
# Step 3: Associate file with customer
file_association = blaaiz.customers.upload_files('customer-id', {
    'id_file': presigned_url['data']['data']['file_id']
})

Collections

Initiate Open Banking Collection (EUR/GBP)

collection = blaaiz.collections.initiate({
    'customer_id': "customer-id",
    'wallet_id': "wallet-id",
    'amount': 100.00,
    'currency': "EUR",  # or "GBP"
    'method': "open_banking",
    'phone': "+1234567890"  # Optional
})

print(f'Payment URL: {collection["data"]["url"]}')
print(f'Transaction ID: {collection["data"]["transaction_id"]}')

Initiate Card Collection (NGN/USD)

collection = blaaiz.collections.initiate({
    'customer_id': "customer-id",
    'wallet_id': "wallet-id",
    'amount': 5000,
    'currency': "NGN",  # or "USD"
    'method': "card",
})

print(f'Payment URL: {collection["data"]["url"]}')

Crypto Collection

# Get available networks
networks = blaaiz.collections.get_crypto_networks()
print(f'Available networks: {networks["data"]}')

# Initiate crypto collection
crypto_collection = blaaiz.collections.initiate_crypto({
    'amount': 100,
    'network': "ethereum",
    'token': "USDT",
    'wallet_id': "wallet-id"
})

Attach Customer to Collection

attachment = blaaiz.collections.attach_customer({
    'customer_id': "customer-id",
    'transaction_id': "transaction-id"
})

Accept Interac Money Request (CAD)

result = blaaiz.collections.accept_interac_money_request({
    'reference_number': "interac-reference-number"
})

Payouts

Bank Transfer Payout (NGN)

payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "bank_transfer",
    'from_amount': 1000,  # OR use 'to_amount' for exact recipient amount
    'from_currency_id': "NGN",
    'to_currency_id': "NGN",
    'bank_id': "1",
    'account_number': "0123456789",
    'note': "Acme Ltd",  # Optional; appears in the transaction description (defaults to your business name if omitted)
})

print(f'Payout Status: {payout["data"]["transaction"]["status"]}')

Passing additional fields

The initiate() method forwards your payload verbatim to the API, so any field documented in the Blaaiz API reference can be included even if it is not shown in the examples above. For instance, the optional note field (used in the NGN example) populates the transaction description and defaults to your business name when omitted. Extra keys are passed through unchanged and are never stripped or rejected by the SDK.

Bank Transfer Payout (GBP)

gbp_payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "bank_transfer",
    'from_amount': 500,
    'from_currency_id': "GBP",
    'to_currency_id': "GBP",
    'sort_code': "12-34-56",
    'account_number': "12345678",
    'account_name': "John Doe",
})

Bank Transfer Payout (EUR)

eur_payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "bank_transfer",
    'from_amount': 500,
    'from_currency_id': "EUR",
    'to_currency_id': "EUR",
    'iban': "DE89370400440532013000",
    'bic_code': "COBADEFFXXX",
    'account_name': "John Doe",
})

Interac Payout (CAD)

interac_payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "interac",
    'from_amount': 100,
    'from_currency_id': "CAD",
    'to_currency_id': "CAD",
    'email': "recipient@example.com",
    'interac_first_name': "John",
    'interac_last_name': "Doe"
})

ACH Payout (USD)

ach_payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "ach",
    'from_amount': 1000,
    'from_currency_id': "USD",
    'to_currency_id': "USD",
    'type': "individual",  # or "business"
    'account_number': "123456789",
    'account_name': "John Doe",
    'account_type': "checking",  # or "savings"
    'bank_name': "Chase Bank",
    'routing_number': "021000021",
})

Wire Payout (USD)

wire_payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "wire",
    'from_amount': 5000,
    'from_currency_id': "USD",
    'to_currency_id': "USD",
    'type': "individual",
    'account_number': "123456789",
    'account_name': "John Doe",
    'account_type': "checking",
    'bank_name': "Chase Bank",
    'routing_number': "021000021",
    'swift_code': "CHASUS33",
})

Crypto Payout (USD)

crypto_payout = blaaiz.payouts.initiate({
    'wallet_id': "wallet-id",
    'customer_id': "customer-id",
    'method': "crypto",
    'from_amount': 100,
    'from_currency_id': "USD",
    'to_currency_id': "USD",
    'wallet_address': "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
    'wallet_token': "USDT",
    'wallet_network': "ethereum",
})

Virtual Bank Accounts

Create Virtual Bank Account

vba = blaaiz.virtual_bank_accounts.create({
    'wallet_id': "wallet-id",
    'account_name': "John Doe"
})

print(f'Account Number: {vba["data"]["account_number"]}')
print(f'Bank Name: {vba["data"]["bank_name"]}')

List Virtual Bank Accounts

# Filter by wallet ID
vbas = blaaiz.virtual_bank_accounts.list(wallet_id="wallet-id")
print(f'Virtual Accounts: {vbas["data"]}')

# Filter by customer ID
vbas = blaaiz.virtual_bank_accounts.list(customer_id="customer-id")

# Filter by both
vbas = blaaiz.virtual_bank_accounts.list(wallet_id="wallet-id", customer_id="customer-id")

Get Virtual Bank Account

vba = blaaiz.virtual_bank_accounts.get("vba-id")
print(f'Account Details: {vba["data"]}')

Close Virtual Bank Account

result = blaaiz.virtual_bank_accounts.close("vba-id", reason="No longer needed")
print(f'Closed: {result["data"]}')

Get Identification Type Requirements

# Using customer ID
id_types = blaaiz.virtual_bank_accounts.get_identification_type(customer_id="customer-id")

# Using country and type
id_types = blaaiz.virtual_bank_accounts.get_identification_type(country="US", type="individual")
print(f'Required ID Types: {id_types["data"]}')

Wallets

List All Wallets

wallets = blaaiz.wallets.list()
print(f'Wallets: {wallets["data"]}')

Get Specific Wallet

wallet = blaaiz.wallets.get("wallet-id")
print(f'Wallet Balance: {wallet["data"]["balance"]}')

Transactions

List Transactions

transactions = blaaiz.transactions.list({
    'page': 1,
    'limit': 10,
    'status': "SUCCESSFUL"  # Optional filter
})

print(f'Transactions: {transactions["data"]}')

Get Transaction Details

transaction = blaaiz.transactions.get("transaction-id")
print(f'Transaction: {transaction["data"]}')

Banks & Currencies

List Banks

banks = blaaiz.banks.list()
print(f'Available Banks: {banks["data"]}')

Bank Account Lookup

account_info = blaaiz.banks.lookup_account({
    'account_number': "0123456789",
    'bank_id': "1"
})

print(f'Account Name: {account_info["data"]["account_name"]}')

List Currencies

currencies = blaaiz.currencies.list()
print(f'Supported Currencies: {currencies["data"]}')

Fees

Get Fee Breakdown

# Calculate fees based on amount you want to send
fee_breakdown = blaaiz.fees.get_breakdown({
    'from_currency_id': "NGN",
    'to_currency_id': "CAD",
    'from_amount': 100000
})

print(f'You send: {fee_breakdown["data"]["you_send"]}')
print(f'Recipient gets: {fee_breakdown["data"]["recipient_gets"]}')
print(f'Total fees: {fee_breakdown["data"]["total_fees"]}')

# OR calculate fees based on exact amount recipient should receive
fee_breakdown = blaaiz.fees.get_breakdown({
    'from_currency_id': "NGN",
    'to_currency_id': "CAD",
    'to_amount': 500  # Recipient gets exactly 500 CAD
})

Webhooks

Register Webhooks

webhook = blaaiz.webhooks.register({
    'collection_url': "https://your-domain.com/webhooks/collection",
    'payout_url': "https://your-domain.com/webhooks/payout"
})

Get Webhook Configuration

webhook_config = blaaiz.webhooks.get()
print(f'Webhook URLs: {webhook_config["data"]}')

Replay Webhook

replay = blaaiz.webhooks.replay({
    'transaction_id': "transaction-id"
})

Simulate Interac Webhook (Non-Production Only)

# Only available in non-production environments
result = blaaiz.webhooks.simulate_interac_webhook({
    'amount': 100,
    'collection_email': "sender@example.com"
})

Advanced Usage

Complete Payout Workflow

complete_payout_result = blaaiz.create_complete_payout({
    'customer_data': {
        'first_name': "John",
        'last_name': "Doe",
        'type': "individual",
        'email': "john@example.com",
        'country': "NG",
        'id_type': "passport",
        'id_number': "A12345678"
    },
    'payout_data': {
        'wallet_id': "wallet-id",
        'method': "bank_transfer",
        'from_amount': 1000,  # OR 'to_amount' for exact recipient amount
        'from_currency_id': "NGN",
        'to_currency_id': "NGN",
        'bank_id': "1",
        'account_number': "0123456789",
    }
})

print(f'Customer ID: {complete_payout_result["customer_id"]}')
print(f'Payout: {complete_payout_result["payout"]}')
print(f'Fees: {complete_payout_result["fees"]}')

Complete Collection Workflow

complete_collection_result = blaaiz.create_complete_collection({
    'customer_data': {
        'first_name': "Jane",
        'last_name': "Smith",
        'type': "individual",
        'email': "jane@example.com",
        'country': "NG",
        'id_type': "drivers_license",
        'id_number': "ABC123456"
    },
    'collection_data': {
        'method': "card",
        'amount': 5000,
        'currency': "NGN",
        'wallet_id': "wallet-id"
    },
    'create_vba': True  # Optionally create a virtual bank account
})

print(f'Customer ID: {complete_collection_result["customer_id"]}')
print(f'Collection: {complete_collection_result["collection"]}')
print(f'Virtual Account: {complete_collection_result["virtual_account"]}')

Context Manager Support

with Blaaiz('your-api-key') as blaaiz:
    customers = blaaiz.customers.list()
    print(f'Total customers: {len(customers["data"])}')

Error Handling

The SDK uses a custom BlaaizError class that provides detailed error information:

from blaaiz import Blaaiz, BlaaizError

try:
    blaaiz = Blaaiz('your-api-key')
    customer = blaaiz.customers.create(invalid_data)
except BlaaizError as e:
    print(f'Blaaiz API Error: {e.message}')
    print(f'Status Code: {e.status}')
    print(f'Error Code: {e.code}')
except Exception as e:
    print(f'Unexpected Error: {str(e)}')

Webhook Handling

Webhook Signature Verification

The SDK provides built-in webhook signature verification. Blaaiz uses HMAC-SHA256 to sign webhooks with the format timestamp.payload.

from blaaiz import Blaaiz

blaaiz = Blaaiz('your-api-key')

# Method 1: Verify signature manually
is_valid = blaaiz.webhooks.verify_signature(
    raw_body,       # Raw webhook payload string
    signature,      # x-blaaiz-signature header
    timestamp,      # x-blaaiz-timestamp header
    webhook_secret  # Your API secret key
)

if is_valid:
    print('Webhook signature is valid')
else:
    print('Invalid webhook signature')

# Method 2: Construct verified event (recommended)
try:
    event = blaaiz.webhooks.construct_event(
        payload,        # Raw webhook payload string
        signature,      # x-blaaiz-signature header
        timestamp,      # x-blaaiz-timestamp header
        webhook_secret  # Your API secret key
    )

    print(f'Verified event: {event}')
    # event['verified'] will be True
    # event['timestamp'] will contain verification timestamp
except ValueError as e:
    print(f'Webhook verification failed: {str(e)}')

Flask Webhook Handler Example

from flask import Flask, request, jsonify
from blaaiz import Blaaiz
import os

app = Flask(__name__)
blaaiz = Blaaiz(os.getenv('BLAAIZ_API_KEY'))

# Webhook secret (your API secret key)
WEBHOOK_SECRET = os.getenv('BLAAIZ_WEBHOOK_SECRET')

@app.route('/webhooks/collection', methods=['POST'])
def handle_collection_webhook():
    signature = request.headers.get('x-blaaiz-signature')
    timestamp = request.headers.get('x-blaaiz-timestamp')
    payload = request.get_data(as_text=True)

    try:
        # Verify webhook signature and construct event
        event = blaaiz.webhooks.construct_event(payload, signature, timestamp, WEBHOOK_SECRET)

        print(f'Verified collection event: {event}')

        # Process the collection
        # Update your database, send notifications, etc.

        return jsonify({'received': True}), 200

    except ValueError as e:
        print(f'Webhook verification failed: {str(e)}')
        return jsonify({'error': 'Invalid signature'}), 400

@app.route('/webhooks/payout', methods=['POST'])
def handle_payout_webhook():
    signature = request.headers.get('x-blaaiz-signature')
    timestamp = request.headers.get('x-blaaiz-timestamp')
    payload = request.get_data(as_text=True)

    try:
        # Verify webhook signature and construct event
        event = blaaiz.webhooks.construct_event(payload, signature, timestamp, WEBHOOK_SECRET)

        print(f'Verified payout event: {event}')

        # Process the payout completion
        # Update your database, send notifications, etc.

        return jsonify({'received': True}), 200

    except ValueError as e:
        print(f'Webhook verification failed: {str(e)}')
        return jsonify({'error': 'Invalid signature'}), 400

if __name__ == '__main__':
    app.run(debug=True)

Environment Configuration

import os

# Development
blaaiz_dev = Blaaiz('dev-api-key', base_url='https://api-dev.blaaiz.com')

# Production (when available)
blaaiz_prod = Blaaiz('prod-api-key', base_url='https://api.blaaiz.com')

# OAuth 2.0 with credentials from the environment
blaaiz_oauth = Blaaiz(
    client_id=os.environ['BLAAIZ_CLIENT_ID'],
    client_secret=os.environ['BLAAIZ_CLIENT_SECRET'],
    base_url='https://api.blaaiz.com',
)

Best Practices

  1. Always validate customer data before creating customers
  2. Use the fees API to calculate and display fees to users
  3. Always verify webhook signatures using the SDK's built-in methods
  4. Store customer IDs and transaction IDs for tracking
  5. Handle rate limiting gracefully with exponential backoff
  6. Use environment variables for API keys and webhook secrets
  7. Implement proper error handling and logging
  8. Test webhook endpoints thoroughly with signature verification
  9. Use the context manager for automatic resource cleanup
  10. Return appropriate HTTP status codes from webhook handlers

Development

To set up the development environment:

# Clone the repository
git clone https://github.com/blaaiz/blaaiz-python-sdk.git
cd blaaiz-python-sdk

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
flake8 blaaiz/
black blaaiz/

# Run type checking
mypy blaaiz/

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support and additional documentation:

Changelog

1.2.0

  • OAuth 2.0 Authentication:
    • Added OAuth 2.0 client-credentials support: construct the client with client_id/client_secret to authenticate via Bearer tokens fetched from /oauth/token
    • Fully backward compatible: the legacy api_key authentication still works unchanged
    • When both api_key and OAuth credentials are provided, OAuth is preferred

1.1.0

  • Customer Service:
    • Added list_beneficiaries() method to list customer beneficiaries
    • Added get_beneficiary() method to get specific beneficiary
    • Updated create() validation: first_name/last_name now only required for individuals
  • Collection Service:
    • Added accept_interac_money_request() method for CAD Interac transfers
    • Updated initiate() required fields: now requires customer_id and currency
  • Payout Service:
    • Added customer_id as required field
    • Added support for to_amount as alternative to from_amount
    • Added currency-specific validation for bank transfers (NGN, GBP, EUR)
    • Added ACH payout support (USD)
    • Added Wire payout support (USD)
    • Added Crypto payout support (USD)
  • Virtual Bank Account Service:
    • Added close() method to close virtual bank accounts
    • Added get_identification_type() method for ID type requirements
    • Updated list() to support customer_id filter parameter
  • Webhook Service:
    • Added simulate_interac_webhook() method (non-production only)
    • Updated verify_signature() to use timestamp-based verification
    • Updated construct_event() to require timestamp parameter
  • Fees Service:
    • Added support for to_amount as alternative to from_amount

1.0.0

  • Initial release
  • Support for all Blaaiz API endpoints
  • Comprehensive error handling
  • Webhook signature verification
  • File upload functionality
  • Complete workflow helpers
  • 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

blaaiz_python_sdk-1.2.0.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

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

blaaiz_python_sdk-1.2.0-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

Details for the file blaaiz_python_sdk-1.2.0.tar.gz.

File metadata

  • Download URL: blaaiz_python_sdk-1.2.0.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for blaaiz_python_sdk-1.2.0.tar.gz
Algorithm Hash digest
SHA256 841e146bd527069ca9a313c2c882555114d95d54f76639201653bd822db6b554
MD5 3a337d337b06512756363014e287c7e9
BLAKE2b-256 baacb7a44f27f46f2d13d44baf406bd1eeb42241dec738c0882da30e2ce608b4

See more details on using hashes here.

File details

Details for the file blaaiz_python_sdk-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for blaaiz_python_sdk-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 58eccca08e4a80f9cce99646dd827998b03d598694259c2fe68b43c39a2405d4
MD5 5611ba5c181b5d471a0bf3c62e518fb2
BLAKE2b-256 41c68e1ec1a0fa0abd020b03a0cc52376b9af2b6d067d103ad177667e6c770ff

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