Management API SDK
A TypeScript SDK for the Prisma Data Platform Management API. Use the simple client for direct API access, or the full SDK with built-in OAuth authentication and automatic token refresh.
Based on the public OpenAPI 3.1 specification.
Installation
npm install @prisma/management-api-sdkBasic Usage
For usage with an existing access or service token.
Making API Calls
The client provides fully typed methods for all API endpoints:
import { createManagementApiClient } from '@prisma/management-api-sdk'
const client = createManagementApiClient({
token: 'your-access-token',
})
// List workspaces
const { data: workspaces, error } = await client.GET('/v1/workspaces')
// Get a specific project
const { data: project } = await client.GET('/v1/projects/{id}', {
params: { path: { id: 'project-id' } },
})
// Create a new project
const { data: newProject } = await client.POST('/v1/workspaces/{workspaceId}/projects', {
params: { path: { workspaceId: 'workspace-id' } },
body: { name: 'My New Project' },
})
// Create a new database
const { data: newDatabase } = await client.POST('/v1/projects/{projectId}/databases', {
params: { path: { projectId: 'project-id' } },
body: {
name: 'my-new-db-instance',
region: 'us-east-1',
isDefault: true,
},
})
// Delete a database
const { error: deleteError } = await client.DELETE('/v1/databases/{databaseId}', {
params: { path: { databaseId: 'database-id' } },
})Customizing the Client
You can override any ClientOptions from openapi-fetch, including baseUrl, headers, and other fetch options:
import { createManagementApiClient } from '@prisma/management-api-sdk'
// Override baseUrl and add custom headers
const client = createManagementApiClient({
token: 'your-access-token',
baseUrl: 'https://api.example.com',
headers: {
'X-Custom-Header': 'value',
},
})Note: If you provide both token and headers.Authorization, the headers.Authorization takes precedence. The baseUrl defaults to https://api.prisma.io if not provided.
Advanced Usage
For applications that need OAuth authentication, automatic token refresh, and token storage management, use the full SDK.
OAuth Authentication Flow
The SDK uses OAuth 2.0 with PKCE for secure authentication. The flow is stateless - you're responsible for storing the state and verifier between the login URL generation and callback handling.
1. Create the SDK Instance
import { createManagementApiSdk, type TokenStorage } from '@prisma/management-api-sdk'
// Implement token storage for your environment
const tokenStorage: TokenStorage = {
async getTokens() {
const stored = localStorage.getItem('prisma-tokens')
return stored ? JSON.parse(stored) : null
},
async setTokens(tokens) {
localStorage.setItem('prisma-tokens', JSON.stringify(tokens))
},
async clearTokens() {
localStorage.removeItem('prisma-tokens')
},
}
// Create the SDK instance
const api = createManagementApiSdk({
clientId: 'your-oauth-client-id',
redirectUri: 'https://your-app.com/auth/callback',
tokenStorage,
})2. Initiate Login
Generate the OAuth login URL. The returned state and verifier must be stored (e.g., in a session or cookie) for use when handling the callback:
const { url, state, verifier } = await api.getLoginUrl({
scope: 'workspace:admin offline_access',
additionalParams: {
utm_source: 'my-app',
utm_medium: 'login',
},
})
// Store state and verifier for the callback (e.g., in session storage)
sessionStorage.setItem('oauth-state', state)
sessionStorage.setItem('oauth-verifier', verifier)
// Redirect user to the login URL
window.location.href = url3. Handle the Callback
When the user is redirected back to your app, retrieve the stored state and verifier and pass them to handleCallback. On success, tokens are automatically stored via your tokenStorage implementation:
// In your callback route handler
const callbackUrl = window.location.href
// Retrieve the stored values
const expectedState = sessionStorage.getItem('oauth-state')
const verifier = sessionStorage.getItem('oauth-verifier')
// Clean up stored values
sessionStorage.removeItem('oauth-state')
sessionStorage.removeItem('oauth-verifier')
try {
await api.handleCallback({
callbackUrl,
verifier,
expectedState,
})
// Tokens are now stored in tokenStorage and the client is ready to use
console.log('Login successful!')
} catch (error) {
if (error instanceof AuthError) {
console.error('Authentication failed:', error.message)
}
}4. Make API Calls
The client automatically includes authentication headers and refreshes tokens when they expire:
// List workspaces
const { data: workspaces } = await api.client.GET('/v1/workspaces')
// Get a specific project
const { data: project } = await api.client.GET('/v1/projects/{id}', {
params: { path: { id: 'project-id' } },
})
// Create a new project
const { data: newProject } = await api.client.POST('/v1/workspaces/{workspaceId}/projects', {
params: { path: { workspaceId: 'workspace-id' } },
body: { name: 'My Project' },
})
// Create a new database
const { data: newDatabase } = await api.client.POST('/v1/projects/{projectId}/databases', {
params: { path: { projectId: 'project-id' } },
body: {
name: 'production',
region: 'us-east-1',
isDefault: true,
},
})
// Delete a database
const { error: deleteError } = await api.client.DELETE('/v1/databases/{databaseId}', {
params: { path: { databaseId: 'database-id' } },
})5. Logout
await api.logout() // Clears stored tokensToken Storage Interface
Implement this interface to handle token persistence in your environment:
interface TokenStorage {
/** Provide the stored tokens to the SDK */
getTokens(): Promise<Tokens | null>
/** Store new or updated tokens when the SDK has successfully authenticated or refreshed tokens */
setTokens(tokens: Tokens): Promise<void>
/** Clear the tokens when the user logs out or the refresh token is invalid */
clearTokens(): Promise<void>
}
type Tokens = {
/** The workspace ID that these tokens are valid for (extracted from the access token) */
workspaceId: string
/** The access token for API requests */
accessToken: string
/** The refresh token for obtaining new access tokens (only present if scope includes 'offline_access') */
refreshToken?: string
}Example: VS Code Extension
const tokenStorage: TokenStorage = {
async getTokens() {
const workspaceId = await context.secrets.get('workspaceId')
const accessToken = await context.secrets.get('accessToken')
const refreshToken = await context.secrets.get('refreshToken')
if (!workspaceId || !accessToken) return null
return { workspaceId, accessToken, refreshToken: refreshToken || undefined }
},
async setTokens(tokens) {
await context.secrets.store('workspaceId', tokens.workspaceId)
await context.secrets.store('accessToken', tokens.accessToken)
if (tokens.refreshToken) {
await context.secrets.store('refreshToken', tokens.refreshToken)
}
},
async clearTokens() {
await context.secrets.delete('workspaceId')
await context.secrets.delete('accessToken')
await context.secrets.delete('refreshToken')
},
}Example: Node.js CLI
import { readFile, writeFile, unlink } from 'node:fs/promises'
import { homedir } from 'node:os'
import { join } from 'node:path'
const tokenPath = join(homedir(), '.prisma', 'credentials.json')
const tokenStorage: TokenStorage = {
async getTokens() {
try {
const data = await readFile(tokenPath, 'utf-8')
return JSON.parse(data)
} catch {
return null
}
},
async setTokens(tokens) {
await writeFile(tokenPath, JSON.stringify(tokens, null, 2))
},
async clearTokens() {
await unlink(tokenPath).catch(() => {})
},
}Example: Stateless Web Server
For stateless web servers (serverless, load-balanced), store the PKCE state in an encrypted cookie or database:
// In your login route
app.get('/login', async (req, res) => {
const { url, state, verifier } = await api.getLoginUrl({
scope: 'workspace:admin offline_access',
})
// Store in encrypted cookie or database keyed by state
res.cookie('oauth-verifier', verifier, { httpOnly: true, secure: true, signed: true })
res.cookie('oauth-state', state, { httpOnly: true, secure: true, signed: true })
res.redirect(url)
})
// In your callback route
app.get('/callback', async (req, res) => {
const verifier = req.signedCookies['oauth-verifier']
const expectedState = req.signedCookies['oauth-state']
// Clear cookies
res.clearCookie('oauth-verifier')
res.clearCookie('oauth-state')
await api.handleCallback({ callbackUrl: req.url, verifier, expectedState })
// Tokens are now stored in tokenStorage
// ... handle successful login
})Automatic Token Refresh
The SDK automatically handles token refresh when a refresh token is available (requires offline_access scope):
- When a request returns 401, the SDK refreshes the access token using the refresh token
- Concurrent requests during refresh are queued and resolved once refresh completes
- If refresh fails due to an invalid refresh token, tokens are cleared and
AuthErroris thrown withrefreshTokenInvalid: true - If no refresh token is available, an
AuthErroris thrown with the message "No refresh token available. Please log in again."
API Reference
createManagementApiClient(options)
Creates a raw API client without authentication handling. Useful if you want to manage authentication yourself or use a service token.
Parameters:
options.token?: string- Access token (automatically converted toAuthorization: Bearer ${token}header)options.baseUrl?: string- Base URL for API requests (defaults tohttps://api.prisma.io)options.headers?: Record<string, string>- Additional headers- Other
ClientOptionsfromopenapi-fetchare also supported
Returns: A typed API client for making requests.
createManagementApiSdk(config)
Creates a Management API SDK instance with OAuth authentication and automatic token refresh.
Parameters:
type ManagementApiClientConfig = {
// Required
clientId: string // OAuth client ID
redirectUri: string // OAuth redirect URI
tokenStorage: TokenStorage
// Optional (with defaults)
apiBaseUrl?: string // Default: 'https://api.prisma.io'
authBaseUrl?: string // Default: 'https://auth.prisma.io'
}Returns: An object with:
client- The typed API client for making requestsgetLoginUrl(options)- Generate OAuth login URL with specified scopehandleCallback(options)- Handle OAuth callback and store tokens viatokenStoragelogout()- Clear stored tokens
Error Handling
The SDK exports two error classes:
AuthError
Thrown for authentication-related errors:
- OAuth callback errors (includes
error_descriptionwhen available) - Invalid or missing tokens
- Token refresh failures
import { AuthError } from '@prisma/management-api-sdk'
try {
await api.handleCallback({ callbackUrl, verifier, expectedState })
} catch (error) {
if (error instanceof AuthError) {
if (error.refreshTokenInvalid) {
// Token is invalid/expired, user needs to log in again
const { url } = await api.getLoginUrl({ scope: 'workspace:admin offline_access' })
// redirect to url...
} else {
// Other auth errors (e.g., "access_denied: User cancelled")
console.error('Auth error:', error.message)
}
}
}FetchError
Thrown for network-related errors. Includes the original error as cause for debugging:
import { FetchError } from '@prisma/management-api-sdk'
try {
const { data } = await client.GET('/v1/workspaces')
} catch (error) {
if (error instanceof FetchError) {
console.error('Network error:', error.message)
console.error('Cause:', error.cause) // Original error for debugging
}
}TypeScript Types
The SDK exports all API types generated from the OpenAPI spec:
import type { paths, components } from '@prisma/management-api-sdk'
// Access response types
type Workspace = components['schemas']['Workspace']
type Project = components['schemas']['Project']Regenerating API Types
The API types are generated from the OpenAPI spec:
pnpm generate-api-clientThis fetches the latest spec from https://api.prisma.io/v1/doc and generates src/api.d.ts.