Skip to main content
Once you’ve created policies in the Developer Portal, you can fetch their details programmatically. This guide shows the current package choices for policy reads and how to retrieve policy information through the REST API and TypeScript clients.
This page covers the portal-facing clients @swig-wallet/api and @swig-wallet/developer. For the primary prepare-first Swig Developer SDK, see What the Developer SDK Does. Treat @swig-wallet/developer as the legacy SDK for new integrations. The current @swig-wallet/developer-sdk package is optimized for prepared wallet operations. It does expose swig.wallets.getPolicy(policyId), but it returns raw policy metadata rather than the richer helper surface from the legacy SDK.

Prerequisites

Before fetching policies, ensure you have:
  • An API key created in the Developer Portal
  • A policy created that you want to fetch
  • The policy ID (visible in the portal’s policy details)

Choose the Right Package

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

Fetching a Policy

Using the REST API

Make a GET request to the policies endpoint:
curl -X GET "https://dashboard.onswig.com/api/v1/policies/{policyId}" \
  -H "Authorization: Bearer sk_your_api_key"
Replace {policyId} with your actual policy ID (e.g., clx1234567890abcdef). Example Response:
{
  "id": "clx1234567890abcdef",
  "name": "user-wallet-policy",
  "description": "Standard user wallet with transfer limits",
  "authority": {
    "type": "Ed25519",
    "publicKey": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
  },
  "actions": [
    { "type": "SolLimit", "amount": "1000000000" },
    { "type": "TokenLimit", "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "amount": "1000000" }
  ]
}

Using a Portal Client

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

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

// Fetch a policy
async function getPolicy(policyId: string) {
  const { data: policy, error } = await client.policies.get(policyId);

  if (error) {
    console.error(`Error fetching policy: ${error.message}`);
    console.error(`Error code: ${error.code}, Status: ${error.status}`);
    return null;
  }

  console.log('Policy:', policy.name);
  console.log('Description:', policy.description);

  if (policy.authority) {
    console.log('Authority Type:', policy.authority.type);
    console.log('Authority Key:', policy.authority.publicKey);
  } else {
    console.log('Authority: Not configured (provide at wallet creation)');
  }

  console.log('Actions:', policy.actions.map(a => a.type).join(', '));

  return policy;
}

// Usage
const policy = await getPolicy('clx1234567890abcdef');

If You’re Already Using the Current SDK

If your app already uses @swig-wallet/developer-sdk for prepared wallet operations, you can read the same raw policy metadata the SDK uses during wallet creation and recovery flows:
import { SwigClient } from '@swig-wallet/developer-sdk/server/typescript';

const swig = new SwigClient({
  apiKey: process.env.SWIG_API_KEY!,
  network: 'devnet',
});

const policy = await swig.wallets.getPolicy('clx1234567890abcdef');

console.log(policy.name);
console.log(policy.guardianEnabled);
console.log(policy.guardianDelaySeconds);
console.log(policy.actions);
Use this when policy lookup is part of a prepared-wallet flow. For standalone policy inspection, prefer @swig-wallet/api. For richer helper methods around actions and authorities, use the legacy @swig-wallet/developer client.

Package Fit

PackagePrimary jobPolicy surface
@swig-wallet/apiRaw portal endpoint accessclient.policies.get() returns raw policy JSON
@swig-wallet/developer-sdkPrepared wallet operationsswig.wallets.getPolicy() returns raw policy metadata used by hosted flows
@swig-wallet/developer (legacy)Existing rich portal integrationsclient.getPolicy() returns richer helper types and query methods
If you are starting fresh and only need to fetch policies, prefer @swig-wallet/api. If you are starting fresh and need hosted wallet operations, use @swig-wallet/developer-sdk and treat policy reads as a supporting detail rather than the primary interface.

Response Types

Policy

interface Policy {
  /** Unique policy ID */
  id: string;
  /** Policy name */
  name: string;
  /** Optional description */
  description: string | null;
  /** Authority configuration (signer) - null if not configured */
  authority: AuthorityConfig | null;
  /** Action configurations (permissions) */
  actions: ActionConfig[];
}

Authority Configuration

The authority field can be one of several types:
type AuthorityConfig =
  | { type: 'Ed25519'; publicKey: string }
  | { type: 'Ed25519Session'; publicKey: string; maxDurationSlots: string }
  | { type: 'Secp256k1'; publicKey: string }
  | { type: 'Secp256k1Session'; publicKey: string; maxDurationSlots: string }
  | { type: 'Secp256r1'; publicKey: string }
  | { type: 'Secp256r1Session'; publicKey: string; maxDurationSlots: string };

Action Configuration

The actions array contains one or more action configurations:
type ActionConfig =
  // General permissions
  | { type: 'All' }
  | { type: 'AllButManageAuthority' }
  | { type: 'ManageAuthority' }

  // SOL transfer limits
  | { type: 'SolLimit'; amount: string }
  | { type: 'SolRecurringLimit'; recurringAmount: string; window: string }
  | { type: 'SolDestinationLimit'; amount: string; destination: string }
  | { type: 'SolRecurringDestinationLimit'; recurringAmount: string; window: string; destination: string }

  // Token transfer limits
  | { type: 'TokenLimit'; mint: string; amount: string }
  | { type: 'TokenRecurringLimit'; mint: string; recurringAmount: string; window: string }
  | { type: 'TokenDestinationLimit'; mint: string; amount: string; destination: string }
  | { type: 'TokenRecurringDestinationLimit'; mint: string; recurringAmount: string; window: string; destination: string }

  // Program access
  | { type: 'Program'; programId: string }
  | { type: 'ProgramAll' }
  | { type: 'ProgramCurated' }

  // Staking
  | { type: 'StakeLimit'; amount: string }
  | { type: 'StakeRecurringLimit'; recurringAmount: string; window: string }
  | { type: 'StakeAll' }

  // Sub-accounts
  | { type: 'SubAccount' };

Error Handling

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

const client = new SwigApiClient({
  apiKey: 'sk_your_api_key',
});

const { data, error } = await client.policies.get('invalid-policy-id');

if (error) {
  // ApiError properties:
  // - message: Human-readable error message
  // - code: Error code string (e.g., 'NOT_FOUND', 'UNAUTHORIZED')
  // - status: HTTP status code
  // - details: Additional error context (if available)

  switch (error.code) {
    case 'NOT_FOUND':
      console.log('Policy does not exist');
      break;
    case 'UNAUTHORIZED':
      console.log('Invalid or expired API key');
      break;
    default:
      console.log(`Unexpected error: ${error.message}`);
  }
}

Common Errors

StatusCodeMeaning
401UNAUTHORIZEDInvalid or missing API key
403FORBIDDENAPI key doesn’t have access to this policy
404NOT_FOUND / POLICY_NOT_FOUNDPolicy ID doesn’t exist
500INTERNAL_ERRORServer error, try again later

Retry Configuration

Both SDKs support automatic retries for transient failures:
const client = new SwigApiClient({
  apiKey: 'sk_your_api_key',
  portalUrl: 'https://dashboard.onswig.com',
  retry: {
    maxRetries: 3,        // Number of retry attempts
    retryDelay: 1000,     // Initial delay in milliseconds
    backoffMultiplier: 2, // Exponential backoff multiplier
  },
});
With these settings, retries occur at: 1s, 2s, 4s (exponential backoff).
Both SDKs only retry on 5xx server errors and network failures. Client errors (4xx) are not retried.

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 policyId = 'your-policy-id';
  const { data: policy, error } = await client.policies.get(policyId);

  if (error) {
    console.error('Failed to fetch policy:', error.message);
    process.exit(1);
  }

  console.log('=== Policy Details ===');
  console.log(`ID: ${policy.id}`);
  console.log(`Name: ${policy.name}`);
  console.log(`Description: ${policy.description ?? 'None'}`);

  console.log('\n=== Authority ===');
  if (policy.authority) {
    console.log(`Type: ${policy.authority.type}`);
    console.log(`Public Key: ${policy.authority.publicKey}`);
  } else {
    console.log('No authority configured');
  }

  console.log('\n=== Actions ===');
  for (const action of policy.actions) {
    console.log(`- ${action.type}`);
  }
}

main();

Next Steps

Now that you can fetch policies, learn how to create Swig wallets using those policies.