Skip to main content

Projects API

REST endpoints for managing projects and workspace configuration. A workspace contains multiple projects, each with isolated data and optional configuration overrides.

Endpoints

MethodEndpointDescription
GET/api/projectsList all projects
POST/api/projectsCreate a new project
GET/api/workspaceGet workspace configuration
PUT/api/workspaceUpdate workspace defaults
GET/api/projects/:projectId/configGet effective project config
PUT/api/projects/:projectId/configUpdate project config
DELETE/api/projects/:projectIdDelete a project

All entity endpoints (personas, scenarios, evals, runs, connectors) are scoped under /api/projects/:projectId/. See individual entity docs for details.


GET /api/projects

List all projects in the workspace.

Response (200 OK)

[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-product-evals"
},
{
"id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321",
"name": "staging-tests"
}
]

Example

curl http://localhost:3000/api/projects

POST /api/projects

Create a new project in the workspace.

Request Body

FieldTypeRequiredDescription
namestringYesProject name
{
"name": "my-product-evals"
}

Response (201 Created)

{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-product-evals"
}

Example

curl -X POST http://localhost:3000/api/projects \
-H "Content-Type: application/json" \
-d '{"name": "my-product-evals"}'

GET /api/workspace

Get the workspace-level configuration (defaults inherited by all projects).

note

API keys are redacted in all config responses. The apiKey field contains a masked value (e.g., "sk-1...cdef") instead of the actual key.

Response (200 OK)

{
"version": 3,
"name": "~/evalstudio",
"projects": [
{ "id": "a1b2c3d4-...", "name": "my-product-evals" }
],
"llmSettings": {
"provider": "openai",
"apiKey": "sk-1...cdef",
"models": { "evaluation": "gpt-4o" }
},
"maxConcurrency": 5
}

PUT /api/workspace

Update workspace-level defaults. These are inherited by projects that don't override them.

Request Body

FieldTypeRequiredDescription
namestringNoWorkspace name
llmSettingsobject | nullNoDefault LLM config (null to remove)
maxConcurrencynumber | nullNoDefault max concurrent runs (null to clear)

When updating llmSettings, the apiKey field is optional. Omit it to keep the existing stored key — only provide it when setting a new key.

Response (200 OK)

Returns the updated workspace config (with redacted API key).


GET /api/projects/:projectId/config

Get the effective configuration for a specific project (workspace defaults merged with project overrides).

Response (200 OK)

{
"version": 3,
"name": "my-product-evals",
"llmSettings": {
"provider": "openai",
"apiKey": "sk-1...cdef",
"models": { "evaluation": "gpt-4o" }
},
"maxConcurrency": 5
}

Example

curl http://localhost:3000/api/projects/a1b2c3d4/config

PUT /api/projects/:projectId/config

Update project-specific configuration. Fields set to null are cleared (inheriting workspace defaults).

Request Body

FieldTypeRequiredDescription
namestringNoProject name
llmSettingsobject | nullNoLLM config (null to inherit from workspace)
maxConcurrencynumber | nullNoMax concurrent runs (null to inherit)

When updating llmSettings, the apiKey field is optional. Omit it to keep the existing stored key — only provide it when setting a new key.

Response (200 OK)

Returns the effective (merged) config after update (with redacted API key).


DELETE /api/projects/:projectId

Delete a project and all its data.

Response (204 No Content)

Empty response on success.

Example

curl -X DELETE http://localhost:3000/api/projects/a1b2c3d4

Project Images

Generic blob store for project images (persona portraits, style references, etc.).

MethodEndpointDescription
GET/api/projects/:projectId/imagesList images by role
POST/api/projects/:projectId/imagesUpload an image
GET/api/projects/:projectId/images/:idServe an image
DELETE/api/projects/:projectId/images/:idDelete an image

GET /api/projects/:projectId/images

List image IDs filtered by role.

Query Parameters:

FieldTypeRequiredDescription
rolestringYesImage role to filter by (e.g., persona-avatar-styleguide)

Response (200 OK):

{ "ids": ["img1.png", "img2.png"] }

POST /api/projects/:projectId/images

Upload an image. Returns a generated image ID.

Request Body:

FieldTypeRequiredDescription
imageBase64stringYesBase64-encoded image data
rolestringYesImage role (e.g., persona-avatar, persona-avatar-styleguide, upload)
filenamestringNoOriginal filename (for mime type detection)

Response (201 Created):

{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890.png" }

GET /api/projects/:projectId/images/:id

Serve an image with appropriate Content-Type header and caching.

DELETE /api/projects/:projectId/images/:id

Delete an image. Returns 204 on success, 404 if not found.


Project-Scoped Entity Routes

All entity endpoints are nested under a project:

/api/projects/:projectId/images
/api/projects/:projectId/personas
/api/projects/:projectId/scenarios
/api/projects/:projectId/evals
/api/projects/:projectId/runs
/api/projects/:projectId/connectors

The project ID can be the full UUID or a unique prefix (first 8+ characters).