For the complete documentation index, see llms.txt. This page is also available as Markdown.

4. Delegate Management

Add, list, and remove delegates. Delegates are addresses that can propose transactions on behalf of Safe owners without being owners themselves.

What you'll learn

  • What delegates are and when to use them

  • Add a delegate for an owner using a signed API call

  • List all delegates for a Safe

  • Remove a delegate

Prerequisites

  • Node.js 18+

  • A Safe on a supported chain where you control an owner key

  • A private key for a Safe owner: testnet only

  • viem: used to create a wallet client for signing delegate API requests

Install dependencies:

npm install @safe-global/api-kit viem

Configuration

import SafeApiKitModule from "@safe-global/api-kit";
import { createWalletClient, http } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

// ESM interop-safe constructor resolution (required in some runtimes)
const SafeApiKit =
  typeof SafeApiKitModule === "function"
    ? SafeApiKitModule
    : (SafeApiKitModule as unknown as { default: typeof SafeApiKitModule }).default;

const CHAIN_ID = 11155111n; // Sepolia
const TX_SERVICE_URL = `https://app.multisig.ledger.com/api/safe-transaction-service/${CHAIN_ID}`;
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com";
const SAFE_ADDRESS = "0xYourSafeAddress";
const OWNER_PRIVATE_KEY = "0xYourPrivateKey" as `0x${string}`; // Testnet only!

const apiKit = new SafeApiKit({
  chainId: CHAIN_ID,
  txServiceUrl: TX_SERVICE_URL,
});

This example uses sepolia for the viem wallet client. If you switch CHAIN_ID, use the matching viem chain object.

The TX_SERVICE_URL points at the Ledger-hosted Transaction Service. Delegate records stored here are visible in the Ledger Multisig UI.

Supported chains: Ethereum (1), Optimism (10), BSC (56), Polygon (137), Base (8453), Arbitrum (42161), Sepolia (11155111).

Step-by-step

1

Set up the owner wallet client

Delegate management requires the owner to sign API requests (proving they authorize the delegate). Create a viem wallet client for the owner:

2

Add a delegate

Add a delegate address that can propose transactions on behalf of the owner. The label is a human-readable identifier stored with the delegate record.

REST API: POST /v2/delegates/

The request body includes the Safe address, delegate address, delegator (owner), label, and a signature proving the delegator authorized this action.

The delegate can now call proposeTransaction with senderAddress set to their own address.

3

List delegates

Query all delegates for the Safe:

REST API: GET /v2/delegates/?safe={address}

4

Remove a delegate

Remove a delegate when they should no longer be able to propose on the owner's behalf:

REST API: DELETE /v2/delegates/{delegateAddress}/

Requires a signature from the delegator (owner) proving they authorize the removal.

Verify the removal:

Key concepts

What are delegates?

A delegate is an address authorized to propose transactions to the Transaction Service on behalf of a Safe owner, without being an owner themselves.

Why use delegates?

  • Automation: A backend service or bot can propose transactions without holding an owner key

  • Separation of concerns: Proposers don't need signing authority; owners still approve and execute

  • No gas cost: Adding and removing delegates are off-chain API calls, not on-chain transactions

Important distinctions:

  • Delegates can propose but cannot sign or execute. Only owners can provide confirmations.

  • Delegate records are stored in the Transaction Service, not on-chain. They only affect who can call the proposal API.

  • Each delegate is associated with a specific delegator (owner). If the delegator is removed as an owner, their delegates lose proposal rights.

Tips and pitfalls

  • No gas required. Delegate management is entirely off-chain. Adding, listing, and removing delegates are API calls to the Transaction Service. No on-chain transactions are involved.

  • Wallet client required for signing. The addSafeDelegate and removeSafeDelegate methods require a signer parameter. This is a viem WalletClient that signs the API request body, proving the owner authorized the action.

  • ESM import gotcha. In some ESM runtimes, using import SafeApiKit from "@safe-global/api-kit" directly can throw TypeError: SafeApiKit is not a constructor. Use the interop-safe constructor resolution shown in Configuration.

  • Delegates per owner. Each delegate is tied to a specific owner (delegator). If you want a delegate to act on behalf of multiple owners, add them separately for each owner.

  • Label is metadata only. The label field is stored alongside the delegate record for identification purposes. It has no functional effect.

Next steps

5. ERC20 Token Transfers

Last updated