Skip to main content

Overview

The portfolio API assembles complete portfolio data from analyzed projects, including project details, skills, summaries, and resume items. It supports customization through representation preferences.

Generate Portfolio

Generate complete portfolio content for a portfolio ID.
POST /portfolio/generate
curl -X POST http://127.0.0.1:8000/portfolio/generate \
  -H "Content-Type: application/json" \
  -d '{
    "portfolio_id": "550e8400-e29b-41d4-a716-446655440000"
  }'
Request Body:
portfolio_id
string
required
Portfolio UUID returned by ZIP uploads (min 1 character)
Response:
{
  "success": true,
  "portfolio_id": "550e8400-e29b-41d4-a716-446655440000",
  "consent_level": "local",
  "generated_at": "2024-03-05T15:30:00",
  "preferences": {
    "showcase_project_ids": [1, 2, 3],
    "project_order": [3, 1, 2],
    "skills_to_highlight": [5, 12, 8],
    "hidden_skills": [],
    "chronology_overrides": [],
    "comparison_attributes": ["languages", "frameworks"],
    "custom_rankings": []
  },
  "projects": [
    {
      "id": 3,
      "project_name": "api-server",
      "project_path": "/path/to/api-server",
      "languages": ["Python"],
      "frameworks": ["FastAPI"],
      "first_commit": "2023-06-15T10:00:00",
      "last_commit": "2024-03-05T14:30:00",
      "ranking_score": 92.5,
      "health_score": 88.0,
      "thumbnail_url": "/uploads/thumbnails/abc123.png",
      "user_role": "Lead Developer",
      "evidence": [
        {
          "id": 1,
          "type": "metric",
          "content": "Reduced API response time by 40%",
          "source": "Performance testing",
          "date": "2024-02-15"
        }
      ]
    }
  ],
  "resume_items": [
    {
      "id": 1,
      "title": "Built REST API with FastAPI",
      "content": "Developed a scalable REST API...",
      "category": "Backend Development",
      "project_name": "api-server",
      "created_at": "2024-03-05T10:00:00"
    }
  ],
  "summaries": [
    {
      "id": 1,
      "repo_path": "/path/to/api-server",
      "user_email": "[email protected]",
      "summary_text": "Led development of a FastAPI backend...",
      "generated_at": "2024-03-05T12:00:00"
    }
  ],
  "skills_chronology": [
    {
      "date": "2023-06-15T10:00:00",
      "skill": "Python",
      "project": "api-server",
      "proficiency": 0.9,
      "category": "Programming Languages"
    }
  ],
  "errors": []
}
success
boolean
true when at least one project is included in the portfolio
portfolio_id
string
Portfolio UUID
Consent level used during analysis
generated_at
datetime
Timestamp when the portfolio was generated
preferences
object
Representation preferences applied to the portfolio
projects
array
Projects included in the portfolio
resume_items
array
Resume items from all portfolio projects
summaries
array
AI-generated summaries for projects
skills_chronology
array
Chronological skill progression
errors
array
Non-critical errors during generation (e.g., preference validation warnings)
Errors:
  • 422 - portfolio_id is empty
  • 404 - Portfolio not found
  • 400 - Portfolio has no analyzed ZIPs yet
Before generating a portfolio, you must upload ZIPs and run analysis with POST /analyze/{zip_id}.

Get Portfolio

Retrieve portfolio display data by ID.
GET /portfolio/{portfolio_id}
curl http://127.0.0.1:8000/portfolio/550e8400-e29b-41d4-a716-446655440000
Path Parameters:
portfolio_id
string
required
Portfolio UUID
Response: Same structure as POST /portfolio/generate response.

Edit Portfolio Preferences

Customize portfolio content through representation preferences.
POST /portfolio/{portfolio_id}/edit
curl -X POST http://127.0.0.1:8000/portfolio/550e8400-e29b-41d4-a716-446655440000/edit \
  -H "Content-Type: application/json" \
  -d '{
    "showcase_project_ids": [1, 3, 5],
    "project_order": [5, 1, 3],
    "skills_to_highlight": [2, 7, 12],
    "comparison_attributes": ["languages", "frameworks", "ranking_score"]
  }'
