Skip to main content
This guide shows how to create Swig wallets programmatically using the Developer Portal API. This approach is ideal for applications that need to create wallets on behalf of users with predefined policies.

When to Use the API

Use the Portal API when:
  • Creating wallets from a backend service
  • Using predefined policies from the Developer Portal
  • Leveraging the paymaster for sponsored wallet creation
  • Managing wallets at scale
Use the SDK directly when:
  • Building client-side applications
  • Users control their own keypairs
  • You need full control over wallet configuration
  • Not using the Developer Portal policies
For direct SDK wallet creation (without the Portal API), see the Creating a Swig tutorial.

Prerequisites

Before creating wallets via the API, ensure you have:
  • An API key created in the Developer Portal
  • A policy configured (with or without a signer)
  • The paymaster public key (provided by Swig or your own paymaster)

Installing the SDK

npm install @swig-wallet/api
# or
bun add @swig-wallet/api

Creating a Swig Wallet

Using the REST API

Make a POST request to the wallet creation endpoint:
curl -X POST "https://dashboard.onswig.com/api/v1/wallet/create" \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "policyId": "clx1234567890abcdef",
    "network": "devnet",
    "paymasterPubkey": "PaymasterPublicKeyHere..."
  }'
Example Response:
{
  "swigId": "a1b2c3d4e5f67890",
  "swigAddress": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  "signature": "5wHu1qwD7g4p3zWxF..."
}

Using the SDK

import { SwigApiClient } from '@swig-wallet/api';

// Initialize the client
const client = new SwigApiClient({
  apiKey: 'sk_your_api_key',
  portalUrl: 'https://dashboard.onswig.com',
});

// Create a wallet
async function createWallet() {
  const { data: wallet, error } = await client.wallet.create({
    policyId: 'clx1234567890abcdef',
    network: 'devnet',
    paymasterPubkey: 'PaymasterPublicKeyHere...',
  });

  if (error) {
    console.error(`Error creating wallet: ${error.message}`);
    return null;
  }

  console.log('Swig ID:', wallet.swigId);
  console.log('Wallet Address:', wallet.swigAddress);
  console.log('Transaction Signature:', wallet.signature);

  return wallet;
}

const wallet = await createWallet();

SDK Comparison

Feature@swig-wallet/api@swig-wallet/developer
Error handlingReturns { data, error }Throws SwigError
Method nameclient.wallet.create()client.createWallet()
Response typeBasic objectSame basic object
Best forLow-level controlDeveloper convenience

Request Parameters

Required Parameters

ParameterTypeDescription
policyIdstringThe policy ID from the Developer Portal
network'mainnet' | 'devnet'Target Solana network
paymasterPubkeystringPublic key of the paymaster covering fees

Optional Parameters

ParameterTypeDescription
swigIdstringCustom Swig ID (auto-generated if not provided)
signerIdstringOverride or provide signer ID when policy has no signer

Response Fields

FieldTypeDescription
swigIdstringThe 8-byte identifier for this Swig wallet
swigAddressstringThe on-chain PDA address of the wallet
signaturestringThe transaction signature (viewable on explorer)

Examples

Basic Wallet Creation

import { SwigApiClient } from '@swig-wallet/api';

const client = new SwigApiClient({
  apiKey: process.env.SWIG_API_KEY!,
  portalUrl: 'https://dashboard.onswig.com',
});

const { data, error } = await client.wallet.create({
  policyId: 'your-policy-id',
  network: 'devnet',
  paymasterPubkey: 'YourPaymasterPublicKey',
});

if (data) {
  console.log(`Wallet created: ${data.swigAddress}`);
  console.log(`View on explorer: https://explorer.solana.com/address/${data.swigAddress}?cluster=devnet`);
}

With Custom Swig ID

// Generate a custom ID (must be unique)
const customId = crypto.randomUUID().replace(/-/g, '').slice(0, 16);

const { data, error } = await client.wallet.create({
  policyId: 'your-policy-id',
  network: 'devnet',
  paymasterPubkey: 'YourPaymasterPublicKey',
  swigId: customId,
});

