> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Signing with utility functions

If your integration cannot leverage the [automatic signing](/controls/authorization-keys/using-owners/sign/signing-on-the-server) capabilities of Privy's SDKs, Privy also offers utility functions for formatting and signing requests.

You can use these functions to sign requests, even without initializing an instance of the Privy SDK, and then can manually include the returned signature in requests to the Privy API.

## Client-side SDKs

There are two ways to sign requests on the client:

1. **Sign a server-formatted binary payload (recommended)** — Your server formats the request into canonical bytes using the server SDK, sends the bytes to the client, and the client signs them directly. This gives the server full control over payload construction and allows server-side changes without requiring client SDK updates.
2. **Sign a structured payload** — The client constructs the payload locally and signs it. This approach is simpler for prototyping but couples the client to the payload format.

### Signing a server-formatted binary payload (recommended)

In this approach, your server serializes the API request into canonical bytes using Privy's server SDK. The client receives these bytes and signs them directly, without needing to understand the payload structure.

This is the recommended approach because:

* Your server has full control over constructing the correct payload
* Server-side updates to the payload format do not require client SDK changes
* The client does not need to construct or serialize the payload itself

<Steps>
  <Step title="Format the payload on your server">
    Use the server SDK's `formatRequestForAuthorizationSignature` function to serialize the request
    into bytes. See [Formatting requests](#formatting-requests) below for the full reference.

    ```ts theme={"system"}
    import {formatRequestForAuthorizationSignature} from '@privy-io/node';

    const serializedPayload = formatRequestForAuthorizationSignature({
      version: 1,
      url: 'https://api.privy.io/v1/wallets/<wallet-id>/rpc',
      method: 'POST',
      headers: {'privy-app-id': '<app-id>'},
      body: {
        method: 'personal_sign',
        params: {message: 'Hello from Privy!', encoding: 'utf-8'}
      }
    });

    // Send the bytes to your client as base64
    const payloadBase64 = Buffer.from(serializedPayload).toString('base64');
    ```
  </Step>

  <Step title="Send the binary payload to your client">
    Send the base64-encoded bytes from your server to the client (e.g., as a JSON response field).
  </Step>

  <Step title="Sign the binary payload on the client">
    Decode the base64 payload and pass the raw bytes to `generateAuthorizationSignature`.

    <Tabs>
      <Tab title="React">
        ```tsx theme={"system"}
        import {useAuthorizationSignature} from '@privy-io/react-auth';

        const {generateAuthorizationSignature} = useAuthorizationSignature();

        // Decode the base64 payload received from the server
        const payloadBytes = Uint8Array.from(atob(payloadBase64), (c) => c.charCodeAt(0));

        // Sign the binary payload
        const {signature} = await generateAuthorizationSignature(payloadBytes);
        ```
      </Tab>

      <Tab title="React Native">
        ```tsx theme={"system"}
        import {useAuthorizationSignature} from '@privy-io/expo';
        import {Buffer} from 'buffer';

        const {generateAuthorizationSignature} = useAuthorizationSignature();

        // Decode the base64 payload received from the server
        const payloadBytes = new Uint8Array(Buffer.from(payloadBase64, 'base64'));

        // Sign the binary payload
        const {signature} = await generateAuthorizationSignature(payloadBytes);
        ```
      </Tab>

      <Tab title="Swift">
        ```swift theme={"system"}
        guard let user = try await privy.getUser() else { return }

        // Decode the base64 payload received from the server
        guard let payloadData = Data(base64Encoded: payloadBase64) else { return }

        // Sign the binary payload
        let signature = try await user.generateAuthorizationSignature(payload: payloadData)
        ```
      </Tab>

      <Tab title="Android">
        ```kotlin theme={"system"}
        import kotlin.io.encoding.Base64
        import kotlin.io.encoding.ExperimentalEncodingApi

        val user = privy.getUser() ?: return

        // Decode the base64 payload received from the server
        @OptIn(ExperimentalEncodingApi::class)
        val payloadBytes = Base64.decode(payloadBase64)

        // Sign the binary payload
        user.generateAuthorizationSignature(payloadBytes)
            .onSuccess { signature ->
                // Use signature in API request headers as 'privy-authorization-signature'
            }
            .onFailure { error ->
                // Handle error
            }
        ```
      </Tab>

      <Tab title="Unity">
        ```csharp theme={"system"}
        using System;
        using Privy.Auth.Models;

        IPrivyUser user = await PrivyManager.Instance.GetUser();

        // Decode the base64 payload received from the server
        byte[] payloadBytes = Convert.FromBase64String(payloadBase64);

        // Sign the binary payload
        string signature = await user.GenerateAuthorizationSignature(payloadBytes);
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Send the signature to your backend">
    Return the base64-encoded signature string to your server.
  </Step>

  <Step title="Send the request to the Privy API">
    From your server, include the signature when making the request to the Privy API. You can pass
    it via the Node SDK's `authorization_context.signatures` field, or include it directly as the
    `privy-authorization-signature` header.

    <Tabs>
      <Tab title="Node SDK">
        ```ts theme={"system"}
        import {PrivyClient} from '@privy-io/node';

        const client = new PrivyClient({appId: '<app-id>', appSecret: '<app-secret>'});

        // Pass the client-generated signature in authorization_context
        const response = await client.wallets().rpc('<wallet-id>', {
          method: 'personal_sign',
          params: {message: 'Hello from Privy!', encoding: 'utf-8'},
          authorization_context: {signatures: [signature]}
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```ts theme={"system"}
        fetch('https://api.privy.io/v1/wallets/<wallet-id>/rpc', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Basic ${btoa('<app-id>:<app-secret>')}`,
            'privy-app-id': '<app-id>',
            'privy-authorization-signature': signature
          },
          body: JSON.stringify({
            method: 'personal_sign',
            params: {message: 'Hello from Privy!', encoding: 'utf-8'}
          })
        });
        ```
      </Tab>
    </Tabs>
  </Step>
</Steps>

### Signing a structured payload

Alternatively, the client can construct the signature payload locally and sign it directly. The SDK canonicalizes the payload to JSON (RFC 8785) before signing.

#### 1. Construct your signature payload

Given your desired request to the Privy API, build a JSON payload with the following fields. Your application will sign this entire payload to authorize the request to the Privy API.

| Field                              | Type                                                                                                                                                                                                                                                  | Description                                                                                                                                                                                                       |   |   |   |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | - |
| `version`                          | `1`                                                                                                                                                                                                                                                   | Authorization signature version. Currently, `1` is the only version.                                                                                                                                              |   |   |   |
| `method`                           | `'POST'  \| 'PUT'                                                                                                                                                                                                             \| 'PATCH' \| 'DELETE'` | HTTP method for the request. Signatures are not required on `'GET'` requests.                                                                                                                                     |   |   |   |
| `url`                              | `string`                                                                                                                                                                                                                                              | The full URL for the request. Should not include a trailing slash.                                                                                                                                                |   |   |   |
| `body`                             | `JSON`                                                                                                                                                                                                                                                | JSON body for the request.                                                                                                                                                                                        |   |   |   |
| `headers`                          | `JSON`                                                                                                                                                                                                                                                | JSON object containing any Privy-specific headers, e.g. those that are prefixed with `'privy-'`. This should **not** include any other headers, such as authentication headers, `content-type`, or trace headers. |   |   |   |
| `headers['privy-app-id']`          | `string`                                                                                                                                                                                                                                              | Privy app ID header (required).                                                                                                                                                                                   |   |   |   |
| `headers['privy-idempotency-key']` | `string`                                                                                                                                                                                                                                              | Privy idempotency key header (optional). If the request does not contain an idempotency key, leave this field out of the payload.                                                                                 |   |   |   |
| `headers['privy-request-expiry']`  | `string`                                                                                                                                                                                                                                              | Privy request expiry header (optional). If the request does not contain an expiry header, leave this field out of the payload.                                                                                    |   |   |   |

As an example, you might build a payload for an Ethereum `personal_sign` RPC request like so:

<Tabs>
  <Tab title="TypeScript">
    ```ts theme={"system"}
    const signaturePayload = {
      version: 1,
      url: 'https://api.privy.io/v1/wallets/<wallet-id>/rpc',
      method: 'POST',
      headers: {
        'privy-app-id': '<app-id>'
      },
      body: {
        method: 'personal_sign',
        params: {
          message: 'Hello from Privy!',
          encoding: 'utf-8'
        }
      }
    } as const;
    ```
  </Tab>

  <Tab title="Swift">
    ```swift theme={"system"}
    import PrivySDK

    // Define structs for the request body (must conform to Encodable)
    struct PersonalSignParams: Encodable {
    let message: String
    let encoding: String
    }

    struct PersonalSignRpcRequest: Encodable {
    let method: String
    let params: PersonalSignParams
    }

    // Create the RPC request body
    let rpcRequest = PersonalSignRpcRequest(
    method: "personal_sign",
    params: PersonalSignParams(message: "Hello from Privy!", encoding: "utf-8")
    )

    // Create the signature payload using WalletApiPayload
    let signaturePayload = WalletApiPayload(
    version: 1,
    url: "https://api.privy.io/v1/wallets/<wallet-id>/rpc",
    method: "POST",
    headers: ["privy-app-id": "<app-id>"],
    body: rpcRequest
    )

    ```

    ### WalletApiPayload parameters

    <ParamField path="version" type="Int" required>
      The payload version. Currently, only version `1` is supported.
    </ParamField>

    <ParamField path="url" type="String" required>
      The full URL of the API endpoint, including protocol and domain. Should not include a trailing
      slash.
    </ParamField>

    <ParamField path="method" type="String" required>
      The HTTP method for the request (e.g., `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`).
    </ParamField>

    <ParamField path="headers" type="[String: String]" required>
      Privy-specific headers (those prefixed with `privy-`). This should not include authentication
      headers, content-type, or trace headers. The `privy-app-id` header is always required.
    </ParamField>

    <ParamField path="body" type="T: Encodable" required>
      The request body to be serialized and included in the signature. Must conform to `Encodable`.
    </ParamField>
  </Tab>

  <Tab title="Android">
    <Warning>
      The request body type and all nested types must be annotated with `@Serializable` from
      `kotlinx.serialization`.
    </Warning>

    ```kotlin theme={"system"}
    import io.privy.wallet.walletApi.WalletApiPayload
    import kotlinx.serialization.Serializable

    // Define data classes for the request body (must be @Serializable)
    @Serializable
    data class PersonalSignParams(
        val message: String,
        val encoding: String
    )

    @Serializable
    data class PersonalSignRpcRequest(
        val method: String,
        val params: PersonalSignParams
    )

    // Create the RPC request body
    val rpcRequest = PersonalSignRpcRequest(
        method = "personal_sign",
        params = PersonalSignParams(message = "Hello from Privy!", encoding = "utf-8")
    )

    // Create the signature payload using WalletApiPayload
    val signaturePayload = WalletApiPayload(
        version = 1,
        url = "https://api.privy.io/v1/wallets/<wallet-id>/rpc",
        method = "POST",
        headers = mapOf("privy-app-id" to "<app-id>"),
        body = rpcRequest
    )
    ```

    ### WalletApiPayload parameters

    <ParamField path="version" type="Int" required>
      The payload version. Currently, only version `1` is supported.
    </ParamField>

    <ParamField path="url" type="String" required>
      The full URL of the API endpoint, including protocol and domain. Should not include a trailing
      slash.
    </ParamField>

    <ParamField path="method" type="String" required>
      The HTTP method for the request (e.g., `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`).
    </ParamField>

    <ParamField path="headers" type="Map<String, String>" required>
      Privy-specific headers (those prefixed with `privy-`). This should not include authentication
      headers, content-type, or trace headers. The `privy-app-id` header is always required.
    </ParamField>

    <ParamField path="body" type="T: @Serializable" required>
      The request body to be serialized and included in the signature. Must be annotated with
      `@Serializable`.
    </ParamField>
  </Tab>

  <Tab title="Flutter">
    In Flutter, the body is passed as a `Map<String, dynamic>` — no special serialization annotations are needed.

    ```dart theme={"system"}
    import 'package:privy_flutter/privy_flutter.dart';

    // Create the RPC request body as a Map
    final rpcRequestBody = {
      'method': 'personal_sign',
      'params': {
        'message': 'Hello from Privy!',
        'encoding': 'utf-8',
      },
    };

    // Create the signature payload
    final signaturePayload = WalletApiPayload(
      version: 1,
      url: 'https://api.privy.io/v1/wallets/<wallet-id>/rpc',
      method: 'POST',
      headers: {'privy-app-id': '<app-id>'},
      body: rpcRequestBody,
    );
    ```

    ### WalletApiPayload parameters

    <ParamField path="version" type="int" required>
      The payload version. Currently, only version `1` is supported.
    </ParamField>

    <ParamField path="url" type="String" required>
      The full URL of the API endpoint, including protocol and domain. Should not include a trailing
      slash.
    </ParamField>

    <ParamField path="method" type="String" required>
      The HTTP method for the request (e.g., `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`).
    </ParamField>

    <ParamField path="headers" type="Map<String, String>" required>
      Privy-specific headers (those prefixed with `privy-`). This should not include authentication
      headers, content-type, or trace headers. The `privy-app-id` header is always required.
    </ParamField>

    <ParamField path="body" type="Map<String, dynamic>" required>
      The request body as a JSON-serializable map. Serialized automatically before signing.
    </ParamField>
  </Tab>

  <Tab title="Unity">
    In Unity, the body is passed as an `object` — any JSON-serializable type works (Newtonsoft.Json handles serialization).

    ```csharp theme={"system"}
    using System.Collections.Generic;
    using Privy.Wallets;

    // Create the signature payload
    var signaturePayload = new WalletApiPayload
    {
        Version = 1,
        Url = "https://api.privy.io/v1/wallets/<wallet-id>/rpc",
        Method = "POST",
        Headers = new Dictionary<string, string> { { "privy-app-id", "<app-id>" } },
        Body = new
        {
            method = "personal_sign",
            @params = new { message = "Hello from Privy!", encoding = "utf-8" }
        }
    };
    ```

    ### WalletApiPayload parameters

    <ParamField path="Version" type="int" required>
      The payload version. Currently, only version `1` is supported.
    </ParamField>

    <ParamField path="Url" type="string" required>
      The full URL of the API endpoint, including protocol and domain. Should not include a trailing
      slash.
    </ParamField>

    <ParamField path="Method" type="string" required>
      The HTTP method for the request (e.g., `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`).
    </ParamField>

    <ParamField path="Headers" type="Dictionary<string, string>" required>
      Privy-specific headers (those prefixed with `privy-`). This should not include authentication
      headers, content-type, or trace headers. The `privy-app-id` header is always required.
    </ParamField>

    <ParamField path="Body" type="object" required>
      The request body. Must be JSON-serializable via Newtonsoft.Json.
    </ParamField>
  </Tab>
</Tabs>

#### 2. Sign your request

Next, use the SDK's `generateAuthorizationSignature` method to sign the request. Pass the payload from step (1) as a parameter to this method.

The method will sign the request with the current authenticated user's signing key, and return the base64-encoded signature.

<Tabs>
  <Tab title="React">
    ```tsx theme={"system"}
    import {useAuthorizationSignature} from '@privy-io/react-auth';

    const {generateAuthorizationSignature} = useAuthorizationSignature();

    // Sign the request using the current authenticated user's signing key.
    // The `signaturePayload` here refers to the JSON payload constructed in step (1).
    const authorizationSignature = await generateAuthorizationSignature(signaturePayload);
    ```
  </Tab>

  <Tab title="React Native">
    ```tsx theme={"system"}
    import {useAuthorizationSignature} from '@privy-io/expo';

    const {generateAuthorizationSignature} = useAuthorizationSignature();

    // Sign the request using the current authenticated user's signing key.
    // The `signaturePayload` here refers to the JSON payload constructed in step (1).
    const authorizationSignature = await generateAuthorizationSignature(signaturePayload);
    ```
  </Tab>

  <Tab title="Swift">
    Use the `generateAuthorizationSignature` method on the `PrivyUser` object to sign the request.

    ### Usage

    ```swift theme={"system"}
    // Get the authenticated user
    guard let user = try await privy.getUser() else {
        // User is not authenticated
        return
    }

    // Sign the request using the payload from step (1)
    do {
        let authorizationSignature = try await user.generateAuthorizationSignature(payload: signaturePayload)
        // Use signature in API request headers as 'privy-authorization-signature'
    } catch {
        // Handle error
    }
    ```

    ### Returns

    <ResponseField name="signature" type="String">
      The cryptographic signature as a base64-encoded `String` that can be included in Privy API
      requests as the `privy-authorization-signature` header.
    </ResponseField>
  </Tab>

  <Tab title="Android">
    Use the `generateAuthorizationSignature` method on the `PrivyUser` object to sign the request.

    ### Usage

    ```kotlin theme={"system"}
    val user = privy.getUser() ?: return

    // Sign the request using the payload from step (1)
    user.generateAuthorizationSignature(signaturePayload)
        .onSuccess { authorizationSignature ->
            // Use signature in API request headers as 'privy-authorization-signature'
        }
        .onFailure { error ->
            // Handle error
        }
    ```

    ### Returns

    <ResponseField name="signature" type="String">
      The cryptographic signature as a base64-encoded `String` that can be included in Privy API
      requests as the `privy-authorization-signature` header.
    </ResponseField>
  </Tab>

  <Tab title="Flutter">
    Use the `generateAuthorizationSignature` method on the `PrivyUser` object to sign the request.

    ### Usage

    ```dart theme={"system"}
    final user = await privy.getUser();
    if (user == null) return;

    // Sign the request using the payload from step (1)
    final result = await user.generateAuthorizationSignature(signaturePayload);

    result.fold(
      onSuccess: (signature) {
        // Use signature in API request headers as 'privy-authorization-signature'
        print('Signature: $signature');
      },
      onFailure: (error) {
        // Handle error
        print('Error: $error');
      },
    );
    ```

    ### Returns

    <ResponseField name="signature" type="String (inside Result<String>)">
      The cryptographic signature as a base64-encoded `String` that can be included in Privy API
      requests as the `privy-authorization-signature` header.
    </ResponseField>
  </Tab>

  <Tab title="Unity">
    Use the `GenerateAuthorizationSignature` method on the `IPrivyUser` object to sign the request.

    ### Usage

    ```csharp theme={"system"}
    using Privy.Core;
    using Privy.Auth.Models;

    IPrivyUser user = await PrivyManager.Instance.GetUser();

    // Sign the request using the payload from step (1)
    string signature = await user.GenerateAuthorizationSignature(signaturePayload);
    // Use signature in API request headers as 'privy-authorization-signature'
    ```

    ### Returns

    <ResponseField name="signature" type="string">
      The cryptographic signature as a base64-encoded `string` that can be included in Privy API
      requests as the `privy-authorization-signature` header.
    </ResponseField>
  </Tab>
</Tabs>

#### 3. Send the request and signature to your backend

Next, make a request from your frontend to your backend including the request you intend to make to the Privy API and the corresponding signature from step (2). Your backend will proxy this request to the Privy API.

#### 4. Send the request to the Privy API

Finally, make your request to the Privy API and include the signature in the `privy-authorization-signature` header for your request. As an example, in NodeJS, you can make the request like so:

```ts theme={"system"}
fetch('https://api.privy.io/v1/wallets/<wallet-id>/rpc', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Basic ${btoa('<app-id>:<app-secret>')}`,
    'privy-app-id': '<app-id>',
    'privy-authorization-signature': '<base64-encoded-signature>'
  },
  body: JSON.stringify({
    method: 'personal_sign',
    params: {
      message: 'Hello from Privy!',
      encoding: 'utf-8'
    }
  })
})
  .then((res) => console.log(res))
  .catch((err) => console.error(err));
```

## Server-side SDKs

Privy's server SDKs offer two utilities for signing requests:

* **Formatting requests for authorization signatures.** This accepts your desired request to the Privy API and formats it into the required signature payload to be signed.
  * This utility is particularly helpful if your application signs requests via a separate service, e.g. an isolated KMS. Your primary server can format your request and generate the signature payload and call out to your signing service with the payload.
* **Generating authorization signatures.** This accepts a formatted signature payload and signs it with your provided signing key.
  * This utility is particularly useful within a specific signing service. Within your signing service, you can import this function and use it to sign requests, and return the signature to your primary service.

### Constructing your input

Both the formatting and signing functions of Privy's SDKs require a JSON input with the following fields:

| Field                              | Type                                                                                                                                                                                                                                                  | Description                                                                                                                                                                                                       |   |   |   |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | - |
| `version`                          | `1`                                                                                                                                                                                                                                                   | Authorization signature version. Currently, `1` is the only version.                                                                                                                                              |   |   |   |
| `method`                           | `'POST'  \| 'PUT'                                                                                                                                                                                                             \| 'PATCH' \| 'DELETE'` | HTTP method for the request. Signatures are not required on `'GET'` requests.                                                                                                                                     |   |   |   |
| `url`                              | `string`                                                                                                                                                                                                                                              | The full URL for the request. Should not include a trailing slash.                                                                                                                                                |   |   |   |
| `body`                             | `JSON`                                                                                                                                                                                                                                                | JSON body for the request.                                                                                                                                                                                        |   |   |   |
| `headers`                          | `JSON`                                                                                                                                                                                                                                                | JSON object containing any Privy-specific headers, e.g. those that are prefixed with `'privy-'`. This should **not** include any other headers, such as authentication headers, `content-type`, or trace headers. |   |   |   |
| `headers['privy-app-id']`          | `string`                                                                                                                                                                                                                                              | Privy app ID header (required).                                                                                                                                                                                   |   |   |   |
| `headers['privy-idempotency-key']` | `string`                                                                                                                                                                                                                                              | Privy idempotency key header (optional). If the request does not contain an idempotency key, leave this field out of the payload.                                                                                 |   |   |   |
| `headers['privy-request-expiry']`  | `string`                                                                                                                                                                                                                                              | Privy request expiry header (optional). If the request does not contain an expiry header, leave this field out of the payload.                                                                                    |   |   |   |

### Formatting requests

Use the SDK's formatting function to generate your signature payload. As a parameter to this function, pass the JSON object as defined above.

<CodeGroup>
  ```ts NodeJS theme={"system"}
  import {
    formatRequestForAuthorizationSignature,
    type WalletApiRequestSignatureInput
  } from '@privy-io/node';

  // Replace this with your desired request to the Privy API, including
  // url, method, headers, and body.
  const input: WalletApiRequestSignatureInput = {
    version: 1,
    url: 'https://api.privy.io/v1/wallets/<insert-wallet-id>/rpc',
    method: 'POST',
    headers: {
      'privy-app-id': '<insert-app-id>'
    },
    body: {
      method: 'personal_sign',
      params: {
        message: 'Hello from Privy!',
        encoding: 'utf-8'
      }
    }
  };
  const serializedPayload = formatRequestForAuthorizationSignature(input);
  ```

  ```java Java theme={"system"}
  // Build the request, in this case an ethereum personal_sign request
  EthereumPersonalSignRpcInputParams params = EthereumPersonalSignRpcInputParams.builder()
      .message(message)
      .encoding(Encoding.of(EncodingUtf8.UTF8))
      .build();

  EthereumPersonalSignRpcInput request = EthereumPersonalSignRpcInput.builder()
      .method(EthereumPersonalSignRpcInputMethod.PERSONAL_SIGN)
      .params(params)
      .build();

  byte[] serializedPayload = privyClient.utils()
      .requestFormatter()
      .formatRequestForAuthorizationSignature(
          new WalletApiRequestSignatureInput(
              1,
              request,
              HttpMethod.POST,
              "https://api.privy.io/wallets/<insert-wallet-id>/rpc",
              null
          )
      );
  ```

  ```rust Rust theme={"system"}
  use privy_rs::format_request_for_authorization_signature;
  use privy_rs::generated::types::*;

  // Build the request, in this case an ethereum personal_sign request
  let params = EthereumPersonalSignRpcInputParams {
      message: "Hello from Privy!".to_string(),
      encoding: Some(EthereumPersonalSignRpcInputParamsEncoding::Utf8),
  };

  let request = EthereumPersonalSignRpcInput {
      method: EthereumPersonalSignRpcInputMethod::PersonalSign,
      params,
  };

  let encoded_request_payload = format_request_for_authorization_signature(
      &app_id,
      crate::Method::POST,
      "https://api.privy.io/wallets/<insert-wallet-id>/rpc".to_string(),
      &request,
      None,
  )?;
  ```
</CodeGroup>

You can then take the returned serialized payload and call out to a signing service to generate a P256 signature over the payload.

### Signing requests

To directly produce a signature over a request, use the SDK's generate authorization signature method. As a parameter to this method, pass the JSON object as defined above.

<CodeGroup>
  ```ts Node theme={"system"}
  import {generateAuthorizationSignature, type WalletApiRequestSignatureInput} from '@privy-io/node';

  // Replace this with your desired request to the Privy API, including
  // url, method, headers, and body.
  const input: WalletApiRequestSignatureInput = {
    version: 1,
    url: 'https://api.privy.io/v1/wallets/<insert-wallet-id>/rpc',
    method: 'POST',
    headers: {
      'privy-app-id': '<insert-app-id>'
    },
    body: {
      method: 'personal_sign',
      params: {
        message: 'Hello from Privy!',
        encoding: 'utf-8'
      }
    }
  };
  // Pass your base64 encoded authorization private key as `authorizationPrivateKey`
  const signature = generateAuthorizationSignature({
    input,
    authorizationPrivateKey: 'insert-private-key'
  });
  ```

  ```java Java theme={"system"}
  // Build the request, in this case an ethereum personal_sign request
  EthereumPersonalSignRpcInputParams params = EthereumPersonalSignRpcInputParams.builder()
      .message(message)
      .encoding(Encoding.of(EncodingUtf8.UTF8))
      .build();

  EthereumPersonalSignRpcInput request = EthereumPersonalSignRpcInput.builder()
      .method(EthereumPersonalSignRpcInputMethod.PERSONAL_SIGN)
      .params(params)
      .build();


  String signature = privyClient.utils()
    .requestSigner()
    .generateAuthorizationSignature(
        "authorization-key",
        new WalletApiRequestSignatureInput(
            1,
            request,
            HttpMethod.POST,
            "https://api.privy.io/wallets/<insert-wallet-id>/rpc",
            null
        )
    );
  ```

  ```rust Rust theme={"system"}
  use privy_rs::generate_authorization_signatures;

  let ctx = AuthorizationContext::new().push(key);
  let body = serde_json::json!({"test": "data"});

  // Returns a list of signatures given the authorization context
  let sig = generate_authorization_signatures(
        ctx,
        &self.app_id,
        crate::Method::PATCH,
        format!("{}/v1/policies/{}", self.base_url, policy_id.as_str()),
        body,
        "idempotency_key".to_string(),
    )
    .await?;
  ```
</CodeGroup>

This will return a base64-encoded signature over the payload you defined. Include this signature as the `privy-authorization-signature` header when making the request to the Privy API.
