Manage API Keys

Create, rotate, and revoke API keys with role-based access and environment scoping.

API keys authenticate every request to the SDP API. Each key is scoped to an environment (sandbox or production) and assigned a role that determines what operations it can perform.

Key format

EnvironmentPrefixSolana network
Sandboxsk_test_devnet
Productionsk_live_mainnet-beta

Roles

RoleDescription
api_adminFull access including custody and platform operations
api_developerRead/write access, excludes custody actions
api_readonlyRead-only access to all resources

Create a key

  1. Navigate to API keys in the sidebar.
  2. Click Create API key in the top right.
  3. Step 1 — Define key details:
    • Name — a descriptive label (e.g., "CI deploy key")
    • Role — Admin, Developer, or Read only
    • Environment — Sandbox or Production
    • Wallet scope — All wallets or Selected wallets
    • Expiration (optional) — date/time picker
  4. Step 2 — Review and confirm: verify the summary and click Create key.
  5. The full key appears in a modal titled API key generated. Click Copy and save it — it will not be shown again.

Rotate a key

In the API keys table, find the active key. Enter a grace period (0–168 hours, default 24) in the inline input and click Rotate. During the grace period both the old and new key are valid.

The new key value appears once in the generated key modal. Save it immediately.

Revoke a key

Click the Delete button next to any key in the table. Revoked keys stop working immediately and cannot be restored.

Create a key

curl -X POST https://api.solana.com/v1/api-keys \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI deploy key",
    "role": "api_developer",
    "environment": "sandbox",
    "walletScope": "all",
    "expiresAt": "2026-12-31T23:59:59Z"
  }'
const response = await fetch("https://api.solana.com/v1/api-keys", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_test_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "CI deploy key",
    role: "api_developer",
    environment: "sandbox",
    walletScope: "all",
    expiresAt: "2026-12-31T23:59:59Z",
  }),
});
const { data } = await response.json();
// data.apiKey.key — save this, only shown once
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.solana.com/v1/api-keys"))
    .header("Authorization", "Bearer sk_test_...")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("""
        {
          "name": "CI deploy key",
          "role": "api_developer",
          "environment": "sandbox",
          "walletScope": "all",
          "expiresAt": "2026-12-31T23:59:59Z"
        }"""))
    .build();

The response includes the full key value — save it, it is only returned once.

Optional fields: allowedIps (CIDR ranges), permissions (fine-grained), signingWalletId, walletBindings.

Rotate a key

curl -X POST https://api.solana.com/v1/api-keys/key_abc123/rotate \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{ "gracePeriodHours": 24 }'
const response = await fetch(
  "https://api.solana.com/v1/api-keys/key_abc123/rotate",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk_test_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ gracePeriodHours: 24 }),
  }
);
const { data } = await response.json();
// data.apiKey — the new key
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.solana.com/v1/api-keys/key_abc123/rotate"))
    .header("Authorization", "Bearer sk_test_...")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("""
        { "gracePeriodHours": 24 }"""))
    .build();

The old key remains valid for the grace period (0–168 hours).

Revoke a key

curl -X DELETE https://api.solana.com/v1/api-keys/key_abc123 \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{ "confirmation": "CI deploy key" }'
await fetch("https://api.solana.com/v1/api-keys/key_abc123", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer sk_test_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ confirmation: "CI deploy key" }),
});
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.solana.com/v1/api-keys/key_abc123"))
    .header("Authorization", "Bearer sk_test_...")
    .header("Content-Type", "application/json")
    .method("DELETE", HttpRequest.BodyPublishers.ofString("""
        { "confirmation": "CI deploy key" }"""))
    .build();

The confirmation field must match the key's name. The key stops working immediately.