---
title: "Migration from Wallet API v1"
description: "Learn how to migrate your data from Wallet API v1 to Wallet API v2."
stack: "Community Stack (open source) — version 1.1.1"
stack_version: "1.1.1"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/community-stack/wallet2/migration
generated: 2026-10-01
---
# Migration from Wallet API v1

The `waltid-wallet-migration` tool migrates data from the old `waltid-wallet-api` (v1) database schema to the new `waltid-wallet-api2` schema. This guide covers the migration process, what gets migrated, and how to run it.

**Error:**

**Important:** Always back up your v1 database before running the migration. The migration tool is designed to be idempotent (running it twice won't duplicate data), but having a backup is essential.

---

## What Gets Migrated

The migration tool transfers the following data from v1 to v2:

| v1 Table | v2 Table(s) | Description |
|----------|-------------|-------------|
| `wallets` | `wallet2_wallets` + store registration tables | Wallet records with auto-created stores |
| `wallet_keys` | `wallet2_keys` | Keys (re-serialized with type inference) |
| `credentials` | `wallet2_credentials` | Credentials (re-parsed into the v2 credential format) |
| `wallet_dids` | `wallet2_dids` | DIDs with documents |
| `account_wallet_mapping` | `wallet2_account_wallets` | Account-to-wallet ownership |

### Store Creation

For each migrated wallet, the tool automatically creates:
- One key store: `wallet-{id}-keys`
- One credential store: `wallet-{id}-creds`
- One DID store: `wallet-{id}-dids`

These deterministic IDs ensure the migration is idempotent.

---

## Prerequisites

1. **Source database**: Your existing v1 wallet database (SQLite or PostgreSQL)
2. **Target database**: A new or empty v2 database (SQLite or PostgreSQL)
3. **Java 17+**: Required to run the migration tool

---

## Running the Migration

### Using Gradle

From the `waltid-identity` repository root:

**SQLite to SQLite:**

```bash
./gradlew :waltid-services:waltid-wallet-migration:run \
  --args="--source jdbc:sqlite:/path/to/old/wallet.db --target jdbc:sqlite:/path/to/new/wallet2.db"
```

**PostgreSQL to PostgreSQL:**

```bash
./gradlew :waltid-services:waltid-wallet-migration:run \
  --args="--source 'jdbc:postgresql://localhost:5432/walletv1?user=wallet&password=secret' --target 'jdbc:postgresql://localhost:5432/walletv2?user=wallet&password=secret'"
```

**Cross-database (SQLite to PostgreSQL):**

```bash
./gradlew :waltid-services:waltid-wallet-migration:run \
  --args="--source jdbc:sqlite:/path/to/wallet.db --target 'jdbc:postgresql://localhost:5432/walletv2?user=wallet&password=secret'"
```

### Dry Run Mode

Add `--dry-run` to preview what would be migrated without writing anything:

```bash
./gradlew :waltid-services:waltid-wallet-migration:run \
  --args="--source jdbc:sqlite:/path/to/wallet.db --target jdbc:sqlite:/path/to/wallet2.db --dry-run"
```

---

## Command Line Arguments

| Argument | Required | Description |
|----------|----------|-------------|
| `--source` | Yes | JDBC URL for the v1 source database |
| `--target` | Yes | JDBC URL for the v2 target database |
| `--dry-run` | No | Preview migration without writing data |

---

## Migration Output

The migration tool logs progress and provides a summary at the end:

```
INFO  - Source: jdbc:sqlite:/path/to/wallet.db
INFO  - Target: jdbc:sqlite:/path/to/wallet2.db
INFO  - Found 5 wallets to migrate
INFO  - 
INFO  - ═══════════════════════════════════════════
INFO  -   Migration complete
INFO  -   Wallets:          5
INFO  -   Keys:             12
INFO  -   Credentials:      28
INFO  -   DIDs:             5
INFO  -   Account mappings: 5
INFO  - ═══════════════════════════════════════════
```

If any items fail to migrate, warnings are logged with details:

```
WARN  - Failed to migrate credential abc123 for wallet xyz789: Invalid credential format
```

---

## Post-Migration Steps

### 1. Verify the Migration

After migration, verify the data was transferred correctly:

Point `wallet2-persistence.conf` at the migrated database (e.g. `jdbcUrl = "jdbc:sqlite:/data/wallet2.db"`), then start wallet-api2 with your config directory and the database mounted:

```bash
docker run \
  -p 7006:7006 \
  -v /path/to/config:/waltid-wallet-api2/config \
  -v /path/to/data:/data \
  waltid/wallet-api2

# List wallets
curl http://localhost:7006/wallet
```

### 2. Update Your Configuration

Update your deployment to use the new wallet-api2 service and database:

**wallet2-persistence.conf:**

```hocon
# wallet2-persistence.conf
jdbcUrl = "jdbc:sqlite:/data/wallet2.db"
driverClassName = "org.sqlite.JDBC"
```

Or for PostgreSQL:

```hocon
# wallet2-persistence.conf
jdbcUrl = "jdbc:postgresql://localhost:5432/walletv2"
driverClassName = "org.postgresql.Driver"
username = "wallet"
password = "secret"
maximumPoolSize = 10
```

See the [Persistence configuration reference](https://docs.walt.id/community-stack/wallet2/configurations/config-files/persistence.md) for all options.

### 3. Update API Calls

The v2 API has some differences from v1. Key changes:

| v1 Endpoint | v2 Endpoint | Notes |
|-------------|-------------|-------|
| `/api/wallet/{walletId}/...` | `/wallet/{walletId}/...` | Simplified path |
| Presentation Exchange | [DCQL](https://docs.walt.id/concepts/data-exchange-protocols/dcql.md) | Different query format for [OID4VP](https://docs.walt.id/concepts/data-exchange-protocols/openid4vp.md) |
| `/api/wallet/{walletId}/credentials/usePresentationRequest` | `/wallet/{walletId}/credentials/present` | New presentation endpoint |

---

## Troubleshooting

### "Key store not found" errors

The migration creates stores with deterministic IDs. If you see this error, ensure the target database is empty or the migration completed successfully.

### Credential parsing failures

Some v1 credentials may use formats not fully supported in v2. Check the warning logs for specific credential IDs and manually verify/re-import if needed.

### Database connection issues

Ensure the JDBC URLs are correct and the databases are accessible:
- SQLite: File path must exist and be writable
- PostgreSQL: User must have CREATE TABLE permissions

---

## Rollback

If you need to rollback:

1. Stop the wallet-api2 service
2. Restore your v1 database from backup
3. Start the wallet-api (v1) service pointing to the restored database

The migration does not modify the source database, so your v1 data remains intact.
