---
title: "Create Project"
description: "API endpoint for creating new TraceRTM projects"
---

# Create Project

Create a new project with specified settings and configuration.

## Endpoint

```http
POST /v1/projects
```

## Authentication

Requires a valid API key or access token with `write:projects` scope.

## Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Project name (3-100 characters) |
| `key` | string | Yes | Unique project key (2-10 uppercase alphanumeric) |
| `description` | string | No | Project description (max 2000 characters) |
| `visibility` | string | No | Access level: `private`, `public`, `organization` |
| `settings` | object | No | Project configuration |
| `template_id` | string | No | Clone from existing project as template |
| `custom_fields` | array | No | Custom field definitions |
| `metadata` | object | No | Additional metadata |

### Settings Object

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `default_workflow_id` | string | `wf_standard` | Default workflow for new items |
| `require_approval` | boolean | false | Require approval for item changes |
| `enable_versioning` | boolean | true | Enable item version history |
| `enable_comments` | boolean | true | Enable item comments |
| `auto_link_detection` | boolean | false | AI-powered link suggestions |
| `default_item_type` | string | `requirement` | Default type for new items |

### Custom Field Definition

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Field name (snake_case) |
| `label` | string | No | Display label |
| `type` | string | Yes | `string`, `number`, `select`, `multi_select`, `date`, `boolean` |
| `required` | boolean | No | Whether field is required |
| `options` | array | No | Options for select/multi_select fields |
| `default` | any | No | Default value |

## Request Examples

### Minimal Request

```bash
curl -X POST "https://api.tracertm.dev/v1/projects" \
  -H "Authorization: Bearer $TRACERTM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "New Project",
    "key": "NEW"
  }'
```

### Full Request

```bash
curl -X POST "https://api.tracertm.dev/v1/projects" \
  -H "Authorization: Bearer $TRACERTM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mobile App Requirements",
    "key": "MOB",
    "description": "Requirements and test cases for iOS and Android mobile applications",
    "visibility": "organization",
    "settings": {
      "default_workflow_id": "wf_standard",
      "require_approval": true,
      "enable_versioning": true,
      "enable_comments": true,
      "auto_link_detection": true,
      "default_item_type": "requirement"
    },
    "custom_fields": [
      {
        "name": "platform",
        "label": "Target Platform",
        "type": "multi_select",
        "options": ["ios", "android", "web"],
        "required": true
      },
      {
        "name": "priority",
        "label": "Priority Level",
        "type": "select",
        "options": ["critical", "high", "medium", "low"],
        "default": "medium"
      },
      {
        "name": "story_points",
        "label": "Story Points",
        "type": "number"
      },
      {
        "name": "target_release",
        "label": "Target Release",
        "type": "date"
      }
    ],
    "metadata": {
      "department": "engineering",
      "cost_center": "CC-1234"
    }
  }'
```

### From Template

```bash
curl -X POST "https://api.tracertm.dev/v1/projects" \
  -H "Authorization: Bearer $TRACERTM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q2 Release Requirements",
    "key": "Q2R",
    "template_id": "proj_template_standard",
    "description": "Cloned from standard template"
  }'
```

## Response

### Success Response (201 Created)

```json
{
  "data": {
    "id": "proj_ghi789rst",
    "name": "Mobile App Requirements",
    "key": "MOB",
    "description": "Requirements and test cases for iOS and Android mobile applications",
    "status": "active",
    "visibility": "organization",
    "owner_id": "user_xyz789",
    "organization_id": "org_456",
    "settings": {
      "default_workflow_id": "wf_standard",
      "require_approval": true,
      "enable_versioning": true,
      "enable_comments": true,
      "auto_link_detection": true,
      "default_item_type": "requirement"
    },
    "custom_fields": [
      {
        "name": "platform",
        "label": "Target Platform",
        "type": "multi_select",
        "options": ["ios", "android", "web"],
        "required": true
      },
      {
        "name": "priority",
        "label": "Priority Level",
        "type": "select",
        "options": ["critical", "high", "medium", "low"],
        "default": "medium"
      },
      {
        "name": "story_points",
        "label": "Story Points",
        "type": "number",
        "required": false
      },
      {
        "name": "target_release",
        "label": "Target Release",
        "type": "date",
        "required": false
      }
    ],
    "metadata": {
      "department": "engineering",
      "cost_center": "CC-1234"
    },
    "item_counts": {
      "total": 0,
      "by_type": {},
      "by_status": {}
    },
    "member_count": 1,
    "link_count": 0,
    "created_at": "2025-01-15T15:00:00Z",
    "updated_at": "2025-01-15T15:00:00Z",
    "created_by": "user_xyz789"
  },
  "meta": {
    "request_id": "req_abc123"
  }
}
```