Path Parameters:
portfolio_id
string
required
Portfolio UUID
Request Body:
showcase_project_ids
array
default:"[]"
RepoStat IDs to showcase. If provided, filters portfolio to only these projects. Use integer repo_stat IDs
project_order
array
default:"[]"
Manual project ordering as a list of RepoStat IDs. Projects not in this list appear after ordered projects
skills_to_highlight
array
default:"[]"
Skill IDs to highlight in portfolio output
hidden_skills
array
default:"[]"
Skill IDs to hide from portfolio output
chronology_overrides
array
default:"[]"
Manual overrides for project chronology. Use date-only values (YYYY-MM-DD). Partial overrides allowedExample: [{"project_id": 1, "first_commit": "2023-01-15", "last_commit": "2024-03-01"}]
comparison_attributes
array
default:"[]"
Allowed attributes for project comparison. Valid values: languages, frameworks, skills, total_commits, ranking_score, health_score, primary_language, role
custom_rankings
array
default:"[]"
Manual custom rankings for projects. Each item has project_id and rank (≥1)Example: [{"project_id": 3, "rank": 1}, {"project_id": 1, "rank": 2}]
Response:
{
  "success": true,
  "portfolio_id": "550e8400-e29b-41d4-a716-446655440000",
  "updated_at": "2024-03-05T16:00:00",
  "preferences": {
    "showcase_project_ids": [1, 3, 5],
    "project_order": [5, 1, 3],
    "skills_to_highlight": [2, 7, 12],
    "hidden_skills": [],
    "chronology_overrides": [],
    "comparison_attributes": ["languages", "frameworks", "ranking_score"],
    "custom_rankings": []
  }
}

Get Portfolio Preferences

Retrieve current representation preferences.
GET /views/{portfolio_id}/prefs
curl http://127.0.0.1:8000/views/550e8400-e29b-41d4-a716-446655440000/prefs
Response:
{
  "showcase_project_ids": [1, 3, 5],
  "project_order": [5, 1, 3],
  "skills_to_highlight": [2, 7, 12],
  "hidden_skills": [],
  "chronology_overrides": [],
  "comparison_attributes": ["languages", "frameworks"],
  "custom_rankings": []
}
If no preferences have been set, returns defaults (all empty arrays).

Update Portfolio Preferences

Update representation preferences (alternative to POST /portfolio//edit).
PUT /views/{portfolio_id}/prefs
curl -X PUT http://127.0.0.1:8000/views/550e8400-e29b-41d4-a716-446655440000/prefs \
  -H "Content-Type: application/json" \
  -d '{
    "showcase_project_ids": [2, 4],
    "project_order": [4, 2]
  }'
Response: Same as GET /views//prefs response.

Example: Complete Portfolio Workflow

import requests

BASE_URL = 'http://127.0.0.1:8000'

# Step 1: Upload and analyze
with open('projects.zip', 'rb') as f:
    upload = requests.post(f'{BASE_URL}/zip/upload', files={'file': f}).json()
    portfolio_id = upload['portfolio_id']
    zip_id = upload['zip_id']

analysis = requests.post(f'{BASE_URL}/analyze/{zip_id}').json()
print(f"Analyzed {analysis['repos_found']} repositories")

# Step 2: Generate initial portfolio
portfolio = requests.post(
    f'{BASE_URL}/portfolio/generate',
    json={'portfolio_id': portfolio_id}
).json()

print(f"Portfolio has {len(portfolio['projects'])} projects")

# Step 3: Get project IDs for customization
project_ids = [p['id'] for p in portfolio['projects']]
top_3 = project_ids[:3]

# Step 4: Customize portfolio
prefs = requests.post(
    f'{BASE_URL}/portfolio/{portfolio_id}/edit',
    json={
        'showcase_project_ids': top_3,
        'project_order': top_3,
        'comparison_attributes': ['languages', 'frameworks', 'ranking_score']
    }
).json()

print(f"Updated preferences for {len(prefs['preferences']['showcase_project_ids'])} projects")

# Step 5: Regenerate with preferences
final = requests.post(
    f'{BASE_URL}/portfolio/generate',
    json={'portfolio_id': portfolio_id}
).json()

print(f"Final portfolio: {len(final['projects'])} projects, {len(final['resume_items'])} resume items")

Build docs developers (and LLMs) love