---
title: "Save the accepted app source profile"
method: POST
path: "/projects/{id}/app-source"
---

# Save the accepted app source profile

`POST /projects/{id}/app-source`

## Request

- Base URL: `https://api.eurobase.dev`
- URL: `https://api.eurobase.dev/projects/{id}/app-source`
- Auth: none declared

## Path parameters

- `id` string, required

## Request body

- ProjectAppSourceSaveRequest
  - `repoId` string
  - `repoFullName` string
  - `branch` string
  - `rootDir` string
  - `rootDirectory` string
  - `rootCandidates` string[]
  - `rootCandidateSetHash` string, nullable
  - `rootChoiceRequired` boolean
  - `rootChoiceConfirmed` boolean
  - `port` integer, nullable
  - `healthPath` string, nullable
  - `appRuntimeTierId` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge' | 'null', nullable
  - `serviceType` 'web_service' | 'static_site'
  - `buildCommand` string, nullable
  - `startCommand` string, nullable
  - `publishDirectory` string, nullable
  - `sourceBuildEngineChange` SourceBuildEngineChange: Explicit confirmation of a project runtime switch (ADR 0076 D2), applied as compare-and-set under the project row lock: from is the stored engine and to the engine detected for the admitted commit. Refused on redeploys and never read from pushes.
    - `from` 'direct-static-v1' | 'paketo-v1' | 'workers-v1', required
    - `to` 'direct-static-v1' | 'paketo-v1' | 'workers-v1', required

## Response `200`

Saved app source profile

