Skip to content

Setting up your environment

Follow the guide below to set up your environment to execute actions with delegated wallets from your server.

Node SDK vs. REST API

To execute actions with delegated wallets, your server must make HTTP requests to Privy's REST API with information about your intended action and appropriate authorization details.

Privy also offers a NodeJS SDK (@privy-io/server-auth) that wraps requests to Privy's REST API in a simple TypeScript interface. If your app uses a TypeScript/JavaScript backend, we strongly recommend using @privy-io/server-auth for executing delegated actions.

Make sure to follow the instructions here to set up your @privy-io/server-auth client or to configure your HTTP requests to Privy's REST API with the required authorization headers.

Authorization signatures

If your app has an authorization keypair enabled for delegated actions, your server must sign any request payloads for executing actions with delegated wallets with your app's authorization private key. This signature must be included as a privy-authorization-signature header on RPC requests.

Follow the instructions below to ensure authorization signatures are included on requests to Privy's API, if applicable for your app.

Using @privy-io/server-auth

When initializing your instance of the PrivyClient, pass your authorization private key from the dashboard to the client's constructor like so:

tsx
import { PrivyClient } from '@privy-io/server-auth';

...

const privy = new PrivyClient('insert-your-app-id', 'insert-your-app-secret', {
  walletApi: {
    authorizationPrivateKey: 'insert-your-authorization-private-key-from-the-dashboard'
  }
});

If an authorization private key is passed in the constructor, the Privy client will automatically sign requests with the private key and include the signature as the required privy-authorization-signature header to Privy's API.

Using the REST API

If requesting Privy's REST API directly, your app must manually sign request payloads with your authorization private key. This involves three steps at a high-level:

  1. Canonicalize the JSON body of the request per RFC8785 and serialize it to a string. This GitHub repository links to various libraries for JSON canonicalization in different languages.
  2. Sign the serialized JSON with ECDSA P-256 using your app's private key and serialize it to a base64-encoded string.
  3. Include the produced signature as the 'privy-authorization-signature' header for your request.

See the code snippets below for examples of how to serialize and sign requests with your app's private key:

ts
import canonicalize from 'canonicalize';
// Support JSON canonicalization
import crypto from 'crypto';

// Support P-256 signing

// Replace these with your app's private key and desired RPC request
const privateKeyAsString = 'insert-your-private-key-from-dashboard';
const request = {...insertYourRequestBody};

// JSON-canonicalize the payload and convert it to a buffer
const serializedPayload = canonicalize(request) as string;
const serializedPayloadBuffer = Buffer.from(serializedPayload);

// Convert your private key to PEM format, and instantiate a node crypto KeyObject for it
const privateKeyAsPem = `-----BEGIN PRIVATE KEY-----\n${privateKeyAsString}\n-----END PRIVATE KEY-----`;
const privateKey = crypto.createPrivateKey({
  key: privateKeyAsPem,
  format: 'pem',
});

// Sign the payload buffer with your private key and serialize the signature to a base64 string
const signatureBuffer = crypto.sign('sha256', serializedPayloadBuffer, privateKey);
const signature = signatureBuffer.toString('base64');

// Insert the signature as the `privy-authorization-signature` header on your request