{"id":7660,"library":"recurly","title":"Recurly Python Client","description":"The `recurly` library is the official Python client for Recurly's V3 API, enabling developers to integrate subscription billing and management into their applications. It provides functionalities for managing accounts, subscriptions, invoices, and transactions. The library is actively maintained with frequent minor version releases, often driven by updates to the underlying Recurly API schema, and the current stable version is 4.70.0.","status":"active","version":"4.70.0","language":"en","source_language":"en","source_url":"https://github.com/recurly/recurly-client-python","tags":["billing","subscription","payments","api-client"],"install":[{"cmd":"pip install recurly","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"note":"The recommended approach is to import the top-level 'recurly' module and access 'Client' via 'recurly.Client' to preserve namespace integrity.","wrong":"from recurly import Client","symbol":"Client","correct":"import recurly\nclient = recurly.Client(api_key='YOUR_API_KEY')"},{"note":"Commonly imported for error handling.","symbol":"ApiError","correct":"from recurly import ApiError"},{"note":"Commonly imported for error handling related to network issues.","symbol":"NetworkError","correct":"from recurly import NetworkError"}],"quickstart":{"code":"import os\nimport recurly\n\n# It's highly recommended to store your API key as an environment variable.\nRECURLY_API_KEY = os.environ.get('RECURLY_API_KEY', 'YOUR_PRIVATE_API_KEY')\n\n# Initialize the Recurly client\n# For EU region, use: client = recurly.Client(RECURLY_API_KEY, region='eu')\nclient = recurly.Client(RECURLY_API_KEY)\n\n# Example: Fetch an account by its code\ntry:\n    # Note: Use 'code-' prefix for account codes, if applicable, based on your Recurly setup.\n    account_code = 'code-example-account-123'\n    account = client.get_account(account_code=account_code)\n    print(f\"Successfully retrieved account: {account.id} (Code: {account.code}, Email: {account.email})\")\n\n    # Example: List recent invoices for the account\n    print(f\"\\nRecent invoices for account {account.code}:\")\n    for invoice in client.list_account_invoices(account_id=account.id).items():\n        print(f\"  Invoice {invoice.id}: State={invoice.state}, Total={invoice.total}\")\n\nexcept recurly.ApiError as e:\n    print(f\"Recurly API Error: {e.message}\")\n    if e.error_code:\n        print(f\"  Error Code: {e.error_code}, Details: {e.details}\")\nexcept recurly.NetworkError as e:\n    print(f\"Recurly Network Error: {e.message}\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")\n","lang":"python","description":"This quickstart demonstrates how to initialize the Recurly client using an API key and perform a basic API call to retrieve an account and list its invoices. Ensure `RECURLY_API_KEY` is set as an environment variable or replaced with your actual private API key. Remember to handle `recurly.ApiError` for API-specific responses and `recurly.NetworkError` for connectivity issues."},"warnings":[{"fix":"Refer to the Recurly Developer Hub for the 'API v2 Python Client Upgrade Guide' and re-implement your integration using the new API v3 paradigms and the v4.x.x Python client.","message":"Upgrading from Recurly Python client v2.x.x (for Recurly API v2) to v4.x.x (for Recurly API v3) requires a complete rewrite of your integration code. There is no backward compatibility or drop-in shim. Recurly API v2 versions are officially deprecated and have reached end-of-life.","severity":"breaking","affected_versions":"All versions prior to 4.0.0 (API v2 client) when migrating to 4.0.0+ (API v3 client)"},{"fix":"For webhooks, use a dedicated XML-to-dict parser like `xmltodict` for processing incoming webhook data. Be mindful of security implications when parsing untrusted XML.","message":"Recurly API (used by this client library) is JSON-based, but webhook payloads are still XML. This library does not handle webhook parsing directly. Developers must implement their own XML parsing (e.g., using `xmltodict`) and validate webhook signatures.","severity":"gotcha","affected_versions":"All 4.x.x versions"},{"fix":"Store your `RECURLY_API_KEY` in environment variables or a secure vault. Access it in server-side code using `os.environ.get('RECURLY_API_KEY')`.","message":"Recurly's private API keys should be treated like passwords and never exposed in client-side code (e.g., JavaScript). They grant full access to your Recurly account's API. Always store them securely, preferably in environment variables or a secret management system.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Consult the specific method's documentation in the `recurly.client` module for parameter expectations. Always use the specified prefixes when interacting with object 'codes' to avoid `NotFoundError` or `InvalidParameterError`.","message":"Many client methods accept IDs or codes (e.g., for accounts, plans). When using a 'code' (a user-defined identifier), it often requires a `code-` prefix (e.g., `client.get_account(account_code='code-my-account')`) while internal Recurly IDs do not use prefixes.","severity":"gotcha","affected_versions":"All 4.x.x versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure you are using the correct client method (e.g., `client.get_account(...)` not `recurly.Account(...)`) and providing the correct identifier type and format (e.g., `account_code='code-your-account'` for a code, or the raw Recurly ID).","cause":"Attempting to retrieve an object (e.g., an account) by directly instantiating its class or using an incorrect identifier (ID vs. code, or missing 'code-' prefix).","error":"recurly.NotFoundError: Not Found"},{"fix":"Verify your `RECURLY_API_KEY` environment variable or the string passed to `recurly.Client()`. Ensure it's a valid private API key from your Recurly Admin Dashboard under Integrations > API Credentials.","cause":"The private API key used to initialize the `recurly.Client` is incorrect, expired, or not provided.","error":"recurly.ApiError: 401 Unauthorized - Your API key is missing or invalid."},{"fix":"Inspect the `e.details` and `e.message` from the `ApiError` for specific validation feedback. Review your request body against the Recurly API documentation for the endpoint you are calling to ensure correct schema and data.","cause":"Often caused by malformed request bodies (e.g., incorrect JSON structure, missing required fields, invalid data types) or, historically with v2 API, invalid XML in requests.","error":"recurly.ApiError: 400 Bad Request - The request was invalid or could not be understood by the server."},{"fix":"Ensure all country fields in your API requests (e.g., when creating or updating an account's billing information or shipping addresses) use the correct 2-letter ISO 3166-1 alpha-2 format (e.g., 'US', 'GB', 'DE').","cause":"An address field containing a country code does not use a valid 2-letter ISO 3166-1 alpha-2 country code.","error":"recurly.ApiError: 400 Bad Request - Invalid country code."},{"fix":"Check network connectivity, proxy settings, and firewall rules. For intermittent issues, particularly in complex deployments, consider implementing retry logic or investigating specific HTTP client library behavior if possible.","cause":"Indicates a problem establishing or maintaining an HTTP connection to the Recurly API servers. This can be due to transient network issues, proxy misconfigurations, firewall restrictions, or issues with the underlying HTTP client in specific deployment environments (e.g., Flask + Gunicorn).","error":"recurly.NetworkError: Connection refused / Max retries exceeded / SSLError"}]}