REST API for building iOS and web integrations with your proposal workspace.
All protected endpoints accept Authorization: Bearer <API_KEY>. Internal app pages also use a secure HttpOnly session cookie, so browser requests do not need to expose the raw key. Manage API_KEY in your Vercel project settings.
Authorization: Bearer your-api-key
Health check — confirms the service is running.
{ "ok": true, "service": "foundry-by-gitwork", "version": "0.1.0", "timestamp": "2026-03-31T00:00:00.000Z" }List all proposals.
{ "proposals": [{ "id": "...", "title": "...", "status": "DRAFT", "clientName": "...", "updatedAt": "..." }] }List manual and suggested clients in the Docs workspace.
{ "clients": [{ "id": "client_acme-health", "name": "Acme Health", "slug": "acme-health", "proposalCount": 3, "source": "SUGGESTED" }, { "id": "clx...", "name": "Gitwork", "slug": "gitwork", "proposalCount": 0, "source": "MANUAL" }] }Create a manual client record.
| Field | Type | Description |
|---|---|---|
| name | string | Client name |
| logoUrl | string | Optional logo URL |
{ "client": { "id": "clx...", "name": "Gitwork", "slug": "gitwork", "proposalCount": 0, "source": "MANUAL" } }Get a client with linked proposals and proof documents.
| Name | Type | Description |
|---|---|---|
| slug | string | Client slug |
{ "client": { "id": "...", "name": "...", "slug": "...", "proposalCount": 3, "source": "SUGGESTED" }, "proposals": [{ "id": "...", "title": "...", "status": "DRAFT" }], "proofDocuments": [] }Update a client record or promote a suggested client into a saved manual record.
| Name | Type | Description |
|---|---|---|
| slug | string | Client slug |
| Field | Type | Description |
|---|---|---|
| name | string | Updated client name |
| logoUrl | string | Optional logo URL |
{ "client": { "id": "...", "name": "...", "slug": "...", "proposalCount": 3, "source": "MANUAL" } }Create a new proposal.
| Field | Type | Description |
|---|---|---|
| title | string | Proposal title |
| clientName | string | Suggested client name to attach to the proposal |
| productName | string | Product or project name shown throughout the proposal |
| templateId | string | ID of a template to apply |
{ "proposal": { "id": "...", "title": "...", "status": "DRAFT", ... } }Get a single proposal with all sections.
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
{ "proposal": { "id": "...", "title": "...", "status": "DRAFT", "cover": {...}, "engagement": {...}, "timeline": [...], "costing": {...} } }Update top-level proposal fields.
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
| Field | Type | Description |
|---|---|---|
| title | string | New title |
| status | DocumentStatus | DRAFT | PRODUCT_SIGN_OFF | TECH_SIGN_OFF | IN_REVIEW | APPROVED | SENT | ARCHIVED |
{ "proposal": { "id": "...", "title": "...", "status": "...", ... } }Duplicate a proposal (copies all sections as a new DRAFT).
| Name | Type | Description |
|---|---|---|
| id | string | Source proposal CUID |
{ "proposal": { "id": "...", "title": "Copy of ...", "status": "DRAFT", ... } }Archive a proposal (sets status to ARCHIVED).
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
{ "proposal": { "id": "...", "status": "ARCHIVED" } }Permanently delete a proposal.
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
{ "ok": true }Update the engagement section (scope, deliverables, objectives).
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
| Field | Type | Description |
|---|---|---|
| ctas | CTA[] | Call-to-action buttons for the engagement section |
| links | Link[] | Supporting links for decks, docs, routes, or email actions |
{ "proposal": { "id": "...", "links": [...], "ctas": [...], ... } }Replace the timeline phases for a proposal.
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
| Field | Type | Description |
|---|---|---|
| timelinePhases | Phase[] | Array of { name, duration, summary, deliverables, viewMode } objects |
| viewMode | LIST | MILESTONE | Preferred timeline presentation mode |
{ "proposal": { "id": "...", "timelinePhases": [...], ... } }Update costing line items for a proposal.
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
| Field | Type | Description |
|---|---|---|
| costLineItems | CostItem[] | Array of costing rows with quantity, rate, and subtotal data |
{ "proposal": { "id": "...", "costLineItems": [...], ... } }Create an export record for print, PDF, or share-link output.
| Name | Type | Description |
|---|---|---|
| id | string | Proposal CUID |
| Field | Type | Description |
|---|---|---|
| format | PRINT | PDF | SHARE_LINK | Export format to prepare |
| settings | object | Optional export settings persisted on the export record |
{ "export": { "id": "...", "format": "PDF", "status": "PENDING", "url": "/app/docs/:id/print", "requestedAt": "..." } }List the shared People & Rates roster used by Axis and other connected clients.
{ "people": [{ "id": "...", "workspaceId": "...", "seedIdentifier": "gitwork.aashir-awan", "name": "Aashir Awan", "area": "Senior • Flutter, Frontend, Backend, DevOps", "sourceRate": 1900, "sourceCurrencyCode": "USD", "billingPeriod": "MONTH", "archivedAt": null, "createdAt": "...", "updatedAt": "..." }] }Supports optional query params `search` and `includeArchived=true`.
Create a new shared People & Rates roster entry.
| Field | Type | Description |
|---|---|---|
| name | string | Display name for the person |
| area | string | Discipline, specialty, or role summary |
| sourceRate | number | Stored source rate in the source currency |
| sourceCurrencyCode | string | 3-letter ISO currency code such as USD or GBP |
| billingPeriod | DAY | WEEK | MONTH | Source billing period used to interpret the stored rate |
{ "person": { "id": "...", "name": "New Person", "area": "Design", "sourceRate": 650, "sourceCurrencyCode": "GBP", "billingPeriod": "DAY", "archivedAt": null, "createdAt": "...", "updatedAt": "..." } }Fetch a single People & Rates roster entry.
| Name | Type | Description |
|---|---|---|
| id | string | Rate-card person CUID |
{ "person": { "id": "...", "name": "...", "area": "...", "sourceRate": 650, "sourceCurrencyCode": "GBP", "billingPeriod": "DAY", "archivedAt": null, "createdAt": "...", "updatedAt": "..." } }Update one or more fields on a People & Rates roster entry.
| Name | Type | Description |
|---|---|---|
| id | string | Rate-card person CUID |
| Field | Type | Description |
|---|---|---|
| name | string | Updated display name |
| area | string | Updated discipline or role summary |
| sourceRate | number | Updated source rate |
| sourceCurrencyCode | string | Updated 3-letter ISO currency code |
| billingPeriod | DAY | WEEK | MONTH | Updated source billing period |
{ "person": { "id": "...", "name": "...", "area": "...", "sourceRate": 700, "sourceCurrencyCode": "USD", "billingPeriod": "WEEK", "archivedAt": null, "createdAt": "...", "updatedAt": "..." } }Archive a People & Rates roster entry without removing its history.
| Name | Type | Description |
|---|---|---|
| id | string | Rate-card person CUID |
{ "person": { "id": "...", "archivedAt": "2026-03-31T15:00:00.000Z", ... } }Get Code dashboard metrics, stage counts, re-check totals, and recent activity.
{ "total": 6, "byStatus": [{ "status": "SOURCED", "count": 1 }, { "status": "CODECLEAR_COMPLETE", "count": 1 }], "avgThis": 90, "avgLast": 82, "passRateThis": 100, "recheckDue": 1, "recentActivity": [{ "id": "...", "eventType": "SCORE_FINALIZED", "createdAt": "..." }] }List developers with filters, score ranges, and facets for building the pipeline UI.
| Name | Type | Description |
|---|---|---|
| q | string | Search by name, GitHub handle, email, or stack |
| status | PipelineStatus | Filter by sourcing / invited / assessment / verified / placed / re-check due |
| tier | CodeClearTier | Filter by Tier 1 / Tier 2 / Tier 3 |
| identityConfidence | IdentityConfidence | Filter by HIGH / MEDIUM / LOW / PENDING |
| recheckDue | ANY | SOON | OVERDUE | Filter candidates with a scheduled re-check |
| stack | string | Filter by primary stack |
| sortBy | createdAt | updatedAt | name | status | recheckDueAt | overallScore | Sort field |
| sortDir | asc | desc | Sort direction |
{ "items": [{ "id": "...", "name": "Sindre Sorhus", "githubHandle": "sindresorhus", "status": "CODECLEAR_COMPLETE", "tier": "TIER_1", "primaryStack": "TypeScript", "analysisState": "COMPLETE", "score": { "overallScore": 90 } }], "meta": { "page": 1, "pageSize": 20, "total": 6, "totalPages": 1, "sortBy": "updatedAt", "sortDir": "desc" }, "facets": { "stacks": ["Node.js", "React", "TypeScript"] } }Create a new developer in the shared Gitwork workspace.
| Field | Type | Description |
|---|---|---|
| name | string | Candidate display name |
| githubHandle | string | GitHub username without the leading @ |
| primaryStack | string | Primary technical discipline or stack |
| string | Email address | |
| location | string | Location |
| bio | string | Short candidate summary |
| tier | CodeClearTier | Tier assignment |
| rateCardPersonId | string | Optional People & Rates roster link |
{ "candidate": { "id": "...", "name": "New Candidate", "githubHandle": "new-user", "status": "SOURCED", "tier": "TIER_1", "analysisState": "NEVER_RUN" } }Bulk-update developers by moving stages or flagging a re-check.
| Field | Type | Description |
|---|---|---|
| action | MOVE_STAGE | FLAG_RECHECK | Bulk action mode |
| ids | string[] | Candidate IDs to update |
| status | PipelineStatus | Required for MOVE_STAGE |
| recheckDueAt | ISO datetime | Optional re-check due date for FLAG_RECHECK |
{ "candidates": [{ "id": "...", "status": "RECHECK_DUE" }] }Get a single developer including notes, placements, activity, scores, and GitHub runs.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
{ "candidate": { "id": "...", "name": "...", "score": { "overallScore": 90 }, "scoreDraft": null, "githubAnalysisRuns": [], "placements": [], "notes": [], "activityLog": [] } }Update the profile, stage, tier, optional re-check date, or People & Rates link for a developer.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
| Field | Type | Description |
|---|---|---|
| name | string | Updated display name |
| githubHandle | string | Updated GitHub username |
| status | PipelineStatus | Updated pipeline stage |
| tier | CodeClearTier | Updated tier |
| recheckDueAt | ISO datetime | Re-check date |
{ "candidate": { "id": "...", "status": "INVITED", "tier": "TIER_2" } }Delete a developer and its linked notes, activity, scores, runs, and placements.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
{ "ok": true }Attach a note to a developer timeline.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
| Field | Type | Description |
|---|---|---|
| body | string | Note content |
{ "note": { "id": "...", "candidateId": "...", "body": "Strong fit for platform work.", "createdBy": "Gitwork Owner", "createdAt": "..." } }Finalize a score from manual review or the current draft values.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
| Field | Type | Description |
|---|---|---|
| technicalDepth | 0-100 | Technical depth score |
| codeQuality | 0-100 | Code quality score |
| aiFluency | 0-100 | AI fluency score |
| deliveryReadiness | 0-100 | Delivery readiness score |
| identityConfidence | IdentityConfidence | Identity confidence |
| taskScore | 0-100 | Optional task score |
| taskTimeSeconds | number | Optional task duration in seconds |
| taskAiReview | string | Reviewer note |
{ "candidate": { "id": "...", "status": "CODECLEAR_COMPLETE", "score": { "overallScore": 86, "verifiedAt": "...", "validUntil": "..." } } }List GitHub analysis runs captured for a developer.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
{ "runs": [{ "id": "...", "status": "COMPLETED", "analysisVersion": "docs-codeclear-v1", "startedAt": "...", "completedAt": "...", "metrics": { "averageHealthScore": 84 } }] }Run a fresh public GitHub analysis and store the snapshot on the candidate.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
{ "run": { "id": "...", "status": "COMPLETED", "recommendedTechnicalDepth": 88, "recommendedCodeQuality": 84, "recommendedDeliveryReadiness": 80, "llmSummary": "..." }, "candidate": { "id": "...", "avatarUrl": "..." } }Uses the candidate's `githubHandle` and optionally `GITHUB_TOKEN` for higher GitHub API limits.
Apply a completed GitHub analysis run to the candidate's score draft.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
| runId | string | GitHub analysis run CUID |
{ "candidate": { "id": "...", "scoreDraft": { "overallScore": 82, "sourceRunId": "..." } }, "run": { "id": "...", "status": "COMPLETED" } }Download a generated PDF scorecard for a developer.
| Name | Type | Description |
|---|---|---|
| id | string | Candidate CUID |
Binary PDF response
Returns `application/pdf` with a generated scorecard filename.
List all proposal templates.
{ "templates": [{ "id": "...", "name": "...", "description": "..." }] }Proof service status endpoint.
{ "error": "Proof service is disabled in POC mode.", "baseUrl": null }Returns 503 until the Proof service is enabled.
Proof document API placeholder.
{ "error": "Proof API is disabled in POC mode. Use the client-side draft workspace instead." }Current GET and POST requests return 501 until the Proof service is wired back in.
DRAFT → Initial state PRODUCT_SIGN_OFF → Awaiting product approval TECH_SIGN_OFF → Awaiting technical approval IN_REVIEW → Under client review APPROVED → Approved by all parties SENT → Delivered to client ARCHIVED → Archived / no longer active