- ProjectAppSourceResponse
  - `project` ProjectSummary, required
    - `id` string, required
    - `name` string, nullable
    - `organizationId` string, nullable
    - `projectMembershipId` string, nullable
    - `projectRole` 'owner' | 'admin' | 'contributor' | 'null', nullable
    - `projectSlug` string, nullable
    - `projectHostname` string, nullable
    - `primaryHostname` string, nullable: Official address of the project: its active custom domain whose DNS points at Eurobase, the one that went live first when several do, otherwise projectHostname. projectHostname stays reserved and keeps serving.
    - `deploymentMode` 'runtime' | 'static', required
    - `lifecycleState` string, nullable
    - `deleteRequestedAt` string, date-time, nullable
    - `projectRoute` ProjectRoute, required
      - `status` 'healthy' | 'repairing' | 'degraded' | 'broken' | 'unknown', required
      - `reasonCode` 'none' | 'dns_record_missing' | 'dns_propagating' | 'domain_binding_missing' | 'tls_pending' | 'missing_project_upstream' | 'upstream_unreachable' | 'ingress_unreachable' | 'unmanaged_custom_domain' | 'scw_mutation_failed', required
      - `checkedAt` string, date-time, nullable
      - `lastRepairAt` string, date-time, nullable
      - `lastError` string, nullable
      - `managed` boolean, required
      - `convergenceState` 'recovering' | 'exhausted' | 'ready' | 'null', nullable
      - `upstream` ProjectUpstreamState, required
        - `status` 'healthy' | 'broken' | 'unknown', required
        - `reasonCode` 'none' | 'missing_project_upstream' | 'upstream_unreachable', required
        - `checkedAt` string, date-time, nullable
        - `lastError` string, nullable
    - `releaseUsability` ReleaseUsability, required
      - `status` 'reachable' | 'degraded' | 'blocked' | 'unknown', required
      - `reasonCode` 'none' | 'missing_live_release' | 'access_not_allowed' | 'route_repair_in_progress' | 'route_incident' | 'project_suspended', required
      - `lastLiveDeploymentId` string, nullable, required
    - `projectSummaryStatus` ProjectSummaryStatus
      - `label` string, required
      - `tone` 'neutral' | 'problem' | 'error', required
      - `code` 'setup_required' | 'route_issue' | 'deploy_failed' | 'deploy_unhealthy' | 'live_release_blocked' | 'status_check_delayed' | 'deploy_in_progress' | 'rollback_live' | 'healthy' | 'suspended', required
      - `detailTitle` string, nullable, required
      - `detail` string, nullable, required
    - `servingSuspension` ProjectServingSuspension: An operator suspension of the project's public serving (ADR 0080). Operator notes and evidence are never included.
      - `state` 'suspended', required
      - `reasonCategory` 'phishing' | 'malware' | 'shared_domain_abuse' | 'spam' | 'illegal_content' | 'legal_order' | 'other_policy_violation', required
      - `reasonLabel` string, required
      - `since` string, date-time, nullable, required
      - `supportEmail` string, required
      - `policyUrl` string, required
    - `sourceProfile` ProjectSourceProfileSummary, required
      - `framework` 'next' | 'astro' | 'svelte-kit' | 'nuxt' | 'react-router' | 'vite' | 'hono' | 'nestjs' | 'fastify' | 'express' | 'django' | 'fastapi' | 'flask' | 'laravel' | 'rails' | 'node' | 'python' | 'php' | 'ruby' | 'go' | 'java' | 'dotnet' | 'static', required
      - `frameworkLabel` string, required
      - `outputMode` 'runtime' | 'static', required
    - `sourceLock` ProjectSourceLock: ADR 0090: while locked, no caller can change the project repository, branch, root directory or deployment mode.
      - `locked` boolean, required
      - `lockedAt` string, date-time, nullable, required
  - `appRepo` AppRepo
    - `repoId` string, required
    - `repoName` string, nullable
    - `repoFullName` string, required
    - `branch` string, required
    - `rootDir` string, required
    - `runCommand` string, required
    - `healthPath` string, required
    - `containerPort` integer, required
    - `deploymentMode` 'runtime' | 'static', required
  - `appRuntimeTier` AppRuntimeTier
    - `code` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge', required
    - `label` string, required
    - `cpu` string
    - `memory` string
    - `limitsKnown` boolean
    - `cpuMillicores` integer, nullable
    - `memoryMb` integer, nullable
    - `minScale` integer, nullable, required
    - `maxScale` integer, nullable, required
    - `burnMultiplier` string, nullable
    - `workloadGuidance` string, nullable
    - `equivalentIncludedRuntimeHours` string, nullable
    - `selectable` boolean
    - `unavailableReason` string, nullable
    - `recoveryAction` string, nullable
    - `configurable` boolean, required
  - `appRuntimeTierOptions` ProjectContainerRuntimeTier[]
    - `code` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge' | 'existing-unmanaged', required
    - `label` string, required
    - `limitsKnown` boolean, required
    - `cpuMillicores` integer, nullable, required
    - `memoryMb` integer, nullable, required
    - `minScale` integer, nullable, required
    - `maxScale` integer, nullable, required
    - `burnMultiplier` string, nullable
    - `workloadGuidance` string, nullable
    - `equivalentIncludedRuntimeHours` string, nullable
    - `unavailableReason` string, nullable
    - `recoveryAction` string, nullable
    - `selectable` boolean, required
  - `defaultAppRuntimeTierCode` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge' | 'null', nullable
  - `appRuntimeTierPolicyState` object, nullable
    - `status` 'ready' | 'blocked' | 'unavailable', required
    - `reasonCode` string, nullable
    - `recoveryAction` string, nullable
  - `planRuntimeAllowance` object, nullable
    - `smallEquivalentHours` string, required
    - `maxScale` integer, required
  - `appSourceProfile` AppSourceProfile, required
    - `sourceType` 'git_repo', required
    - `repository` object, nullable, required
      - `id` string, nullable
      - `name` string, nullable
      - `fullName` string, nullable
    - `branch` string, required
    - `rootDirectory` string, required
    - `rootCandidates` string[], required
    - `rootCandidateSetHash` string, nullable
    - `rootChoiceRequired` boolean, required
    - `rootChoiceConfirmed` boolean, required
    - `sourceBuildEngine` 'direct-static-v1' | 'paketo-v1' | 'workers-v1', required
    - `directStatic` boolean, required
    - `framework` 'next' | 'astro' | 'svelte-kit' | 'nuxt' | 'react-router' | 'vite' | 'hono' | 'nestjs' | 'fastify' | 'express' | 'django' | 'fastapi' | 'flask' | 'laravel' | 'rails' | 'node' | 'python' | 'php' | 'ruby' | 'go' | 'java' | 'dotnet' | 'static' | 'unknown', required
    - `frameworkLabel` string, required
    - `outputMode` 'runtime' | 'static', required
    - `appRuntimeTierId` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge' | 'null', nullable
    - `port` integer, nullable
    - `healthPath` string, nullable
    - `appRuntimeTier` AppRuntimeTier
      - `code` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge', required
      - `label` string, required
      - `cpu` string
      - `memory` string
      - `limitsKnown` boolean
      - `cpuMillicores` integer, nullable
      - `memoryMb` integer, nullable
      - `minScale` integer, nullable, required
      - `maxScale` integer, nullable, required
      - `burnMultiplier` string, nullable
      - `workloadGuidance` string, nullable
      - `equivalentIncludedRuntimeHours` string, nullable
      - `selectable` boolean
      - `unavailableReason` string, nullable
      - `recoveryAction` string, nullable
      - `configurable` boolean, required
    - `detection` AppSourceDetection, required
      - `status` 'not_requested' | 'pending' | 'detected' | 'needs_review' | 'failed' | 'unavailable', required
      - `reason` 'none' | 'no_match' | 'ambiguous' | 'cap_exceeded' | 'timeout' | 'rate_limited' | 'repo_access_unavailable' | 'detector_error', required
      - `confidence` 'high' | 'medium' | 'low' | 'unknown', required
      - `detectedAt` string, date-time, nullable
      - `commitSha` string, nullable
      - `treeSha` string, nullable
      - `detectorVersion` string, nullable, required
      - `evidence` AppSourceDetectionEvidence[], required
        - `path` string, required
        - `reason` string, required
      - `warnings` string[], required
    - `overrideState` 'auto' | 'custom_override' | 'detected_but_unconfirmed', required
    - `canDeploy` boolean, required
    - `blockedReason` string, nullable
    - `blockedMessage` string, nullable
    - `sourceRuntime` 'ruby' | 'dotnet' | 'go' | 'python' | 'php' | 'java' | 'node' | 'null', nullable
    - `serviceType` 'web_service' | 'static_site' | 'null', nullable
    - `packageManager` 'npm' | 'yarn' | 'null', nullable
    - `buildCommand` string, nullable
    - `startCommand` string, nullable
    - `publishDirectory` string, nullable
    - `sourceBuild` AppSourceBuildPlan
      - `runtime` string, nullable, required
      - `packageManager` string, nullable, required
      - `blockedReason` string, nullable, required
      - `procfileWeb` string, nullable, required
      - `scripts` string[], required
      - `startRequired` boolean, required
      - `buildAvailable` boolean, required
      - `startLooksLikeDevServer` boolean
      - `defaults` object, required
        - `serviceType` 'web_service' | 'static_site', required
        - `buildCommand` string, nullable, required
        - `startCommand` string, nullable, required
        - `publishDirectory` string, nullable, required
    - `buildHints` object, nullable
      - `runtime` string, nullable
      - `pythonVersion` string, nullable
      - `nodeVersion` string, nullable
      - `nodeLaunchpoint` string, nullable
  - `detectedAppSourceProfile` AppSourceProfile
    - `sourceType` 'git_repo', required
    - `repository` object, nullable, required
      - `id` string, nullable
      - `name` string, nullable
      - `fullName` string, nullable
    - `branch` string, required
    - `rootDirectory` string, required
    - `rootCandidates` string[], required
    - `rootCandidateSetHash` string, nullable
    - `rootChoiceRequired` boolean, required
    - `rootChoiceConfirmed` boolean, required
    - `sourceBuildEngine` 'direct-static-v1' | 'paketo-v1' | 'workers-v1', required
    - `directStatic` boolean, required
    - `framework` 'next' | 'astro' | 'svelte-kit' | 'nuxt' | 'react-router' | 'vite' | 'hono' | 'nestjs' | 'fastify' | 'express' | 'django' | 'fastapi' | 'flask' | 'laravel' | 'rails' | 'node' | 'python' | 'php' | 'ruby' | 'go' | 'java' | 'dotnet' | 'static' | 'unknown', required
    - `frameworkLabel` string, required
    - `outputMode` 'runtime' | 'static', required
    - `appRuntimeTierId` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge' | 'null', nullable
    - `port` integer, nullable
    - `healthPath` string, nullable
    - `appRuntimeTier` AppRuntimeTier
      - `code` 'euro-small' | 'euro-medium' | 'euro-large' | 'euro-xlarge', required
      - `label` string, required
      - `cpu` string
      - `memory` string
      - `limitsKnown` boolean
      - `cpuMillicores` integer, nullable
      - `memoryMb` integer, nullable
      - `minScale` integer, nullable, required
      - `maxScale` integer, nullable, required
      - `burnMultiplier` string, nullable
      - `workloadGuidance` string, nullable
      - `equivalentIncludedRuntimeHours` string, nullable
      - `selectable` boolean
      - `unavailableReason` string, nullable
      - `recoveryAction` string, nullable
      - `configurable` boolean, required
    - `detection` AppSourceDetection, required
      - `status` 'not_requested' | 'pending' | 'detected' | 'needs_review' | 'failed' | 'unavailable', required
      - `reason` 'none' | 'no_match' | 'ambiguous' | 'cap_exceeded' | 'timeout' | 'rate_limited' | 'repo_access_unavailable' | 'detector_error', required
      - `confidence` 'high' | 'medium' | 'low' | 'unknown', required
      - `detectedAt` string, date-time, nullable
      - `commitSha` string, nullable
      - `treeSha` string, nullable
      - `detectorVersion` string, nullable, required
      - `evidence` AppSourceDetectionEvidence[], required
        - `path` string, required
        - `reason` string, required
      - `warnings` string[], required
    - `overrideState` 'auto' | 'custom_override' | 'detected_but_unconfirmed', required
    - `canDeploy` boolean, required
    - `blockedReason` string, nullable
    - `blockedMessage` string, nullable
    - `sourceRuntime` 'ruby' | 'dotnet' | 'go' | 'python' | 'php' | 'java' | 'node' | 'null', nullable
    - `serviceType` 'web_service' | 'static_site' | 'null', nullable
    - `packageManager` 'npm' | 'yarn' | 'null', nullable
    - `buildCommand` string, nullable
    - `startCommand` string, nullable
    - `publishDirectory` string, nullable
    - `sourceBuild` AppSourceBuildPlan
      - `runtime` string, nullable, required
      - `packageManager` string, nullable, required
      - `blockedReason` string, nullable, required
      - `procfileWeb` string, nullable, required
      - `scripts` string[], required
      - `startRequired` boolean, required
      - `buildAvailable` boolean, required
      - `startLooksLikeDevServer` boolean
      - `defaults` object, required
        - `serviceType` 'web_service' | 'static_site', required
        - `buildCommand` string, nullable, required
        - `startCommand` string, nullable, required
        - `publishDirectory` string, nullable, required
    - `buildHints` object, nullable
      - `runtime` string, nullable
      - `pythonVersion` string, nullable
      - `nodeVersion` string, nullable
      - `nodeLaunchpoint` string, nullable
  - `sourceConfirmation` ProjectSourceConfirmation
    - `repository` string, required
    - `branch` string, required
    - `rootDirectory` string, required
    - `configurationHash` string, required: API-owned binding of the saved source defaults, excluding detector caches and unrelated project updates.
  - `runtimeSelection` RuntimeSelection: The project runtime plan for one commit. detected: no runtime is stored yet and this commit selects it; confirmed: the commit matches the stored runtime; change-required: the commit needs the detected runtime and deploys only after an explicit sourceBuildEngineChange; stored-engine-blocked: this commit cannot deploy, and blocker carries its reason: either the stored runtime cannot admit it, or a build Job already detected it as a Workers app (detectedEngine workers-v1) that cannot run, which is refused with its fix and never built on Paketo. detectedEngine workers-v1 without a stored runtime is the route: the Workers build Job detects the runtime before any user code runs, then builds on Workers, builds the same deployment on Paketo, or refuses it. Warnings (from the last build Job detection for this commit, and client-written-cookies from the plan read) never block the deploy.
    - `storedEngine` 'direct-static-v1' | 'paketo-v1' | 'workers-v1' | 'null', nullable, required
    - `detectedEngine` 'direct-static-v1' | 'paketo-v1' | 'workers-v1' | 'null', nullable, required
    - `commitSha` string, nullable, required
    - `state` 'detected' | 'confirmed' | 'change-required' | 'changed' | 'stored-engine-blocked', required
    - `detectedBlockedReason` string, nullable
    - `blocker` object
      - `reason` string, required
      - `message` string, required: Owner-facing copy; a command inside it is delimited by backticks.
      - `fixCommand` string, nullable: The one command that fixes a Workers refusal in the repository, when one exists.
      - `evidence` object[], required
        - `path` string
        - `reason` string
    - `warnings` object[]: Warnings for a deployable plan; the deploy proceeds. Workers detection warnings, then one `client-written-cookies` warning per distinct fix for the Root dependencies that write a cookie in the browser for the server to read.
      - `code` 'adapter-compatibility-unverified' | 'client-written-cookies' | 'framework-version-end-of-life' | 'framework-version-vulnerable' | 'package-manager-version-substituted', required
      - `message` string, required: Owner-facing copy; a command or code inside it is delimited by backticks.
      - `fixCommand` string, nullable, required
      - `docsPath` string: Eurobase docs page that explains the warning, as a path on the web app origin.

## Other responses

- `400`: Invalid app source save request
- `409`: App source detection or runtime policy blocks save, or the project source is locked (project-source-locked). runtime-detection-changed means the commit needs a runtime other than the stored one; resend with sourceBuildEngineChange {from: stored, to: detected} to switch. A direct-static-* reason is the stored runtime blocker when the detected runtime cannot deploy the commit either.
- `422`: App source validation failed
- `503`: Workers builds are temporarily unavailable: the live Source Builder supply cannot yet detect the Workers runtime in the build Job (reason workers-detection-unavailable); nothing is saved

---

[API](https://skmtc.dev/eurobase/apis/eurobase-api.md) · [All operations](https://skmtc.dev/eurobase/apis/eurobase-api/llms.txt) · [OpenAPI document](https://skmtc.dev/eurobase/apis/eurobase-api/revisions/5266a299d18a?raw)