### Template Clone Response

```json
{
  "data": {
    "id": "proj_new456",
    "name": "Q2 Release Requirements",
    "key": "Q2R",
    "cloned_from": {
      "project_id": "proj_template_standard",
      "project_name": "Standard Template"
    },
    "item_counts": {
      "total": 25
    },
    "created_at": "2025-01-15T15:00:00Z"
  },
  "meta": {
    "items_cloned": 25,
    "links_cloned": 12,
    "workflows_cloned": 2
  }
}
```

## SDK Examples

### Python

```python
from tracertm import TraceRTMClient
from tracertm.models import CustomFieldType

client = TraceRTMClient(api_key="rtm_live_...")

# Minimal creation
project = await client.projects.create(
    name="New Project",
    key="NEW"
)
print(f"Created: {project.id}")

# Full creation with custom fields
project = await client.projects.create(
    name="Mobile App Requirements",
    key="MOB",
    description="iOS and Android requirements",
    visibility="organization",
    settings={
        "require_approval": True,
        "enable_versioning": True,
        "auto_link_detection": True
    },
    custom_fields=[
        {
            "name": "platform",
            "label": "Target Platform",
            "type": CustomFieldType.MULTI_SELECT,
            "options": ["ios", "android", "web"],
            "required": True
        },
        {
            "name": "priority",
            "type": CustomFieldType.SELECT,
            "options": ["critical", "high", "medium", "low"],
            "default": "medium"
        },
        {
            "name": "story_points",
            "type": CustomFieldType.NUMBER
        }
    ],
    metadata={
        "department": "engineering"
    }
)

# From template
project = await client.projects.create_from_template(
    template_id="proj_template_standard",
    name="Q2 Release",
    key="Q2R"
)

# With context manager for rollback on error
async with client.projects.create_context(
    name="Critical Project",
    key="CRT"
) as project:
    # If any operation fails, project is automatically deleted
    await client.items.create(
        project_id=project.id,
        title="First Requirement",
        type="requirement"
    )
```

### TypeScript

```typescript
import { TraceRTMClient, CustomFieldType, Visibility } from '@tracertm/sdk'

const client = new TraceRTMClient({ apiKey: 'rtm_live_...' })

// Minimal creation
const simpleProject = await client.projects.create({
  name: 'New Project',
  key: 'NEW'
})

// Full creation
const project = await client.projects.create({
  name: 'Mobile App Requirements',
  key: 'MOB',
  description: 'iOS and Android requirements',
  visibility: Visibility.Organization,
  settings: {
    requireApproval: true,
    enableVersioning: true,
    autoLinkDetection: true
  },
  customFields: [
    {
      name: 'platform',
      label: 'Target Platform',
      type: CustomFieldType.MultiSelect,
      options: ['ios', 'android', 'web'],
      required: true
    },
    {
      name: 'priority',
      type: CustomFieldType.Select,
      options: ['critical', 'high', 'medium', 'low'],
      default: 'medium'
    }
  ],
  metadata: {
    department: 'engineering'
  }
})

console.log(`Created project: ${project.id}`)

// From template
const templateProject = await client.projects.createFromTemplate({
  templateId: 'proj_template_standard',
  name: 'Q2 Release',
  key: 'Q2R'
})
```

### Go

