Skip to main content
A delegate renews users’ VTXOs before batch expiry on their behalf — without ever holding their keys. This guide runs one with Fulmine, Ark Labs’ wallet daemon, in headless mode.

What you’re running

Fulmine is a wallet daemon that doubles as delegate infrastructure: clients hand it presigned, tamper-proof intents and it submits them in a batch swap before their VTXOs expire — fully self-custodial (see Intent Delegation for the model). Run “headless,” its Delegate API needs no wallet: a fresh daemon with delegation enabled serves clients immediately, with nothing to create, unlock, or fund. Fulmine has no flag to hide the Web UI; just ignore it. Fulmine listens on three ports:
PortEnv varPurpose
7000FULMINE_GRPC_PORTgRPC API (not needed for a delegate-only deployment)
7001FULMINE_HTTP_PORTREST API (mounted under /api) and Web UI; delegation status lookups
7002FULMINE_DELEGATE_PORTDelegate API — info and submission, served at /v1/... (no /api prefix)

Prerequisites

  • Docker — the quickest way to run Fulmine.
  • The mainnet Arkade Service URL: https://arkade.computer.
Fulmine’s REST and gRPC interfaces are not authenticated. Do not expose them to the public internet — keep the daemon on a private network or behind a reverse proxy with its own access control.

Quickstart with Docker

1

Start Fulmine with delegation enabled

Run the daemon as a detached container, pointed at mainnet with the delegate enabled:
docker run -d --name fulmine \
  -p 7001:7001 -p 7002:7002 \
  -e FULMINE_ARK_SERVER="https://arkade.computer" \
  -e FULMINE_DELEGATE_ENABLED=true \
  -v fulmine-data:/app/data \
  ghcr.io/arklabshq/fulmine:latest
This publishes the HTTP port (7001, for status lookups and the Web UI) and the delegate port (7002, the Delegate API). The gRPC port (7000) is intentionally left unpublished — it isn’t needed for a delegate-only deployment.
2

Verify the delegate is live

Query the delegate info endpoint — it returns the delegate’s public key and fee. The Delegate API is served on port 7002 at /v1/... (no /api prefix):
curl http://localhost:7002/v1/delegate/info
# { "pubkey": "<hex>", "fee": "0", "delegateAddress": "<fee address, if set>" }
A JSON response means your delegate server is ready for clients — no wallet creation or unlock required.
delegateAddress is where your service fee is paid, so it may be empty while FULMINE_DELEGATE_FEE is 0. The response also carries a deprecated delegatorAddress alias — prefer delegateAddress.

Essential environment variables

Fulmine is configured entirely through FULMINE_-prefixed environment variables — there are no CLI flags. These are the ones that matter for a headless delegate:
VariableExample (mainnet)Purpose
FULMINE_ARK_SERVERhttps://arkade.computerArkade Service the daemon connects to
FULMINE_DELEGATE_ENABLEDtrueTurns on delegate functionality (default false)
FULMINE_DELEGATE_PORT7002Delegate server port (must differ from gRPC/HTTP)
FULMINE_DELEGATE_FEE0Service fee applied by the delegate (default 0)
FULMINE_DATADIR/app/dataData directory — image default, persisted by the volume
That’s all a delegate needs. If you also want to run this daemon as a funded wallet, you’d additionally create a wallet and configure auto-unlock (FULMINE_UNLOCKER_*) for unattended operation — but none of that is required for the Delegate API. See the Fulmine repo for the full configuration.

How a wallet uses your delegate

Once your server is up, a client wallet uses it in three steps:
  1. Discover — the wallet calls GET /v1/delegate/info (port 7002) to read your delegate pubkey, fee, and address, then builds a delegated address with an operator + user + delegate spend path.
  2. Delegate — the wallet submits a presigned intent and forfeit transactions to POST /v1/delegate (port 7002). The intent is bound by a time window and signed with BIP322, so your server cannot alter or redirect the funds — only submit what was authorized.
  3. Renew — your server watches those VTXOs and submits the intent in a batch swap just before expiry. Status can be tracked via GET /api/v1/delegates on the HTTP port (7001), which accepts status (pending, completed, failed), limit, and offset query parameters.
# Submit a delegation (client side) — Delegate API on port 7002
curl -X POST http://localhost:7002/v1/delegate \
  -H "Content-Type: application/json" \
  -d '{"intent": {"message": "{\"vtxos\": [...]}", "proof": "<base64 psbt>"}, "forfeitTxs": ["<base64 psbt>"]}'
The info endpoint is also exposed at /v1/delegator/info as a legacy alias, but /v1/delegate/info is preferred. For a complete client-side example of building the intent and forfeit transactions, see the TS-SDK delegate.js example.

Next Steps

VTXO Management

Automatic renewal and recovery from the client side

Intent Delegation

The delegation workflow and security model in depth

Fulmine Reference

The wallet daemon powering your delegate

Fulmine on GitHub

Source, releases, and full configuration