With Signer Override

If your policy doesn’t have a signer attached, or you want to use a different signer:
const { data, error } = await client.wallet.create({
  policyId: 'policy-without-signer',
  network: 'devnet',
  paymasterPubkey: 'YourPaymasterPublicKey',
  signerId: 'specific-signer-id', // Signer ID from the portal
});

Production Wallet

const { data, error } = await client.wallet.create({
  policyId: 'production-policy-id',
  network: 'mainnet', // Use mainnet for production
  paymasterPubkey: 'ProductionPaymasterKey',
});

if (data) {
  // Store the wallet info in your database
  await db.wallets.create({
    swigId: data.swigId,
    address: data.swigAddress,
    createdAt: new Date(),
  });
}

Error Handling

const { data, error } = await client.wallet.create({
  policyId: 'your-policy-id',
  network: 'devnet',
  paymasterPubkey: 'YourPaymasterPublicKey',
});

if (error) {
  switch (error.code) {
    case 'NOT_FOUND':
      console.error('Policy not found. Check the policy ID.');
      break;
    case 'UNAUTHORIZED':
      console.error('Invalid API key.');
      break;
    case 'BAD_REQUEST':
      console.error('Invalid request:', error.details);
      break;
    case 'CONFLICT':
      console.error('Swig ID already exists. Try a different ID.');
      break;
    default:
      console.error(`Unexpected error: ${error.message}`);
  }
}

Common Errors

StatusCodeMeaning
400BAD_REQUESTInvalid request parameters
401UNAUTHORIZEDInvalid or missing API key
404NOT_FOUND / POLICY_NOT_FOUNDPolicy or signer not found
409CONFLICT / SWIG_ID_EXISTSSwig ID already exists
500INTERNAL_ERRORServer error, try again

Complete Example

import { SwigApiClient } from '@swig-wallet/api';

async function main() {
  const client = new SwigApiClient({
    apiKey: process.env.SWIG_API_KEY!,
    portalUrl: 'https://dashboard.onswig.com',
    retry: { maxRetries: 3, retryDelay: 1000 },
  });

  const config = {
    policyId: process.env.SWIG_POLICY_ID!,
    network: (process.env.SWIG_NETWORK || 'devnet') as 'mainnet' | 'devnet',
    paymasterPubkey: process.env.SWIG_PAYMASTER_PUBKEY!,
  };

  console.log('Creating Swig wallet...');
  console.log(`Network: ${config.network}`);
  console.log(`Policy: ${config.policyId}`);

  const { data: wallet, error } = await client.wallet.create(config);

  if (error) {
    console.error('Failed to create wallet:', error.message);
    console.error('Error code:', error.code);
    process.exit(1);
  }

  console.log('\n=== Wallet Created ===');
  console.log(`Swig ID: ${wallet.swigId}`);
  console.log(`Address: ${wallet.swigAddress}`);
  console.log(`Transaction: ${wallet.signature}`);

  const cluster = config.network === 'mainnet' ? '' : '?cluster=devnet';
  console.log(`\nExplorer: https://explorer.solana.com/address/${wallet.swigAddress}${cluster}`);
}

main();

TypeScript Types

interface CreateWalletRequest {
  /** Policy ID to use for wallet creation */
  policyId: string;
  /** Optional signer ID to override or provide */
  signerId?: string;
  /** Optional swig ID (generated if not provided) */
  swigId?: string;
  /** Network to use */
  network: 'mainnet' | 'devnet';
  /** Paymaster public key */
  paymasterPubkey: string;
}

interface CreateWalletResponse {
  /** Swig ID (8-byte identifier) */
  swigId: string;
  /** Swig wallet address */
  swigAddress: string;
  /** Transaction signature */
  signature: string;
}

Comparison: API vs Direct SDK

FeaturePortal APIDirect SDK
Uses predefined policiesYesNo
Requires API keyYesNo
Paymaster sponsoredYesOptional
Full configuration controlLimited to policyFull
Best forBackend servicesClient apps
Keypair managementServer-sideClient-side

Next Steps

After creating a wallet, you can: