Projects
Manage your OpenPanel projects programmatically. Create, read, update, and delete projects using the Manage API.
Authentication
To authenticate with the Projects API, you need to use your clientId and clientSecret from a root client. Root clients have organization-wide access.
For detailed authentication information, see the Authentication guide.
Include the following headers with your requests:
openpanel-client-id: Your OpenPanel root client IDopenpanel-client-secret: Your OpenPanel root client secret
Base URL
All Projects API requests should be made to:
https://api.openpanel.dev/manage/projectsEndpoints
List Projects
Retrieve all projects in your organization.
GET /manage/projectsExample Request
curl 'https://api.openpanel.dev/manage/projects' \
-H 'openpanel-client-id: YOUR_ROOT_CLIENT_ID' \
-H 'openpanel-client-secret: YOUR_ROOT_CLIENT_SECRET'Response
{
"data": [
{
"id": "my-project",
"name": "My Project",
"organizationId": "org_123",
"domain": "https://example.com",
"cors": ["https://example.com", "https://www.example.com"],
"crossDomain": false,
"allowUnsafeRevenueTracking": false,
"filters": [],
"types": ["website"],
"eventsCount": 0,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"deleteAt": null
}
]
}Get Project
Retrieve a specific project by ID.
GET /manage/projects/{id}Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The ID of the project |
Example Request
curl 'https://api.openpanel.dev/manage/projects/my-project' \
-H 'openpanel-client-id: YOUR_ROOT_CLIENT_ID' \
-H 'openpanel-client-secret: YOUR_ROOT_CLIENT_SECRET'Response
{
"data": {
"id": "my-project",
"name": "My Project",
"organizationId": "org_123",
"domain": "https://example.com",
"cors": ["https://example.com"],
"crossDomain": false,
"allowUnsafeRevenueTracking": false,
"filters": [],
"types": ["website"],
"eventsCount": 0,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"deleteAt": null
}
}Create Project
Create a new project in your organization. A default write client is automatically created with the project.
POST /manage/projectsRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name (minimum 1 character) |
domain | string | null | No | Primary domain for the project (URL format or empty string) |
cors | string[] | No | Array of allowed CORS origins (default: []) |
crossDomain | boolean | No | Enable cross-domain tracking (default: false) |
types | string[] | No | Project types: website, app, backend (default: []) |
Project Types
website: Web-based projectapp: Mobile applicationbackend: Backend/server-side project
Example Request
curl -X POST 'https://api.openpanel.dev/manage/projects' \
-H 'openpanel-client-id: YOUR_ROOT_CLIENT_ID' \
-H 'openpanel-client-secret: YOUR_ROOT_CLIENT_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"name": "My New Project",
"domain": "https://example.com",
"cors": ["https://example.com", "https://www.example.com"],
"crossDomain": false,
"types": ["website"]
}'Response
{
"data": {
"id": "my-new-project",
"name": "My New Project",
"organizationId": "org_123",
"domain": "https://example.com",
"cors": ["https://example.com", "https://www.example.com"],
"crossDomain": false,
"allowUnsafeRevenueTracking": false,
"filters": [],
"types": ["website"],
"eventsCount": 0,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"deleteAt": null,
"client": {
"id": "fa0c2780-55f2-4d9e-bea0-da2e02c7b1a9",
"secret": "sec_6c8ae85a092d6c66b242"
}
}
}Important: The client.secret is only returned once when the project is created. Store it securely immediately.
Update Project
Update an existing project's configuration.
PATCH /manage/projects/{id}Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The ID of the project |
Request Body
All fields are optional. Only include fields you want to update.
| Parameter | Type | Description |
|---|---|---|
name | string | Project name (minimum 1 character) |
domain | string | null | Primary domain (URL format, empty string, or null) |
cors | string[] | Array of allowed CORS origins |
crossDomain | boolean | Enable cross-domain tracking |
allowUnsafeRevenueTracking | boolean | Allow revenue tracking without client secret |
Example Request
curl -X PATCH 'https://api.openpanel.dev/manage/projects/my-project' \
-H 'openpanel-client-id: YOUR_ROOT_CLIENT_ID' \
-H 'openpanel-client-secret: YOUR_ROOT_CLIENT_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"name": "Updated Project Name",
"crossDomain": true,
"allowUnsafeRevenueTracking": false
}'Response
{
"data": {
"id": "my-project",
"name": "Updated Project Name",
"organizationId": "org_123",
"domain": "https://example.com",
"cors": ["https://example.com"],
"crossDomain": true,
"allowUnsafeRevenueTracking": false,
"filters": [],
"types": ["website"],
"eventsCount": 0,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T11:00:00.000Z",
"deleteAt": null
}
}Delete Project
Soft delete a project. The project will be scheduled for deletion after 24 hours.
DELETE /manage/projects/{id}Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The ID of the project |
Example Request
curl -X DELETE 'https://api.openpanel.dev/manage/projects/my-project' \
-H 'openpanel-client-id: YOUR_ROOT_CLIENT_ID' \
-H 'openpanel-client-secret: YOUR_ROOT_CLIENT_SECRET'Response
{
"success": true
}Note: Projects are soft-deleted. The deleteAt field is set to 24 hours in the future. You can cancel deletion by updating the project before the deletion time.
Error Handling
The API uses standard HTTP response codes. Common error responses:
400 Bad Request
{
"error": "Bad Request",
"message": "Invalid request body",
"details": [
{
"path": ["name"],
"message": "String must contain at least 1 character(s)"
}
]
}401 Unauthorized
{
"error": "Unauthorized",
"message": "Manage: Only root clients are allowed to manage resources"
}404 Not Found
{
"error": "Not Found",
"message": "Project not found"
}429 Too Many Requests
Rate limiting response includes headers indicating your rate limit status.
Rate Limiting
The Projects API implements rate limiting:
- 20 requests per 10 seconds per client
- Rate limit headers included in responses
- Implement exponential backoff for retries
Notes
- Project IDs are automatically generated from the project name using a slug format
- If a project ID already exists, a numeric suffix is added
- CORS domains are automatically normalized (trailing slashes removed)
- The default client created with a project has
type: 'write' - Projects are scoped to your organization - you can only manage projects in your organization
- Soft-deleted projects are excluded from list endpoints