> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dfns.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Server-side SDK for integrating Dfns into Python backends

<Warning>
  **Attention: This project is currently in BETA.**

  This means that while we've worked hard to ensure its functionality, stability, and security, there may still be bugs, performance issues, or unexpected behavior.
</Warning>

The Python SDK is designed for **server-side/backend** applications. It handles request signing and provides typed access to the Dfns API.

You can find the repository [here](https://github.com/dfns/dfns-sdk-python).

## Installation

```bash theme={null}
pip install dfns_sdk
```

## Quick start

### 1. Read-only operations

For read-only operations (listing wallets, fetching balances, etc.), you only need an auth token:

```python theme={null}
from dfns_sdk import DfnsClient, DfnsClientConfig

config = DfnsClientConfig(auth_token="your-auth-token")

with DfnsClient(config) as client:
    wallets = client.wallets.list_wallets()
    for wallet in wallets["items"]:
        print(f"{wallet['id']}: {wallet['network']} {wallet['address']}")
```

<Tip>
  For a quick test you can get your login token (short-lived) from the [Dfns Dashboard](https://app.dfns.io/) under `Settings` > `Personal Access Tokens`.
</Tip>

### 2. Signing requests

State-changing operations (creating wallets, signing transactions, etc.) require cryptographic request signing. Choose your approach based on where the private key lives:

<Tabs>
  <Tab title="Direct signing">
    Use `DfnsClient` with a `KeySigner` when your backend has direct access to the private key (e.g., stored in a file or environment variable).

    This is ideal for service accounts where the private key is securely stored on your server.

    ```python theme={null}
    from dfns_sdk import DfnsClient, DfnsClientConfig, KeySigner

    signer = KeySigner(
        credential_id="cr-...",
        private_key=open("/path/to/private-key.pem").read(),
        app_origin="https://your-app.example.com"
    )

    config = DfnsClientConfig(
        auth_token="your-auth-token",
        signer=signer
    )

    with DfnsClient(config) as client:
        wallet = client.wallets.create_wallet({"network": "EthereumSepolia"})
        print(f"Created wallet: {wallet['id']}")
    ```
  </Tab>

  <Tab title="Delegated signing">
    Use `DfnsDelegatedClient` when the private key is not directly accessible to your backend:

    * **User passkeys**: Users sign with their own device (WebAuthn/biometrics)
    * **External KMS**: Private key stored in AWS KMS, HashiCorp Vault, etc.

    The flow splits into init and complete phases:

    ```python theme={null}
    from dfns_sdk import DfnsDelegatedClient, DfnsDelegatedClientConfig

    config = DfnsDelegatedClientConfig(auth_token="user-auth-token")

    with DfnsDelegatedClient(config) as client:
        # Step 1: Initialize and get a challenge
        challenge = client.wallets.create_wallet_init(body={"network": "EthereumSepolia"})

        # Step 2: Send challenge to be signed externally
        # - For passkeys: send to user's frontend for WebAuthn signing
        # - For KMS: send to your KMS to sign
        # signed_challenge = ... (received from external signer)

        # Step 3: Complete with the signed challenge
        wallet = client.wallets.create_wallet_complete(
            body={"network": "EthereumSepolia"},
            signed_challenge={
                "challengeIdentifier": challenge["challengeIdentifier"],
                "firstFactor": signed_challenge
            }
        )
        print(f"Created wallet: {wallet['id']}")
    ```
  </Tab>
</Tabs>

## Next steps

* **[Create a service account](/guides/developers/service-account)** for server-to-server authentication with long-lived tokens
* **[Development guide](/sdks/backend/python/development)** for detailed request signing architecture
* **[Delegated wallets](/guides/developers/delegated-wallets)** for implementing user passkey flows
