> ## 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.

# Overview

> Shared concepts for the server-side Dfns SDKs, including authentication, request signing, error handling, and language-specific guidance.

Backend SDKs are designed for server-side applications: API servers, background workers, scripts. They handle [request signing](/api-reference/auth/signing-flows) automatically and provide typed access to the full Dfns API.

<Warning>
  Backend SDKs require a private key for request signing. Never expose private keys to client-side code. For user-facing applications, use a [frontend SDK](/sdks/frontend) with [delegated signing](#delegated-signing).
</Warning>

## Authentication tokens

All backend SDKs require an `authToken`. This can be:

* A **Service Account** token — long-lived, for server-to-server automation
* A **[Personal Access Token (PAT)](/guides/developers/personal-access-token)** — long-lived, tied to a specific user
* A **User login token** — short-lived, issued after user authentication

See [Required headers](/api-reference/auth) for details on obtaining tokens.

## Request signing

All state-changing requests (POST, PUT, DELETE) must be cryptographically signed. The SDK handles this automatically when you configure a key signer.

The signing flow works as follows:

1. Your SDK sends the request payload to Dfns
2. Dfns returns a User Action Challenge
3. Your SDK signs the challenge with your private key
4. The signed challenge is sent back to complete the request

<Info>
  For a detailed explanation, see [Signing requests](/guides/developers/signing-requests).
</Info>

## Key signer

Each backend SDK provides a key signer that takes your credential ID and private key. All SDKs support the same key types:

| Algorithm | Description                               |
| --------- | ----------------------------------------- |
| Ed25519   | Edwards-curve Digital Signature Algorithm |
| ECDSA     | Elliptic Curve DSA (P-256, secp256k1)     |
| RSA       | RSA PKCS#1 v1.5 with SHA-256              |

Your credential ID and private key come from creating a [Service Account](/guides/developers/service-account) or Personal Access Token in the Dfns Dashboard under `Settings` > `Service Accounts` or `Settings` > `Personal Access Tokens`.

<CodeGroup>
  ```ts TypeScript theme={null}
  import { AsymmetricKeySigner } from '@dfns/sdk-keysigner'

  const signer = new AsymmetricKeySigner({
    credId: 'cr-...',
    privateKey: process.env.DFNS_PRIVATE_KEY!,
  })
  ```

  ```go Go theme={null}
  import "github.com/dfns/dfns-sdk-go/v2/signer"

  keySigner, err := signer.NewKeySigner(
      "cr-...",
      string(privateKeyPEM),
  )
  ```

  ```python Python theme={null}
  from dfns_sdk import KeySigner

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

  ```java Java theme={null}
  import co.dfns.sdk.auth.*;

  Signer signer = KeySigner.fromEd25519PrivateKey(
      "cr-...",
      privateKeyBytes
  );
  ```
</CodeGroup>

## Direct vs delegated signing

Backend SDKs support two client patterns:

### Direct signing

Use the standard client when your backend has the private key and signs requests itself. This is the most common pattern for service accounts and automation.

The SDK handles the full signing flow internally — you just call API methods and the signing happens transparently.

<CodeGroup>
  ```ts TypeScript theme={null}
  import { DfnsApiClient } from '@dfns/sdk'
  import { AsymmetricKeySigner } from '@dfns/sdk-keysigner'

  const signer = new AsymmetricKeySigner({
    credId: 'cr-...',
    privateKey: process.env.DFNS_PRIVATE_KEY!,
  })

  const dfns = new DfnsApiClient({
    baseUrl: 'https://api.dfns.io',
    orgId: 'or-...',
    authToken: '...',
    signer,
  })

  const wallet = await dfns.wallets.createWallet({
    body: { network: 'EthereumSepolia' },
  })
  ```

  ```go Go theme={null}
  import (
      dfns "github.com/dfns/dfns-sdk-go/v2"
      "github.com/dfns/dfns-sdk-go/v2/signer"
      "github.com/dfns/dfns-sdk-go/v2/wallets"
  )

  keySigner, _ := signer.NewKeySigner("cr-...", string(privateKeyPEM))

  client, _ := dfns.NewClient(dfns.Options{
      AuthToken: "...",
      Signer:    keySigner,
  })

  wallet, _ := client.Wallets.CreateWallet(ctx, wallets.CreateWalletRequest{
      Network: "EthereumSepolia",
  })
  ```

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

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

  config = DfnsClientConfig(auth_token="...", signer=signer)

  with DfnsClient(config) as client:
      wallet = client.wallets.create_wallet({"network": "EthereumSepolia"})
  ```

  ```java Java theme={null}
  import co.dfns.sdk.*;
  import co.dfns.sdk.auth.*;
  import co.dfns.sdk.wallets.model.*;

  Signer signer = KeySigner.fromEd25519PrivateKey("cr-...", privateKeyBytes);

  DfnsClientConfig config = DfnsClientConfig.builder()
      .authToken("...")
      .signer(signer)
      .build();

  try (DfnsClient client = new DfnsClient(config)) {
      Wallet wallet = client.wallets.createWallet(
          new CreateWalletRequest(Network.EthereumSepolia, null, null, null, null, null, null)
      );
  }
  ```
</CodeGroup>

### Delegated signing

Use the delegated client when the private key is **not** on your backend — for example, when users sign with passkeys on their own device, or when the key lives in an external KMS.

The delegated client splits every state-changing operation into two steps:

1. **Init** — your backend sends the request and receives a challenge
2. **Complete** — your backend sends the challenge (signed externally) to finish the request

<CodeGroup>
  ```ts TypeScript theme={null}
  import { DfnsDelegatedApiClient } from '@dfns/sdk'

  const dfnsDelegated = new DfnsDelegatedApiClient({
    baseUrl: 'https://api.dfns.io',
    orgId: 'or-...',
    authToken: userAuthToken,
  })

  // Step 1: Get a challenge
  const challenge = await dfnsDelegated.wallets.createWalletInit({
    body: { network: 'EthereumSepolia' },
  })

  // Step 2: Send challenge to user's frontend for signing
  // ... user signs with passkey via frontend SDK ...

  // Step 3: Complete with the signed challenge
  const wallet = await dfnsDelegated.wallets.createWalletComplete(
    { body: { network: 'EthereumSepolia' } },
    signedChallenge,
  )
  ```

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

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

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

      # Step 2: Send challenge to user's frontend for signing
      # ... user signs with passkey via frontend SDK ...

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

<Info>
  The Go and Java SDKs do not have a delegated client yet. Use the TypeScript or Python SDK for delegated signing flows.
</Info>

See [Delegated wallets](/guides/developers/delegated-wallets) for a full implementation guide.
