Install & Compatibility
Where this runs
tested against v6.1.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 1.556s · 66.7MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 4.2s · import 1.396s · 67MB
70MB installed
● package 70MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
ApiClient
✓ from docusign_esign import ApiClient
✗ from docusign_esign.client.api_client import ApiClient
The top-level import is preferred for simplicity; the longer path is also valid but less commonly used in examples.
Configuration
✓ from docusign_esign import Configuration
✗ from docusign_esign.configuration import Configuration
The top-level import is preferred; the longer path is also valid but less commonly used in examples.
EnvelopesApi
✓ from docusign_esign import EnvelopesApi
✗ from docusign_esign.apis.envelopes_api import EnvelopesApi
Top-level imports are convenient for frequently used API classes (e.g., EnvelopesApi, AccountsApi).
This quickstart demonstrates how to authenticate with DocuSign using JWT Grant, configure the API client, and make a simple call to retrieve user information. It highlights the critical distinction between authentication server and API server host configurations.
import os
from docusign_esign import ApiClient, Configuration, OAuth, AccountsApi
from docusign_esign.client.api_exception import ApiException
def get_access_token_jwt():
# Ensure these environment variables are set or replace with actual values
client_id = os.environ.get('DS_CLIENT_ID', 'YOUR_INTEGRATION_KEY')
impersonated_user_id = os.environ.get('DS_IMPERSONATED_USER_ID', 'YOUR_IMPERSONATED_USER_ID')
# Private key should be the raw PEM bytes, often loaded from a file or env var
private_key_bytes = os.environ.get('DS_PRIVATE_KEY_BYTES', 'YOUR_PRIVATE_KEY').encode('utf-8')
# Authentication server: 'account-d.docusign.com' for demo, 'account.docusign.com' for production
auth_server = os.environ.get('DS_AUTH_SERVER', 'account-d.docusign.com')
if 'YOUR_' in client_id or 'YOUR_' in impersonated_user_id or 'YOUR_' in private_key_bytes.decode('utf-8'):
print("Please set DS_CLIENT_ID, DS_IMPERSONATED_USER_ID, DS_PRIVATE_KEY_BYTES, and DS_AUTH_SERVER environment variables.")
return None
try:
# Use the JWT helper to request a token
api_client_oauth = OAuth.ApiClient()
token_response = api_client_oauth.request_jwt_user_token(
client_id=client_id,
impersonated_user_id=impersonated_user_id,
private_key_bytes=private_key_bytes,
expires_in=3600, # 1 hour
scopes=["signature", "impersonation"],
auth_host="https://" + auth_server
)
return token_response.access_token
except ApiException as e:
print(f"Error during JWT token request: {e.reason} - {e.body}")
return None
def main():
# 1. Get Access Token via JWT Grant
access_token = get_access_token_jwt()
if not access_token:
return
# DocuSign API server: 'demo.docusign.net' for demo, 'naX.docusign.net' for production (X is a number)
api_server = os.environ.get('DS_API_SERVER', 'demo.docusign.net')
if 'YOUR_' in api_server:
print("Please set DS_API_SERVER environment variable.")
return
# 2. Configure API Client
config = Configuration()
config.host = f"https://{api_server}/restapi"
config.access_token = access_token
api_client = ApiClient(config)
# 3. Make an API call (e.g., get user info)
try:
accounts_api = AccountsApi(api_client)
user_info = accounts_api.get_user_info()
print(f"Successfully authenticated user: {user_info.name} ({user_info.email})")
if user_info.accounts:
print(f"Default Account ID: {user_info.accounts[0].account_id}")
print(f"Base URL for API calls: {user_info.accounts[0].base_url}")
else:
print("No accounts found for this user.")
except ApiException as e:
print(f"Error calling DocuSign API: {e.reason} - {e.body}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
if __name__ == '__main__':
main()
Debug
Known issues
gotchaThe DocuSign API server (e.g., `demo.docusign.net/restapi` or `naX.docusign.net/restapi`) and the OAuth authentication server (e.g., `account-d.docusign.com` or `account.docusign.com`) use distinct base URLs. Misconfiguring `config.host` for API calls or the `auth_host` parameter in OAuth token requests can lead to authentication failures or API connection issues.fixEnsure `config.host` is set to the correct API base URL (including `/restapi` and API version, typically `v2.1`), and the `auth_host` parameter in JWT/OAuth methods points to the correct authentication server. Use 'account-d.docusign.com' for demo/sandbox environments and 'account.docusign.com' for production.
affects: All versions
gotchaJWT Grant authentication requires precise setup: `client_id` (integration key), `impersonated_user_id` (GUID of the user to impersonate), `private_key_bytes` (the raw PEM private key from your integration app), and correct `scopes` (e.g., 'signature', 'impersonation'). Common errors include 'consent required' (the impersonated user hasn't granted consent to the integration key) or 'invalid_grant' (incorrect client ID, user ID, private key, or scopes).fixVerify all JWT parameters match your DocuSign integration key settings in Admin Console. Ensure the impersonated user has granted consent for your integration key in their DocuSign account. Load the private key as raw PEM bytes (e.g., `open('private_key.pem', 'rb').read()`). affects: All versions using JWT Grant
Errors
Common errors & fixes
docusign_esign.client.rest.ApiException: (400) Reason: Bad Request
This generic ApiException with a 400 status code often indicates issues with the API request payload, incorrect authentication credentials (e.g., malformed JWT, invalid access token), or misconfigured environment settings (e.g., wrong base URL for demo vs. production). It frequently accompanies more specific error descriptions within the response body, such as 'invalid_grant' or 'USER_AUTHENTICATION_FAILED'.
fixThoroughly review your authentication setup (integration key, user ID, private key, scopes, consent, OAuth base URL) and the structure of your API request body. Ensure all required parameters are correctly formatted and provided. For JWT, verify the user ID is the API Username and that consent has been granted for the necessary scopes. Check the full error response body for a more detailed `error_description` or `errorCode` to pinpoint the specific issue.
{"error":"invalid_grant","error_description":"issuer_not_found"}
This error occurs during JWT authentication when the DocuSign system cannot find the issuer associated with the integration key, often because the user ID specified in the JWT assertion is not a member of the DocuSign account that owns the integration key, or consent has not been correctly granted.
fixVerify that the User ID used in your JWT assertion is a valid GUID user ID of an active user within the correct DocuSign account. Ensure that consent has been successfully granted for the required scopes (e.g., `signature`, `impersonation`) by navigating to the consent URL and accepting. Double-check all IDs (Integration Key, API Account ID, User ID) and the OAuth base URL for the correct environment (demo or production).
ModuleNotFoundError: No module named 'docusign_esign'
This error indicates that the Python interpreter cannot find the `docusign-esign` package, typically due to it not being installed, an incorrect Python environment being used, or an issue with the `PYTHONPATH` environment variable.
fixInstall the `docusign-esign` package using pip: `pip install docusign-esign`. If already installed, ensure you are running your code with the Python environment where the package was installed. You might also need to verify that your `PYTHONPATH` includes the directory where Python packages are installed (e.g., `site-packages`).
AttributeError: 'ApiException' object has no attribute 'trace_token'
This error occurs when attempting to access the `trace_token` attribute directly from a `docusign_esign.client.ApiException` object. The `trace_token` is found in the HTTP response headers, not directly in the `ApiException` object itself, especially when using standard API methods that only return the JSON body.
fixTo retrieve the `TraceToken`, you need to call the `_with_http_info` variant of the API method (e.g., `envelopes_api.create_envelope_with_http_info`) which returns the full HTTP response, including headers. The `TraceToken` can then be extracted from the `header_params` dictionary within the response object.
Upgrade
Version history
6.1.0latest on PyPI · released Mar 13, 2026
Audit
Dependencies
No dependency data recorded yet.