```go
package main

import (
    "context"
    "fmt"
    "github.com/tracertm/tracertm-go"
)

func main() {
    client := tracertm.NewClient("rtm_live_...")
    ctx := context.Background()

    // Create project
    project, err := client.Projects.Create(ctx, &tracertm.CreateProjectInput{
        Name:        "Mobile App Requirements",
        Key:         "MOB",
        Description: "iOS and Android requirements",
        Visibility:  tracertm.VisibilityOrganization,
        Settings: &tracertm.ProjectSettings{
            RequireApproval:    true,
            EnableVersioning:   true,
            AutoLinkDetection:  true,
        },
        CustomFields: []tracertm.CustomField{
            {
                Name:     "platform",
                Type:     tracertm.FieldTypeMultiSelect,
                Options:  []string{"ios", "android", "web"},
                Required: true,
            },
        },
    })

    if err != nil {
        panic(err)
    }

    fmt.Printf("Created: %s\n", project.ID)
}
```

## Error Responses

### Validation Error (422)

```json
{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed",
    "details": [
      {
        "field": "name",
        "code": "too_short",
        "message": "Name must be at least 3 characters"
      },
      {
        "field": "key",
        "code": "invalid_format",
        "message": "Key must be 2-10 uppercase alphanumeric characters"
      }
    ]
  }
}
```

### Key Conflict (409)

```json
{
  "error": {
    "code": "conflict",
    "message": "Project key already exists",
    "details": {
      "key": "MOB",
      "existing_project_id": "proj_abc123",
      "suggestion": "Try MOB2 or MOBI"
    }
  }
}
```

### Quota Exceeded (402)

```json
{
  "error": {
    "code": "quota_exceeded",
    "message": "Project limit reached for your plan",
    "details": {
      "current_count": 10,
      "limit": 10,
      "plan": "pro",
      "upgrade_url": "https://app.tracertm.dev/billing/upgrade"
    }
  }
}
```

### Invalid Template (400)

```json
{
  "error": {
    "code": "invalid_template",
    "message": "Template project not found or not accessible",
    "details": {
      "template_id": "proj_invalid"
    }
  }
}
```

## Validation Rules

### Project Name

- Minimum: 3 characters
- Maximum: 100 characters
- Allowed: Letters, numbers, spaces, hyphens, underscores

### Project Key

- Minimum: 2 characters
- Maximum: 10 characters
- Allowed: Uppercase letters and numbers only
- Must be unique within organization
- Cannot be changed after creation

### Custom Field Names

- Format: snake_case
- Allowed: lowercase letters, numbers, underscores
- Must start with a letter
- Maximum: 50 characters

## Best Practices

### Use Descriptive Keys

```python
# Good - descriptive and recognizable
await client.projects.create(name="Frontend Requirements", key="FRONT")
await client.projects.create(name="API Tests", key="APIT")

# Avoid - unclear abbreviations
await client.projects.create(name="Frontend Requirements", key="FE1")
```

### Define Custom Fields Upfront

```python
# Define all custom fields at creation to ensure consistency
project = await client.projects.create(
    name="Sprint Planning",
    key="SPR",
    custom_fields=[
        {"name": "story_points", "type": "number"},
        {"name": "sprint", "type": "select", "options": ["1", "2", "3", "4"]},
        {"name": "assignee", "type": "string"}
    ]
)
```

### Use Templates for Consistency

```python
# Create template once
template = await client.projects.create(
    name="Standard Project Template",
    key="TPL",
    settings=standard_settings,
    custom_fields=standard_fields
)

# Reuse for new projects
new_project = await client.projects.create(
    name="New Feature",
    key="NFT",
    template_id=template.id
)
```

## Related Documentation

- [Projects API](/docs/api-reference/rest-api/projects) - All project endpoints
- [List Projects](/docs/api-reference/rest-api/projects-list) - Listing projects
- [Custom Fields](/docs/wiki/concepts/custom-fields) - Field types and usage
- [Workflows](/docs/api-reference/rest-api/workflows) - Status workflows

