> ## 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.

# App secrets

> Create app secrets with full access or read-only access to authenticate server requests to the Privy API.

App secrets authenticate your server's requests to the Privy API. Each request sends your app ID and an app secret with [Basic authentication](/api-reference/introduction.md), along with the `privy-app-id` header.

> [!WARNING]
>
> Never expose an app secret outside of your backend server. Privy does not store your app secret.
> Lost app secrets cannot be recovered and must be re-generated.

## Access levels

When you create an app secret, you choose its access level:

| Access level | What it can do |
| - | - |
| **Full access** | Can view, create, update, and delete your app's resources and data. |
| **Read-only** | Can view your app's data, but cannot create, update, or delete anything. |

Use read-only secrets for services that only need to look up data, such as analytics pipelines, support tools, internal dashboards, and reconciliation jobs. If a read-only secret is exposed, it cannot be used to create wallets, sign transactions, or change your app's configuration.

App secrets created before access levels were introduced have full access.

> [!NOTE]
>
> The access level of an app secret cannot be changed after it is generated. To change access,
> generate a new secret with the access level you need and delete the old one.

## Create an app secret

1. Go to [Configuration > App settings > Basics](https://dashboard.privy.io/apps?page=settings\&tab=basics) in the Privy Dashboard.
2. Under **API keys**, select **New secret**.
3. Select **Full access** or **Read-only** as the access level.
4. Select **Generate secret**, then copy the secret and store it in a secret manager.

Each app can have up to 5 app secrets. Only teammates with the [Admin role](/basics/get-started/dashboard/teammate-roles.md#admin) can create and delete app secrets.

## Read-only access

### Supported endpoints

A read-only app secret can call all `GET` endpoints except the following:

| Endpoint | Description |
| - | - |
| [`/v1/intents`](/api-reference/intents/list) | List intents |
| [`/v1/intents/{intent_id}`](/api-reference/intents/get) | Get intent |
| `/v1/apps/{app_id}/test_credentials` | Get test credentials |

A read-only app secret can also call the following `POST` endpoints, which look up data without changing it:

| Endpoint | Description |
| - | - |
| [`/v1/users/custom_auth/id`](/api-reference/users/get-by-custom-auth) | Get user by custom auth ID |
| [`/v1/users/discord/username`](/api-reference/users/get-by-discord-username) | Get user by Discord username |
| [`/v1/users/email/address`](/api-reference/users/get-by-email-address) | Get user by email address |
| [`/v1/users/farcaster/fid`](/api-reference/users/get-by-farcaster-id) | Get user by Farcaster ID |
| [`/v1/users/github/username`](/api-reference/users/get-by-github-username) | Get user by GitHub username |
| [`/v1/users/instagram/username`](/api-reference/users/get-by-instagram-username) | Get user by Instagram username |
| [`/v1/users/phone/number`](/api-reference/users/get-by-phone-number) | Get user by phone number |
| [`/v1/users/search`](/api-reference/users/search) | Search users |
| [`/v1/users/smart_wallet/address`](/api-reference/users/get-by-smart-wallet-address) | Get user by smart wallet address |
| [`/v1/users/spotify/subject`](/api-reference/users/get-by-spotify-subject) | Get user by Spotify subject |
| [`/v1/users/telegram/telegram_user_id`](/api-reference/users/get-by-telegram-user-id) | Get user by Telegram user ID |
| [`/v1/users/telegram/username`](/api-reference/users/get-by-telegram-username) | Get user by Telegram username |
| [`/v1/users/twitch/username`](/api-reference/users/get-by-twitch-username) | Get user by Twitch username |
| [`/v1/users/twitter/subject`](/api-reference/users/get-by-twitter-subject) | Get user by Twitter subject |
| [`/v1/users/twitter/username`](/api-reference/users/get-by-twitter-username) | Get user by Twitter username |
| [`/v1/users/wallet/address`](/api-reference/users/get-by-wallet-address) | Get user by wallet address |
| [`/v1/wallets/address`](/api-reference/wallets/get-by-address) | Get wallet by address |
| [`/v1/users/{user_id}/fiat/status`](/api-reference/fiat/status) | Get fiat transaction status |

All other requests require a full access secret, including every request that creates, updates, or deletes a resource.

### Error handling

When a read-only app secret makes a request that requires full access, the API returns a `403 Forbidden` error with the code [`insufficient_app_secret_permissions`](/basics/troubleshooting/error-handling/api-errors#insufficient-app-secret-permissions). These requests do not count toward your app's rate limits.

If your app uses an [IP allowlist](/security/implementation-guide/ip-allowlist.md), Privy checks the allowlist first. A request from an IP address that is not allowlisted receives the IP allowlist's generic `403 Forbidden` error instead.

## Best practices

* **Enforce least privilege.** Give each service the lowest access level it needs. Reserve full access secrets for services that create wallets, send transactions, or manage your app's configuration.
* **Use one secret per service.** Separate secrets let your app rotate or delete credentials for one service without affecting others.
* **Combine with an IP allowlist.** An [IP allowlist](/security/implementation-guide/ip-allowlist.md) limits where any app secret can be used from.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.