This commit is contained in:
2026-09-03 17:56:47 +03:00
commit 33490da091
136 changed files with 20062 additions and 0 deletions
@@ -0,0 +1,102 @@
# api-basics
Core conventions for the Prisma Management API. All three `prisma-postgres-*` skills share these patterns.
## Base URL
```
https://api.prisma.io/v1
```
API documentation: https://api.prisma.io/v1/doc
## Response Envelope
### Single resource
```json
{
"data": {
"id": "proj_clx7abc123def456",
"type": "project",
"name": "My Project",
"createdAt": "2025-06-15T10:30:00.000Z"
}
}
```
### Collection
```json
{
"data": [
{ "id": "proj_aaa", "type": "project", "name": "Alpha" },
{ "id": "proj_bbb", "type": "project", "name": "Beta" }
],
"pagination": {
"hasMore": true,
"nextCursor": "clx7cursor123"
}
}
```
## Resource ID Prefixes
Every resource ID carries a type prefix:
| Prefix | Resource |
|---|---|
| `proj_` | Project |
| `db_` | Database |
| `con_` | Connection |
| `wksp_` | Workspace |
Always include the prefix when sending IDs in API requests.
## Pagination
Collection endpoints use cursor-based pagination:
```
GET /v1/projects?limit=10
GET /v1/projects?cursor=clx7abc123&limit=10
```
| Parameter | Type | Default | Description |
|---|---|---|---|
| `cursor` | string | — | Opaque cursor from `nextCursor` |
| `limit` | number | 100 | Maximum items per page |
Continue fetching while `pagination.hasMore` is `true`, using `pagination.nextCursor` as the `cursor` parameter.
## Error Responses
All errors follow this shape:
```json
{
"error": {
"code": "resource-not-found",
"message": "database with id db_abc not found"
}
}
```
### Error codes by HTTP status
| HTTP Status | Error Code | Meaning |
|---|---|---|
| 400 | `client-error` | Malformed request |
| 401 | `authentication-failed` | Missing or invalid token |
| 403 | `permission-denied` | Token lacks required access |
| 404 | `resource-not-found` | Resource does not exist or is not accessible |
| 422 | `validation-error` | Request body failed validation |
| 429 | `rate-limit-exceeded` | Too many requests |
| 500 | `internal-server-error` | Server error — retry after a delay |
### Self-correction patterns
- **401**: Token is invalid or expired. Create a new service token in Console → Workspace Settings → Service Tokens.
- **404**: Verify the resource ID includes the correct prefix (`proj_`, `db_`, `con_`). Use `GET /v1/projects` or `GET /v1/databases` to list available resources.
- **422**: Check the request body against the endpoint schema. Common issues: missing required fields, invalid region ID, empty `name`.
- **429**: Wait 25 seconds and retry. If repeated, increase the backoff interval.
@@ -0,0 +1,46 @@
# auth
How to authenticate with the Prisma Management API using service tokens.
## Service Tokens
Service tokens authenticate server-to-server requests. They are scoped to a workspace and grant access to all resources within it.
### Creating a service token
1. Open https://console.prisma.io
2. Navigate to **Workspace Settings****Service Tokens**
3. Click **Create Token**
4. Copy the token immediately — it is only shown once
### Using a service token
Set the token as an environment variable:
```bash
export PRISMA_SERVICE_TOKEN="eyJ..."
```
Include it in the `Authorization` header of every API request:
```bash
curl -H "Authorization: Bearer $PRISMA_SERVICE_TOKEN" \
https://api.prisma.io/v1/projects
```
### Token scope
Service tokens are workspace-scoped. A single token grants access to all projects, databases, and connections within the workspace. There are no project-scoped tokens at this time.
### Security practices
- Store tokens in environment variables or secret managers, never in source code
- Add `.env` to `.gitignore` to prevent accidental commits
- Rotate tokens periodically via Console → Workspace Settings → Service Tokens
- In CI/CD, store tokens as encrypted secrets (e.g., GitHub Secrets)
## OAuth 2.0 (for user-scoped access)
OAuth is used when acting on behalf of a user, typically in partner/integrator flows. See the `prisma-postgres-integrator` skill for OAuth details.
For standard database setup, service tokens are the recommended authentication method.
@@ -0,0 +1,223 @@
# endpoints
Management API endpoint details for database setup workflows.
## List regions
```
GET /v1/regions/postgres
```
No request body. Returns available Prisma Postgres regions.
**Response:**
```json
{
"data": [
{
"id": "us-east-1",
"type": "region",
"name": "US East (N. Virginia)",
"status": "available"
},
{
"id": "eu-west-1",
"type": "region",
"name": "EU West (Ireland)",
"status": "available"
}
]
}
```
Only use regions where `status` is `available`.
## Create project (with database)
```
POST /v1/projects
```
**Request body:**
```json
{
"name": "my-project",
"region": "us-east-1",
"createDatabase": true
}
```
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `name` | string | No | Auto-generated | Project display name |
| `region` | string | No | `us-east-1` | Region for the database |
| `createDatabase` | boolean | No | `true` | Create a default database with the project |
**Response** (with `createDatabase: true`):
```json
{
"data": {
"id": "proj_clx7abc123",
"type": "project",
"url": "https://api.prisma.io/v1/projects/proj_clx7abc123",
"name": "my-project",
"createdAt": "2025-06-15T10:30:00.000Z",
"defaultRegion": "us-east-1",
"workspace": {
"id": "wksp_xyz789",
"url": "https://api.prisma.io/v1/workspaces/wksp_xyz789",
"name": "My Workspace"
},
"database": {
"id": "db_def456",
"type": "database",
"url": "https://api.prisma.io/v1/databases/db_def456",
"name": "my-project",
"status": "ready",
"createdAt": "2025-06-15T10:30:00.000Z",
"isDefault": true,
"defaultConnectionId": "con_ghi789",
"connections": [
{
"id": "con_ghi789",
"type": "connection",
"url": "https://api.prisma.io/v1/connections/con_ghi789",
"name": "Default",
"createdAt": "2025-06-15T10:30:00.000Z",
"kind": "postgres",
"endpoints": {
"direct": {
"host": "db.prisma.io",
"port": 5432,
"connectionString": "postgres://user:pass@db.prisma.io:5432/postgres?sslmode=require"
}
}
}
],
"region": {
"id": "us-east-1",
"name": "US East (N. Virginia)"
}
}
}
}
```
Key field to extract:
- `data.database.connections[0].endpoints.direct.connectionString` → use as `DATABASE_URL`
The response also includes `pooled` and `accelerate` endpoints — ignore these for new projects. The direct connection string is all you need.
If `data.database.status` is `provisioning`, poll `GET /v1/databases/{id}` until `status` is `ready`.
## Get database
```
GET /v1/databases/{databaseId}
```
Use to check database status after creation or to retrieve database details.
**Response:**
```json
{
"data": {
"id": "db_def456",
"type": "database",
"url": "https://api.prisma.io/v1/databases/db_def456",
"name": "my-project",
"status": "ready",
"createdAt": "2025-06-15T10:30:00.000Z",
"isDefault": true,
"defaultConnectionId": "con_ghi789",
"connections": [],
"project": {
"id": "proj_clx7abc123",
"url": "https://api.prisma.io/v1/projects/proj_clx7abc123",
"name": "my-project"
},
"region": {
"id": "us-east-1",
"name": "US East (N. Virginia)"
}
}
}
```
## Create connection
```
POST /v1/databases/{databaseId}/connections
```
Creates a new named connection string for a database. Use for per-developer or per-environment connections.
**Request body:**
```json
{
"name": "dev"
}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | Yes | Display name for the connection |
**Response:**
```json
{
"data": {
"id": "con_newcon123",
"type": "connection",
"url": "https://api.prisma.io/v1/connections/con_newcon123",
"name": "dev",
"createdAt": "2025-06-15T10:31:00.000Z",
"kind": "postgres",
"endpoints": {
"direct": {
"host": "db.prisma.io",
"port": 5432,
"connectionString": "postgres://user:pass@db.prisma.io:5432/postgres?sslmode=require"
}
},
"database": {
"id": "db_def456",
"url": "https://api.prisma.io/v1/databases/db_def456",
"name": "my-project"
}
}
}
```
Extract: `data.endpoints.direct.connectionString` → use as `DATABASE_URL`.
## Delete database
```
DELETE /v1/databases/{databaseId}
```
Permanently deletes a database and all its connections. Returns `204 No Content` on success.
## List projects
```
GET /v1/projects
```
Returns all projects in the workspace. Supports cursor-based pagination (`?cursor=...&limit=...`).
## Delete project
```
DELETE /v1/projects/{projectId}
```
Permanently deletes a project and all its databases. Returns `204 No Content` on success.
@@ -0,0 +1,82 @@
# Prisma 7 Client Instantiation
Prisma 7 changed how PrismaClient connects to databases. The CLI (`prisma db push`, `prisma migrate`) reads the URL from `prisma.config.ts`. But at **runtime**, you must provide a driver adapter to PrismaClient explicitly.
## Required packages
```bash
npm install @prisma/client @prisma/adapter-pg pg
```
- `@prisma/adapter-pg` — the Prisma adapter for the `pg` PostgreSQL driver
- `pg` — the underlying Node.js PostgreSQL driver
## Basic instantiation
```typescript
import 'dotenv/config'
import pg from 'pg'
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from './generated/prisma/client.js'
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })
```
## Key rules
1. **Import path**: Always `./generated/prisma/client.js` — not `./generated/prisma` and not `@prisma/client`.
2. **Adapter is mandatory**: `new PrismaClient()` with no arguments throws. `new PrismaClient({ datasourceUrl: '...' })` also throws — `datasourceUrl` does not exist in Prisma 7.
3. **ESM required**: The generated client uses ESM. Ensure `package.json` has `"type": "module"`.
4. **Pool lifecycle**: Call `await pool.end()` when shutting down (after `prisma.$disconnect()`).
## Usage in application code
```typescript
import 'dotenv/config'
import pg from 'pg'
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from './generated/prisma/client.js'
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })
// Create
const user = await prisma.user.create({
data: { email: 'alice@example.com', name: 'Alice' },
})
// Read with relations
const posts = await prisma.post.findMany({
where: { published: true },
include: { author: true },
})
// Update
await prisma.post.update({
where: { id: 1 },
data: { published: true },
})
// Delete
await prisma.post.delete({ where: { id: 1 } })
// Cleanup
await prisma.$disconnect()
await pool.end()
```
## Common mistakes
| Mistake | Error | Fix |
|---|---|---|
| `import { PrismaClient } from './generated/prisma'` | `Cannot find module` | Use `./generated/prisma/client.js` |
| `new PrismaClient()` | `PrismaClient needs non-empty options` | Pass `{ adapter }` |
| `new PrismaClient({ datasourceUrl: url })` | `Unknown property datasourceUrl` | Use adapter pattern instead |
| Missing `"type": "module"` in package.json | ESM import errors | Add `"type": "module"` |
| `import { PrismaClient } from '@prisma/client'` | Wrong export | Use `./generated/prisma/client.js` |