Projects

Projects group related work inside one workspace without making project assignment mandatory.

Projects are an optional organization layer inside a workspace. Jobs, files, workflows, workflow runs, Studio sessions, and AI conversations can belong to one project or remain unassigned.

Every resource still belongs to the API key workspace. A project never changes workspace permissions, billing, credits, or storage ownership.

Project routes

The Projects API supports project metadata, resource assignment, and deletion operations.

Use GET /api/v1/projects to list projects and PATCH /api/v1/projects/assignments to organize supported resources.

Project lists are cursor paginated. Use limit (1–100), then pass the returned next_cursor as starting_after while has_more is true. The optional q parameter searches names, descriptions, and project IDs.

MethodRoutePurpose
GET/api/v1/projectsList active projects
POST/api/v1/projectsCreate a project
GET/api/v1/projects/{projectId}Read project metadata and resource counts
PATCH/api/v1/projects/{projectId}Update a project name or description
DELETE/api/v1/projects/{projectId}Start a project deletion operation
PATCH/api/v1/projects/assignmentsMove resources to a project or leave them unassigned
GET/api/v1/project-deletions/{operationId}Read a deletion operation
POST/api/v1/project-deletions/{operationId}Retry a recoverable deletion operation

Read routes require projects:read. Write routes require projects:write and the matching workspace permission.

Create a project

Use POST /api/v1/projects with a name and optional description.

Bash
curl -s -X POST \
  -H "Authorization: Bearer $PROTEINIQ_API_KEY" \
  -H "Content-Type: application/json" \
  "https://proteiniq.io/api/v1/projects" \
  -d '{
    "name": "Kinase screening",
    "description": "Docking and follow-up analysis"
  }'

Names are trimmed, contain 1 to 80 characters, and are unique within a workspace without regard to case. Descriptions may contain up to 500 characters.

The response includes counts for every supported resource type:

JSON
{
  "id": "project_123",
  "object": "project",
  "name": "Kinase screening",
  "description": "Docking and follow-up analysis",
  "counts": {
    "jobs": 4,
    "files": 8,
    "workflows": 1,
    "workflow_runs": 3,
    "studio_sessions": 0,
    "ai_conversations": 2
  },
  "created_at": "2026-07-25T08:00:00.000Z",
  "updated_at": "2026-07-25T09:00:00.000Z"
}

Assign resources

Use PATCH /api/v1/projects/assignments to move jobs, files, workflows, workflow runs, Studio sessions, or AI conversations. Set target_project_id to null to leave the selected resources unassigned.

JSON
{
  "target_project_id": "project_123",
  "resources": [
    {
      "type": "job",
      "ids": ["job_123"]
    },
    {
      "type": "file",
      "ids": ["file_123"]
    }
  ],
  "move_linked_files": true
}

The request requires projects:write plus the write scope for every resource type:

  • Jobs, workflows, and workflow runs: jobs:write
  • Files: files:write
  • Studio sessions and AI conversations: no additional resource scope

move_linked_files applies when jobs are selected. When true, saved files linked to those jobs move to the same destination. Moving a file never moves its source job.

Each request can select at most 500 resources. Every selected resource and destination project must belong to the API key workspace.

Use projects with other resources

Job, file, workflow, and workflow-run resources include project_id. A null value means the resource is unassigned.

  • Create a job: Add optional project_id to POST /api/v1/jobs
  • Upload a file: Add optional project_id to the multipart form for POST /api/v1/files
  • Start a workflow run: Add optional project_id to POST /api/v1/workflows/{workflowId}/runs
  • Filter lists: Add project_id=<id> to job, file, or workflow list routes
  • Find unassigned resources: Add unassigned=true to those list routes

Do not combine project_id and unassigned=true in one list request.

Creating a resource with a non-null project_id requires projects:write in addition to that resource's normal write scope. Omitting project_id keeps direct jobs and uploads unassigned. A workflow run inherits its workflow project unless the request supplies an override; any explicit workflow-run project_id, including null, requires projects:write.

Delete a project

Project deletion requires owner or admin permission. Send one of three modes to DELETE /api/v1/projects/{projectId}:

  • move: Move direct project resources to target_project_id, then delete the project
  • unassign: Leave direct project resources in the workspace without a project
  • delete_contents: Delete the project and its contents using the existing resource deletion behavior
JSON
{
  "mode": "move",
  "target_project_id": "project_456"
}

Deletion is rejected while affected jobs or workflow runs are active. Collections remain workspace-wide. Deleting project files removes their collection links but does not delete the collections.

The endpoint returns a project_deletion resource. Read it through GET /api/v1/project-deletions/{operationId} when a client needs to confirm the final state. If a failed operation returns "retryable": true, retry its cleanup with POST /api/v1/project-deletions/{operationId}. Retrying requires projects:write and owner or admin permission.

JSON
{
  "id": "deletion_123",
  "object": "project_deletion",
  "project_id": "project_123",
  "project_name": "Kinase screening",
  "mode": "unassign",
  "target_project_id": null,
  "status": "completed",
  "error": null,
  "attempt_count": 1,
  "next_attempt_at": null,
  "retryable": false,
  "created_at": "2026-07-25T10:00:00.000Z",
  "started_at": "2026-07-25T10:00:00.000Z",
  "completed_at": "2026-07-25T10:00:01.000Z",
  "updated_at": "2026-07-25T10:00:01.000Z"
}